ggplot:按多个分类变量绘制箱线图

7
我正在尝试使用ggplot2在一个图表中绘制几个箱线图。我有一个连续变量和几个因子。我想要一个单一的Y轴,每对箱线图都有自己的X轴和因子水平。到目前为止,我尝试使用cowplot::plot_grid将我分别制作的图表与用于Y轴的空图表连接起来。我试图通过隐藏边距和调整图表大小使图表融合得很好,但我仍然无法得到合理的结果,而且这种方法涉及太多手动调整。
这是我想要的效果以及我迄今为止想出的解决方案:charts 以下是我的脚本:
library(ggplot2)
library(cowplot)
library(dplyr)

# make a dataset:
DF <- mtcars
DF$cyl <- as.factor(DF$cyl)
DF$vs <- as.factor(DF$vs)
DF$am <- as.factor(DF$am)
DF$gear <- as.factor(DF$gear)
DF$carb <- as.factor(DF$carb)
#str(DF)

# fisrt boxplot
p1 <- DF %>% ggplot() + theme_grey() + aes(x=cyl, y=mpg, fill=cyl) +
  geom_boxplot() +
  theme(legend.position = "none",
        axis.title.y = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank()) +
  theme(plot.margin = margin(t=0.1, r=0, b=0, l=0, unit="cm"))

# second boxplot
p2 <- DF %>% ggplot() + theme_grey() + aes(x=vs, y=mpg, fill=vs) +
  geom_boxplot() +
  theme(legend.position = "none",
        axis.title.y = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank()) +
  theme(plot.margin = margin(t=0.1, r=0, b=0, l=0, unit="cm"))

# empty boxplot used only for the y axis
y_axis <- DF %>% ggplot() + theme_grey() + aes(x=mpg, y=mpg) +
  geom_point() +
  theme(axis.title.y = element_text(),
        axis.text.y = element_text(),
        axis.title.x = element_text(),
        axis.text.x = element_text()) +
  theme(plot.margin = margin(t=0.1, r=0, b=0, l=0, unit="cm"))+
  scale_x_continuous(limits = c(0, 0), breaks=c(0), labels = c(""), name="")

# join all charts toghether
p_all <- plot_grid(y_axis, p1, p2,
                   align="v", axis="l", 
                   nrow=1, rel_widths = c(0.2, 1, 1))

ggdraw(p_all)

你期望在x轴和y轴上看到什么?通常可以使用gacet_grid / facet_wrap在ggplot中完成。 - sai saran
2个回答

7

这是使用几个变量、一些颜色和 tidyr 的效果。您可以使用 panel.border 添加图形之间的边框,并应在 facet_wrap 中指定要为 1 的行数:

library(ggplot2)
library(dplyr)
library(tidyr)

# Only select variables meaningful as factor
DF <- select(mtcars, mpg, cyl, vs, am, gear, carb) 

DF %>% 
  gather(variable, value, -mpg) %>%
  ggplot(aes(factor(value), mpg, fill = factor(value))) +
  geom_boxplot() +
  facet_wrap(~variable, scales = "free_x", nrow = 1, strip.position = "bottom") +
  theme(panel.spacing = unit(0, "lines"),
        panel.border = element_rect(fill = NA),
        strip.background = element_blank(),
        axis.title.x = element_blank(),
        legend.position = "none",
        strip.placement = "outside")

enter image description here


谢谢。这个解决方案与alex_555的解决方案几乎相同,只是使用了tidyr::gather而不是reshape2::melt。我可能也会为其他函数导入tidyr,所以这可能最终更有用。 - user2053921

2
这是你想要的吗?
x <- DF
x$cars <- rownames(x)
x <- melt(x[,c("cars", "cyl", "mpg", "vs")], id.vars=c("cars", "mpg"))

ggplot(x, aes(x=value,y=mpg))+
  geom_boxplot()+
  facet_wrap(~variable, strip.position = "bottom", scales = "free_x")+
  theme(panel.spacing = unit(0, "lines"),
        strip.background = element_blank(),
        strip.placement = "outside")

我首先使用 melt() 函数将您的数据格式转换为适合分面显示的格式。我想您可以从这里开始并自行完成其余的格式设置。

enter image description here


1
谢谢。我把所有内容放到一个函数中,并添加了一些自定义内容。现在它可以正常工作了。 - user2053921
1
哇,多么优雅的解决方案!可惜,如果需要真正的分面呈现,那就有点遗憾了 :( 我希望 ggplot 能够支持嵌套分面。 - JelenaČuklina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接