Home > OS >  Is it possible to put all grouping values in a facet_grid below the labels of the x axis?
Is it possible to put all grouping values in a facet_grid below the labels of the x axis?

Time:04-06

I'm using gglplot2 for creating graphics.

According to the user manual of facet_grid the switch parameter does the following :

switch: By default, the labels are displayed on the top and right of the plot. If '"x"', the top labels will be displayed to the bottom. If '"y"', the right-hand side labels will be displayed to the left. Can also be set to '"both"'.

I would like to know whether it is possible that in a facet using two variables for grouping values, put both variables on bottom, that is below the labels of the x axis. I mean instead of

 
                                2
                                0
                                2
                                2
              march

Is it possible to have

 
                             
                             
                             
                             
              march
              2022

This is actually how I often create bar charts in Excel/Calc and I find it to be much more readable.

Here is my test case :

Dataframe to be used for the graphic

df_graph_data <- data.frame(
    year = rep.int(rep.int("2022", times = 28), times = 4),
    month = rep.int(rep.int("march", times = 28), times = 4),
    day_number = rep.int(seq_len(28), times = 4),
    user_name = rep.int(
        c(
            rep.int("all users", times = 28),
            rep.int("user1", times = 28),
            rep.int("user2", times = 28),
            rep.int("user3", times = 28)
        ),
        times = 4
    ),
    nbr_requetes = c(
        3756702L, 2147114L, 3931021L, 3250020L,
        2902070L, 1807425L, 2793984L, 2923112L,
        3240588L, 2965146L, 2778786L, 1915146L,
        1945332L, 2763420L, 2948967L, 2953477L,
        3056854L, 3005814L, 2252867L, 2503640L,
        2574102L, 1525419L, 1694105L, 2796715L,
        2448590L, 1571465L, 1641066L, 2406683L,
        358992L, 294093L, 264117L, 164634L,
        132962L, 147587L, 211403L, 187508L,
        249445L, 309832L, 295148L, 114369L,
        178935L, 229215L, 108168L, 202477L,
        268470L, 301246L, 199027L, 281434L,
        216888L, 135288L, 196308L, 219157L,
        111560L, 73738L, 112145L, 177282L,
        349976L, 146039L, 404627L, 443312L,
        298097L, 294996L, 317332L, 389586L,
        308677L, 313986L, 300024L, 309731L,
        270230L, 310996L, 355700L, 312721L,
        371876L, 303862L, 293709L, 275199L,
        287980L, 148739L, 172012L, 363912L,
        300369L, 299126L, 280704L, 326646L,
        642780L, 350965L, 633404L, 432376L,
        119252L, 109750L, 519688L, 546885L,
        507847L, 489425L, 460825L, 168577L,
        163430L, 505327L, 515003L, 498683L,
        492875L, 441591L, 198819L, 188225L,
        513477L, 390207L, 400769L, 493959L,
        458977L, 166925L, 151197L, 558081L
    )
)
df_graph_data$user_name <- factor(df_graph_data$user_name, ordered = TRUE, levels = c("all users", "user1", "user2", "user3"))

Code for the graphic

library("tidyverse")
options(device = "windows")
###
###
require(scales)
ggplot(data = df_graph_data)   
  geom_bar(mapping = aes(
    x = day_number,
    y = nbr_requetes,
    fill = user_name
  ), 
  position = "dodge",
  stat = "identity"
  )  
  scale_x_continuous(
    breaks=seq(
      min(df_graph_data$day_number), 
      max(df_graph_data$day_number), 
      by = 1L),
    labels = stringr::str_pad(
      unique(df_graph_data$day_number), 
      width = 2, 
      pad = "0"
    )
  )   
  scale_y_continuous(
    limits = c(0, 4000000),
    labels = comma,
    expand = expansion(mult = 0, add = 0)
  )   
  facet_grid(
    rows = vars(year),
    cols = vars(month),
    switch = "x",
    scales = "free_x",
    space = "free_x"
  )  
  labs(
    x = "day number",
    y = "query count per day",
    caption = "Test API"
  )  
  ggtitle("March 2022 : Active users")  
  theme(
    strip.placement = "outside",
    axis.text.x = element_text(angle = 0, vjust = 0.5, hjust=0.5),
    axis.title.y = element_text(margin = margin(t = 0, r = 15, b = 0, l = 0)),
    axis.title.x = element_text(margin = margin(t = 15, r = 0, b = 0, l = 0)),
    plot.title = element_text(hjust = 0.5, size = 12),
    plot.caption = element_text(size = 8, hjust = 1),
    plot.caption.position = "plot",
    panel.spacing.x=unit(0.0, "lines"),
    panel.spacing.y=unit(0.0, "lines")
  )  
  guides(fill=guide_legend(title="User account"))   
  scale_fill_manual(values = c("all users" = "#004586",
                               "user1" = "#ffd320",
                               "user2" = "#579d1c",
                               "user3" = "#7e0021"))

In the above graphics the year 2022 is on the top right hand side. Is there any way to put below the month value (march)?

CodePudding user response:

You can change to facet_wrap(), with strip.position = "bottom" indicated, like this:

  facet_wrap(~year month,
    strip.position = "bottom",
    scales = "free_x"
  )

CodePudding user response:

If you want to keep facet_grid functionality, you could also use ggh4x::facet_nested

(note I've stripped your plot from lots of extraneous bits)

library(tidyverse)

## ...preparing your data, as per your question... 

ggplot(data = df_graph_data)  
  geom_col(mapping = aes(
    x = day_number,
    y = nbr_requetes,
    fill = user_name
  ))  
  ggh4x::facet_nested(~year month,
    switch = "x",
    scales = "free_x",
    space = "free_x"
  )  
  theme(
    strip.placement = "outside"
  )

  • Related