使用 grid.arrange 或 face_grid 获取每个绘图列的 x 个刻度

Get varrying x ticks per plot column with grid.arrange or face_grid

我有这个示例数据。

structure(list(type = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 6L, 6L, 6L, 6L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 
5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L), .Label = c("1", "2", "3", 
"4", "5", "6"), class = "factor"), category = c("fact", "fact", 
"fact", "fact", "fact", "fact", "fake", "fake", "fake", "fake", 
"fake", "fake", "fact", "fact", "fact", "fact", "fact", "fact", 
"fake", "fake", "fake", "fake", "fake", "fake", "fact", "fact", 
"fake", "fake", "fact", "fact", "fact", "fact", "fact", "fact", 
"fake", "fake", "fake", "fake", "fake", "fake", "fact", "fact", 
"fact", "fact", "fact", "fact", "fake", "fake", "fake", "fake", 
"fake", "fake", "fact", "fact", "fact", "fact", "fact", "fact", 
"fake", "fake", "fake", "fake", "fake", "fake"), group = c("TG1", 
"TG1", "TG2", "TG2", "TG3", "TG3", "TG1", "TG1", "TG2", "TG2", 
"TG3", "TG3", "TG1", "TG1", "TG2", "TG2", "TG3", "TG3", "TG1", 
"TG1", "TG2", "TG2", "TG3", "TG3", "TG2", "TG2", "TG2", "TG2", 
"TG1", "TG1", "TG2", "TG2", "TG3", "TG3", "TG1", "TG1", "TG2", 
"TG2", "TG3", "TG3", "TG1", "TG1", "TG2", "TG2", "TG3", "TG3", 
"TG1", "TG1", "TG2", "TG2", "TG3", "TG3", "TG1", "TG1", "TG2", 
"TG2", "TG3", "TG3", "TG1", "TG1", "TG2", "TG2", "TG3", "TG3"
), cred = c("dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes", "dislikes", 
"likes", "dislikes", "likes", "dislikes", "likes"), sum_possible = c(1256L, 
1256L, 1236L, 1236L, 1238L, 1238L, 4396L, 4396L, 4326L, 4326L, 
4333L, 4333L, 9420L, 9420L, 9270L, 9270L, 9285L, 9285L, 6908L, 
6908L, 6798L, 6798L, 6809L, 6809L, 0L, 0L, 1236L, 1236L, 2512L, 
2512L, 2472L, 2472L, 2476L, 2476L, 1884L, 1884L, 1854L, 1854L, 
1857L, 1857L, 11304L, 11304L, 11124L, 11124L, 11142L, 11142L, 
9420L, 9420L, 9270L, 9270L, 9285L, 9285L, 2512L, 2512L, 2472L, 
2472L, 2476L, 2476L, 1884L, 1884L, 1854L, 1854L, 1857L, 1857L
), rate = c(0.02, 0.02, 0.02, 0.03, 0.05, 0.02, 0.05, 0.01, 0.05, 
0.01, 0.08, 0, 0.08, 0.17, 0.07, 0.16, 0.08, 0.18, 0.14, 0.1, 
0.11, 0.09, 0.18, 0.09, NaN, NaN, 0.08, 0.13, 0.05, 0.17, 0.04, 
0.15, 0.05, 0.18, 0.26, 0.14, 0.22, 0.13, 0.36, 0.12, 0.02, 0.13, 
0.02, 0.15, 0.03, 0.21, 0.11, 0.05, 0.13, 0.05, 0.19, 0.07, 0, 
0.02, 0, 0.03, 0, 0.06, 0, 0, 0, 0, 0, 0), sum_clicks = c(27, 
30, 19, 34, 57, 29, 221, 39, 196, 26, 331, 15, 718, 1591, 607, 
1491, 710, 1694, 983, 696, 736, 578, 1196, 630, 0, 0, 103, 155, 
126, 416, 91, 381, 129, 437, 495, 266, 414, 235, 671, 223, 235, 
1515, 201, 1634, 379, 2373, 1083, 450, 1241, 418, 1740, 649, 
3, 61, 1, 62, 10, 158, 2, 1, 2, 0, 5, 3)), row.names = c(NA, 
-64L), class = c("tbl_df", "tbl", "data.frame"))

并想为每个类别和组绘制一个图。

可以使用 facet_wrap:

library(ggplot2)
library(gridExtra)
library(gtable)
library(grid)

ggplot(sample, aes(x = type, y = rate, fill = cred))+
  geom_col()+
  labs(y = "Rate") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        axis.title.x = element_blank(),
        legend.title = element_blank())+
  facet_grid(rows = vars(category), cols = vars(group), 
             switch = 'y')+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)

给出:

