1
votes

This question seems fairly simple, but I wasn't able to find another post that answers it (apologies if I've missed it though).

I have a variable with three factors (a value for each month). The data looks like the below:

id  variable value
AZ   Feb-20  1085
AZ   Mar-20     1
AZ   Apr-20    61
CO   Feb-20     6
CO   Mar-20   192
FO   Apr-20     2

I want to stack the data, such that I have a bar for February, and then the marginal increases for March, and April stacked on top.

Right now, the values for each month are stacked on top of each other.

ggplot(df3, aes(x = id, y = value, fill=factor(variable, levels=c("Apr-20","Mar-20", "Feb-20")))) + geom_bar(stat = "identity") 

enter image description here

How do I stack the increases from February? Is there a way to modify a stacked bar plot or do I need to try another method?

EDIT

After thinking on this, I believe the best solution is overlapping bars. But higher bars cover smaller bars. Changing the transparency isn't very useful with three factors. Maybe there is a way to reorder so that the smaller bars are in the forefront?

ggplot(df2) +geom_bar(aes(x = id, y = `Feb-20`), position = "identity",stat="identity", fill = 'green') +
  geom_bar(aes(x = id, y = `Mar-20`), position = "identity", stat="identity",fill = 'navy') +
  geom_bar(aes(x = id, y = `Apr-20`), position = "identity", stat="identity", fill = 'red') 

enter image description here

Second Edit Apologies, this is my fault for being unclear. Prior, I wanted to avoid the cumulative summing that occurs with stacked barplots, and asked that each additional month be added as a marginal increase.

Now, though, as overlapping barplots, it is not necessary for the bars to display change. The problem with the overlapping bar charts is just that the data is obscured for bars with a shorter height.

This plot still plots marginal change. I'm looking for something like plot 2 in this post, but where all of the data is visible.

enter image description here

EDIT 3

Maybe this is a better way to explain:

Take the example of 'WA' in the first plot. For Feb, the data point was 338, for March, the data point was 318, and for April, the data point was 2270. A stacked bar plot adds these on top of each other, cumulatively.

However, the bar that I want for 'WA' should really show 338 for February, then a drop of 20 for March. And finally, an addition of 1952 for April.

This is why I had used the language of a marginal increase/decrease for a stacked barplot. I had also tried an overlapping barplot, but all of the data is not visible, and longer bars cover shorter bars.

1
Do you want to order the barsakrun
Yes, so that for each id, the order from the baseline to top (ie, from left to right) is Feb-20, Mar-20, Apr-20.Yu Na
How would you show a marginal decrease? Do you want the bars to be stacked or not? You appear to be saying both.Axeman
Do you need df1 %>% arrange(id, as.yearmon(variable, '%b-%y')) %>% mutate(variable = factor(variable, levels = unique(variable))) %>% ggplot(aes(x = id, y = value, fill = variable)) + geom_bar(stat = "identity")akrun
@akrun Thank you for your help, if you post it as a solution, I'm happy to accept. If you have any advice as to how to reorder the bars so the smallest are visible too, I'd appreciate it. But I will still accept the current commentYu Na

1 Answers

0
votes

We can arrange based on converting the column to yearmon class (from zoo), then convert to factor with levels specified as the unique elements (or do a match and convert)

library(dplyr)
library(zoo)
library(ggplot2)
df1 %>%
    arrange(id, as.yearmon(variable, '%b-%y')) %>% 
    mutate(variable = factor(variable, levels = unique(variable))) %>% 
    ggplot(aes(x = id, y = value, fill = variable)) + 
        geom_bar(stat = "identity") 

If we wanted to automate the second plot

library(tidyr)


df2 <- df1 %>% 
       pivot_wider(names_from = variable, values_from = value)


p <- ggplot(df2)

colrs <- c('green', 'navy', 'red')
nm1 <- names(df2)[-1]
for(i in seq_along(nm1)) p <- p + 
          geom_bar(aes(x = id, y = !! rlang::sym(nm1[i])), 
          position = 'identity', stat = 'identity', fill = colrs[i])