rggplot2bar-chartgrouped-bar-chart

A problem with an stacked, grouped and faceted graph y gg plot


I'm trying to create a graph. Here is the code for the data:

ea3 <- ddply(dias_semana, c("mes","weekday", "member_casual", "rideable_type"), summarise, n = sum(n))

ea3$rideable_type <- factor(ea3$rideable_type, levels = c("classic_bike", "electric_bike"))

ea3$fill_var <- factor(interaction(ea3$member_casual, ea3$rideable_type), 
                      levels = c("casual.classic_bike", "casual.electric_bike",
                                "member.classic_bike", "member.electric_bike"))

And here is the ggplot code.

theme_set(theme_bw(base_size = 12))
plot_diassem_m_mc = ggplot(ea3, aes(x=factor(weekday, 
                                   level = c("lunes","martes","miércoles", 
                                             "jueves","viernes","sábado",
                                             "domingo")), y = n, fill=fill_var)) +
  geom_bar(stat = "identity", position=position_dodge(), width = 0.7)+
  theme(plot.title=element_text(size=11))+
  theme(axis.text.x=element_blank(), 
        axis.ticks.x=element_blank())+
  theme(axis.title=element_text(size=10))+
  theme(axis.text.y=element_text(size=8))+
  theme(legend.title=element_blank())+
  labs(title = "Gráfico 11. Número de viajes por cada día de la semana, según mes",
       x = "",
       y = "")+
  facet_wrap(~mes)+
  theme(strip.text = element_text(size = 7, color = "dark green"))+
  theme(legend.key.height= unit(0.2, 'cm'),
        legend.key.width= unit(0.3, 'cm'),
        legend.text = element_text(size=9))+
  scale_fill_discrete(labels=c('casuales (bici clásica)', 'casuales (bici eléctrica)', 
                               'miembros (bici clásica)', 'miembros (bici eléctrica)'))
print(plot_diassem_m_mc)

The result is this graph:

enter image description here

In this graph, we have 12 months. In each months there are four bars for each day of the week. The four bars on the far left have values for Monday and the ones on the far right are for Sunday. The other ones belong to the other days of the week. So, I want two bars instead of four. One bar for casual and the other for member (column member_casual). Then, I want to divide each bar in two parts: one for classic bike and one for electric bike (each part should have a different color). In the end, I want a graph with two bars for each day of the week, and each bar should have two different colors because of the classic and electric bike division.

Please, I ask your help with this. Thanks in advance.


Solution

  • I can only think of doing this with a lot of manual calculations and geom_rect(). Each day is given an integer value and then the rectangle is shifted left or right depending on the value of casual_member and the rectangle is shifted up if the value is elec. Obviously, this is just a sketch. I left the intermediate printing of DF as comments. Using those may help you understand how the data frame is built up. I invented a small data set since you didn't post any data.

    library(tidyverse)
    DF <- data.frame(Month = rep(c("Feb", "Mar"), each = 8),
                     Day = rep(c("Mon", "Tues"), 8),
                     casual_member =rep(rep(c("casual", "member"),each=4),2),
                     Elec = rep(c("classic", "classic", "elec", "elec"), 4),
                     Value = c(23,14,10,25,22,16,8,19,20,7,15,21,17,10,18,9))
    #DF
    DF <- DF |> mutate(JoinValue = ifelse(Elec == "classic", "elec", "classic"))
    #DF
    DF <- inner_join(DF, DF, by = c("Month", "casual_member", "Day", Elec = "JoinValue"))
    #DF
    DF <- DF |> mutate(ymin = ifelse(Elec == "classic", 0, Value.y),
                 ymax = ifelse(Elec == "classic", Value.x, Value.x + Value.y),
                 x_center = case_when(
                   Day == "Mon" ~ 1,
                   Day == "Tues" ~ 2
                 ),
                 x_shift = case_when(
                   casual_member == "casual" ~ -0.2,
                   TRUE ~ 0.2
                 ),
                 X = x_center + x_shift)
    
    #DF
    ggplot(DF, aes(xmin = X - 0.2, xmax = X + 0.2, ymin = ymin, ymax = ymax, 
                   fill = interaction(Elec, casual_member))) + geom_rect() +
      facet_wrap(~Month) +
      scale_x_continuous(breaks = c(1,2), labels = c("Mon", "Tues")) +
      labs(fill = "Categories")
    

    Created on 2024-10-09 with reprex v2.1.1