是否可以将所有分组值放在 x 轴标签下方的 facet_grid 中?

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

我正在使用 gglplot2 创建图形。

根据 facet_grid 的用户手册,switch 参数执行以下操作:

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"'.

我想知道是否有可能在使用两个变量对值进行分组的方面,将两个变量都放在底部,即 x 轴标签下方。我的意思是而不是

+
+   +       +       +           2
+   +       +   +   +           0
+   +       +   +   +   +       2
+   +   +   +   +   +   +   +   2
              march

是否可以

+
+   +       +       +        
+   +       +   +   +        
+   +       +   +   +   +    
+   +   +   +   +   +   +   +
              march
              2022

这实际上是我经常在 Excel/Calc 中创建条形图的方式,我发现它更具可读性。

这是我的测试用例:

要用于图形的数据框

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"))

图形代码

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"))

在上图中,2022 年位于右上方。有没有办法把月值(三月)放到下面?

您可以更改为 facet_wrap(),并标明 strip.position = "bottom",如下所示:

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

如果您想保留 facet_grid 功能,您还可以使用 ggh4x::facet_nested

(注意我已经从很多无关的位中剥离了你的情节)

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"
  )