Boxplot ggplot2:在分组箱线图中显示平均值和观察次数
Posted
技术标签:
【中文标题】Boxplot ggplot2:在分组箱线图中显示平均值和观察次数【英文标题】:Boxplot ggplot2: Show mean value and number of observations in grouped boxplot 【发布时间】:2020-10-07 13:26:05 【问题描述】:我希望将观察数添加到此箱线图中,不是按组,而是按因子分隔。另外,我希望显示除了看起来像这样的 x 轴标签之外的观察数:(“PF(N = 12)”)。 此外,我想显示盒子内每个盒子的平均值,以百万显示,以免每个盒子都有一个巨大的数字。
这是我得到的:
give.n <- function(x)
return(c(y = median(x)*1.05, label = length(x)))
mean.n <- function(x)x <- x/1000000
return(c(y = median(x)*0.97, label = round(mean(x),2)))
ggplot(Soils_noctrl) +
geom_boxplot(aes(x=Slope,y=Events.g_Bacteria, fill = Detergent),
varwidth = TRUE) +
stat_summary(aes(x = Slope, y = Events.g_Bacteria), fun.data = give.n, geom = "text",
fun = median,
position = position_dodge(width = 0.75))+
ggtitle("Cell Abundance")+
stat_summary(aes(x = Slope, y = Events.g_Bacteria),
fun.data = mean.n, geom = "text", fun = mean, colour = "red")+
facet_wrap(~ Location, scale = "free_x")+
scale_y_continuous(name = "Cell Counts per Gram (Millions)",
breaks = round (seq(min(0),
max(100000000), by = 5000000),1),
labels = function(y) y / 1000000)+
xlab("Sample")
到目前为止,它看起来像这样: As you can see, the mean value is at the bottom of the plot and the number of observations are in the boxes but not separated
感谢您的帮助!干杯
【问题讨论】:
没有任何样本数据很难做出好的推荐。见***.com/a/5965451/4114240。我最好的猜测是您的问题是 stat_summary 没有继承 aes,而是定义了一个新的并且不包括 Detergent。因此,如果没有根据 Detergent 因子将它们分开,代码会将文本放在箱线图所在的位置。只是我最好的猜测。 HTH 使用 geom_text 作为样本大小和平均值可能更容易 - 您可以设置 x 和 y 坐标,例如geom_text(aes(x = Slope, y = min(Events.g.bacteria), label = give.n)) + geom_text(aes(x = Slope, y = 1.1 * min(Events.g.bacteria), label = mean.n)) 应将样本编号放在底部,将平均值放在其上方。您可能需要稍微调整一下比例(例如 0.9*min(...) 等) 另一个可能的想法是fill
参数在 facet 和 x 变量的组合之间拆分数据。但是中值和均值函数使用给定组合中的所有值。特别是,有多少行数据适合AL_S
和Buot
方面?有 9 个吗?
【参考方案1】:
TL;DR - 您需要提供 group=
美学,因为 ggplot2
不知道它应该在哪个列数据上避开文本几何图形。
很遗憾,我们没有您的数据,但这里有一个示例集,可以展示此处的基本原理以及 group=
的功能/需求。
set.seed(1234)
df1 <- data.frame(detergent=c(rep('EDTA',15),rep('Tween',15)), cells=c(rnorm(15,10,1),rnorm(15,10,3)))
df2 <- data.frame(detergent=c(rep('EDTA',20),rep('Tween',20)), cells=c(rnorm(20,1.3,1),rnorm(20,4,2)))
df3 <- data.frame(detergent=c(rep('EDTA',30),rep('Tween',30)), cells=c(rnorm(30,5,0.8),rnorm(30,3.3,1)))
df1$smp='Sample1'
df2$smp='Sample2'
df3$smp='Sample3'
df <- rbind(df1,df2,df3)
我将不使用stat_summary()
,而是创建一个单独的数据框来保存我想要作为文本包含在绘图中的平均值:
summary_df <- df %>% group_by(smp, detergent) %>% summarize(m=mean(cells))
现在,这是geom_text()
的情节和使用与躲避:
p <- ggplot(df, aes(x=smp, y=cells)) +
geom_boxplot(aes(fill=detergent))
p + geom_text(data=summary_df,
aes(y=m, label=round(m,2)),
color='blue', position=position_dodge(0.8)
)
您会注意到这些数字都沿y=
分开很好,但“躲避”不起作用。这是因为我们没有提供任何关于如何进行躲闪的信息。在这种情况下,可以提供 group=
美学以让 ggplot2
知道这是用于躲避的列:
p + geom_text(data=summary_df,
aes(y=m, label=round(m,2), group=detergent),
color='blue', position=position_dodge(0.8)
)
如果您提供另一种美学(例如 color=
或 fill=
),则您没有有提供group=
美学。如果您同时给出color=
和group=
美学,则group=
美学将覆盖任何其他美学以用于躲避目的。这是一个相同的示例,但您不需要 group=
美学,因为我已将 color=
移动到 aes()
(将填充更改为灰度以便您可以看到文本):
p + geom_text(data=summary_df,
aes(y=m, label=round(m,2), color=detergent),
position=position_dodge(0.8)
) + scale_fill_grey()
小花絮:即使您为geom_text()
提供了通常可以用于躲避的荒谬美学,例如fill=
,躲避仍然有效。您会收到警告消息Ignoring unknown aesthetics: fill
,但躲避仍然有效:
p + geom_text(data=summary_df,
aes(y=m, label=round(m,2), fill=detergent),
position=position_dodge(0.8)
)
# gives you the same plot as if you just supplied group=detergent, but with black text
在您的情况下,将您的 stat_summary()
行更改为此应该可以:
stat_summary(aes(x = Slope, y = Events.g_Bacteria, group = Detergent),...
【讨论】:
以上是关于Boxplot ggplot2:在分组箱线图中显示平均值和观察次数的主要内容,如果未能解决你的问题,请参考以下文章
ggplot2 函数中 geom_boxplot 的平均值和中值箱线图图例
R语言使用ggplot2包使用geom_boxplot函数绘制基础分组箱图(配置数据点显示)实战
R语言使用ggplot2包使用geom_boxplot函数绘制基础分组箱图(boxplot)实战