但是,只有TG2在type变量中有变量级别“6”。 这就是为什么我不希望“6”显示在 x 轴的第 1 列和第 3 列中。

我了解到如果轴变化我可能不想使用 facet_grid 并继续分别构建每个地块并使用 grid.arrange

p1 <- ggplot(sample %>% filter(category == "fact", group == "TG1"), aes(x = type, y = rate, fill = cred))+
  geom_col()+
  labs(y = "Rate") +
  theme(axis.title = element_blank(),
        legend.title = element_blank(),
        #axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank()
  )+
  facet_grid(rows = vars(category), cols = vars(group),
             switch = 'y')+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)

p2 <- ggplot(sample %>% filter(category == "fact", group == "TG2"), aes(x = type, y = rate, fill = cred))+
  geom_col(show.legend = FALSE)+
  labs(y = "Rate") +
  theme(axis.title = element_blank(),
        legend.title = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank()
  )+
  facet_grid(rows = vars(category), cols = vars(group),
             switch = 'y')+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)

p3 <- ggplot(sample %>% filter(category == "fact", group == "TG3"), aes(x = type, y = rate, fill = cred))+
  geom_col(show.legend = FALSE)+
  labs(y = "Rate") +
  theme(axis.title = element_blank(),
        legend.title = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank()
  )+
  facet_grid(rows = vars(category), cols = vars(group),
             switch = 'y')+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)


p4 <- ggplot(sample %>% filter(category == "fake", group == "TG1"), aes(x = type, y = rate, fill = cred))+
  geom_col(show.legend = FALSE)+
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        axis.title = element_blank(),
        strip.text.x = element_blank())+
  facet_grid(rows = vars(category), cols = vars(group),
             switch = 'y')+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)

p5 <- ggplot(sample %>% filter(category == "fake", group == "TG2"), aes(x = type, y = rate, fill = cred))+
  geom_col(show.legend = FALSE)+
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        axis.title = element_blank(),
        strip.text.x = element_blank())+
  facet_grid(rows = vars(category), cols = vars(group),
             switch = 'y')+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)

p6 <- ggplot(sample %>% filter(category == "fake", group == "TG3"), aes(x = type, y = rate, fill = cred))+
  geom_col(show.legend = FALSE)+
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        axis.title = element_blank(),
        strip.text.x = element_blank())+
  facet_grid(rows = vars(category), cols = vars(group),
             switch = 'y')+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)

legend = gtable_filter(ggplotGrob(p1), "guide-box")
grid.arrange(arrangeGrob(p1+ theme(legend.position="none"),
                         p2,
                         p3,
                         p4,
                         p5,
                         p6,
                         nrow = 2,
                         left = textGrob("Click Rate", rot = 90, vjust = 1)
),
legend,
widths=unit.c(unit(1, "npc") - legend$width, legend$width),
nrow = 1)

这给了我:

这里我只有 type TG2 的“6”。不过,在我的真实示例中,axis.text 实际上是完整的单词,它们会裁剪图表的底行,这使得它们的缩放比例与顶行大不相同。

我进一步尝试提取 axis.text 并将其添加到下面的附加行中。

axis.ticks = gtable_filter(ggplotGrob(p4), "axis-b-1")
axis.ticks_tg2 = gtable_filter(ggplotGrob(p5), "axis-b-1")

grid.arrange(arrangeGrob(p1+ theme(legend.position="none"),
                         p2,
                         p3,
                         p4+ theme(axis.text.x = element_blank()),
                         p5+ theme(axis.text.x = element_blank()),
                         p6+ theme(axis.text.x = element_blank()),
                         nrow = 2,
                         left = textGrob("Rate", rot = 90, vjust = 1)
),
legend,
widths=unit.c(unit(1, "npc") - legend$width, legend$width),
arrangeGrob(axis.ticks,axis.ticks_tg2,axis.ticks, nrow = 1),
nrow = 2)

但是,这与我的坐标系不太匹配。

你知道我怎样才能得到我喜欢的解决方案吗:

x 轴文本仅在网格底部,如 facet_grid,但 x 轴刻度数不同,如 grid.arrange 每列?

非常感谢您的帮助!

代替grid.arrange的一种选择是使用facet_grid(...scales = "free_x")释放x比例:

library(ggplot2)

ggplot(sample, aes(x = type, y = rate, fill = cred))+
  geom_col()+
  labs(y = "Rate") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        axis.title.x = element_blank(),
        legend.title = element_blank())+
  facet_grid(rows = vars(category), cols = vars(group), 
             switch = 'y', scales = "free_x")+
  scale_fill_discrete(labels = c("Dislikes", "Likes"))+
  ylim(0, 0.5)
#> Warning: Removed 2 rows containing missing values (position_stack).