一个组内的多个箱线图

3
我找到了一些解决方案,但不完全是我想要的。我在R中有5个数据框,每个数据框都有4列:

假设第一个数据框的名称是“Gene1”

Ind1     Ind2       Ind3      Ind4
1          3         3.2        2.5
1          3         4          2
1.5        2         2.2        1
3.4        2         1          3

其余的数据框分别称为“Gene2”,“Gene3”,“Gene4”和“Gene5”,并且类似。

我想将所有数据框和所有列的箱线图并排绘制在同一张图中。我没有找到这样的图,因此我无法上传图片,但我会尝试解释。

现在从上面的数据中,图表将具有20个箱线图。前4个箱线图应该靠在一起,并且x轴名称应为“Gene1”(对于所有4个箱线图),然后在图中留出一点空间,再次出现4个箱线图,其x轴名称为“Gene2”,以此类推。

我可以轻松地在一个图中绘制所有箱线图,但我无法区分数据框。也就是说,它应该清楚地显示前4个箱线图来自“Gene1”,接下来的4个箱线图来自“Gene2”,以此类推。

如果问题不清楚,请告诉我。

2个回答

11

我猜想这就是你想要的,实际上使用标准的 graphics 包中的绘图函数并不复杂。这些分组数据以4个单独面板的形式进行绘制,但是共享y轴和在外侧边缘绘制的标题使其看起来像是一个单独的绘图。

# Faking the data, since you didn't provide any
Gene <- data.frame(matrix(rweibull(100*4, 1), 100))
names(Gene) <- paste0("Ind", 1:4)
Gene <- rep(list(Gene), 4)

# Setup the panels
layout(t(1:4))
par(oma=c(2, 4, 4, 0), mar=rep(1, 4), cex=1)
# `mar` controls the space around each boxplot group

# Calculating the range so that the panels are comparable
my.ylim <- c(min(sapply(Gene, min)), max(sapply(Gene, max)))

# Plot all the boxes
for(i in 1:length(Gene)){
    boxplot(Gene[[i]], ylim=my.ylim, axes=FALSE)
    mtext(paste("Gene", i), 1, 0)
    if(i == 1){
        axis(2, las=1)
        mtext("Expression or what you have", 2, 3)
    }
}
title("Look at all my genes!", outer=TRUE)

enter image description here

顺便说一下,我建议将数据框存储在列表中,而不是通过命名它们为 "Gene1"、"Gene2"、"Gene3"和"Gene4"来模拟列表。这样做更容易自动化。如果您仍然想将它们存储为单独的变量,请将 Gene[[i]] 替换为 get(paste0("Gene", i))my.ylim <- ... 替换为 min(c(min(Gene1), min(Gene2) ... 等。


@Backlin +1 非常好的答案。您如何在每个组的箱线图下方添加文本(但在组名称上方)?例如,对于“基因1”组,A、B、C、D在每个箱线图下面?如何添加图例?我尝试了最后一个绘图,但一半的图例被第三个图所遮挡。如果您愿意,我可以创建一个新问题。提前致谢。 - Antoine
很高兴能帮到你!我会使用 axis(1, at=1:4, LETTERS[1:4], lwd=0, mgp=c(0,0,0)) 添加盒子标签,然后使用 mtext(paste("Gene", i), 1, 1) 添加组标签。 - Backlin

6

以下是我使用 ggplot2 和相关工具尝试满足您的需求。

library(ggplot2)
library(reshape2)
library(plyr)

Gene1 <- read.table(text = "Ind1     Ind2       Ind3      Ind4
1          3         3.2        2.5
1          3         4          2
1.5        2         2.2        1
3.4        2         1          3", header = TRUE)

#Make a copy of Gene1
Gene2 <- Gene1

#A Round about way to rbind these together with an ID column
combined_data <- ldply(list(Gene1 = Gene2, Gene2 = Gene2))

#Melt into the long format needed by ggplot2
combined_data_melt <- melt(combined_data, id.vars = 1)

#Plot and use facet_wrap for each data.frame
ggplot(combined_data_melt, aes(variable, value)) +
  geom_boxplot() +
  facet_wrap(~.id, ncol = 1) +
  theme_bw()

给你一个类似这样的输出:

enter image description here

这应该可以满足您的需求,对代码进行了相当小的更改。感谢JoranR聊天室中关于躲避的提示。
ggplot(combined_data_melt, aes(.id, value, dodge = variable)) +
  geom_boxplot(position = position_dodge(width = 0.8)) +
  theme_bw()

enter image description here


谢谢您的回复。我问题中提供的链接提供了某种类似的解决方案。但是我想要在一个图中呈现。前4个图应该彼此靠近,并且“Gene1”标签应该在x轴上(下方),然后留出一点空间,然后是4个图等等。我知道没有图片很难解释,但如果仍然不清楚,请告诉我。 - Vikas
1
@Vikas - 所以你想要一个宽度为20个箱线图的图表,每四个箱线图之间还有一些额外的空白区域?你是要将其打印成壁画吗? :) - Chase
我认为我们可以减小箱线图的尺寸,这样就可以了。 - Vikas
@Vikas - 我明白了,看看修改后的答案。 - Chase

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