[英]How to align geom_point, geom_bar and geom_errobar with position_dodge
我正在尝试在 ggplot 中生成 plot 用于多项逻辑回归。 并非在每个因子水平上都观察到我的名义因变量的所有水平。 我想要一个具有均匀宽度的 plot。 一旦我使用position_dodge(preserve='single')
代码,我可以使用带有均匀宽度条的 geom_bar 获得每个因子的平均值,但我无法让geom_point
对齐相同。
这是我的数据,决定是名义因变量:
decide=c("h", "g", "h", "g", "h", "g", "g", "h", "g", "h", "g", "h", "h", "h", "h", "h", "g", "h", "h", "r", "g", "h", "h", "h", "g", "g", "g", "h", "h", "h","h", "h", "h", "r", "h", "g", "g", "h", "g", "h", "g", "h", "g", "h", "d", "h", "h", "r", "h", "h", "g", "g", "g", "h", "g", "g", "g", "g", "h", "h")
dcsz=c("small", "medium", "small", "small", "medium", "small", "small", "medium", "medium", "small", "small", "medium", "small", "medium", "small", "medium", "small", "medium", "small", "small", "medium", "small", "medium", "medium", "medium", "small", "small", "medium", "small", "medium", "small", "medium", "small", "medium", "medium", "medium", "small", "medium", "medium", "small", "medium", "small", "medium", "medium", "small", "small", "medium", "small", "medium", "medium", "medium", "small", "small", "small", "small", "medium", "medium", "small", "small", "medium")
disthome=c(9.2,10.0,5.0,0.8,6.5,2.0,6.8,1.6,6.9,4.4,5.8,6.2,4.7,0.6,3.0,4.7,5.8,1.5,5.8,4.5,3.2,4.6,2.9,4.1,6.5,4.8,9.1,4.7,4.3,4.2,4.8,3.5,5.4,7.1,3.0,5.3,1.0,5.2,2.2,1.7,6.0,6.1,3.1,2.4,4.3,5.1,7.2,9.8,6.9,3.1,8.8,0.9,9.7,2.2,5.4,4.4,6.8,8.3,5.4,2.2)
gohome=data.frame(decide, dcsz, disthome)
这是我得到平均误差和标准误差的方法:
gohome.disthome <- gohome %>%
group_by(dcsz,decide) %>%
summarise(meandisthome = mean(na.omit(disthome)),
sedisthome=sd(na.omit(disthome))/sqrt(n()))
现在进入细节:这是我在设法将误差线与均值条对齐并将点分成名义变量之前的原始代码:
ggplot(gohome,aes(y=disthome, x=dcsz, fill = decide)) +
#add bars and the preserve part keeps all bars same width
geom_bar(stat="identity", position=position_dodge(),
data=gohome.disthome,aes(x=dcsz,y=meandisthome))
#overlay data points
geom_point(position=position_dodge()) +
#add error bars of means
geom_errorbar(data=gohome.disthome,stat="Identity",
position=position_dodge(),
aes(x=dcsz, fill = decide,y=meandisthome,
ymin=meandisthome-sedisthome,ymax=meandisthome+sedisthome),
width=0.3)+
#flip axis
coord_flip()
这是我让误差线与平均线对齐的代码(在position_dodge
中使用 0.9),将点分成名义变量(0.9),并且即使误差线和平均线都具有相同的宽度因变量的水平并未在每个因子水平中都观察到(我在position_dodge
中添加了preserve="single"
)。 我不能将preserve='single'
添加到geom_point
中,否则它不会通过名义变量分隔点,并且使用preserve='total'
也不会做任何事情:
ggplot(gohome,aes(y=disthome, x=dcsz, fill = decide)) +
#add bars and the preserve part keeps all bars same width
geom_bar(stat="identity",position=position_dodge(preserve='single'),
data=gohome.disthome,aes(x=dcsz,y=meandisthome))+
#overlay data points
geom_point(position=position_dodge(0.9)) +
#add error bars of means
geom_errorbar(data=gohome.disthome,stat="Identity",
position=position_dodge(0.9,preserve = "single"),
aes(x=dcsz, fill = decide,y=meandisthome,
ymin=meandisthome-sedisthome,ymax=meandisthome+sedisthome),
width=0.3)+
#flip axis
coord_flip()
我也尝试过使用position_dodge2
而不是position_dodge
来处理不同的组合和preserve='total'
,但这也不能解决它。 这些点要么保持发言权,要么完全分散,没有分离。 我的想法是使用以下链接中的position_dodge2
和preserve='total'
因为我的问题非常相似(不知道为什么我的问题不工作): https://github.com/tidyverse/ggplot2/issues/2712
有人可以帮我修复我的代码吗? 我需要指出所有错误栏的完美对齐。
躲避可能是一种痛苦。 鉴于您的用例,并假设您没有将构面用于其他任何事情,使用它们可能会更简单:
ggplot(gohome,
aes(x = decide, y = disthome)) +
stat_summary(geom = "bar", fun = "mean",
aes(fill = decide),
width = 1) +
geom_point() +
stat_summary(geom = "errorbar") + # default summary function is mean_se()
facet_grid(forcats::fct_rev(dcsz) ~ ., switch = "y") +
coord_flip() +
# optional: aesthetic changes to imitate the original look
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank(),
panel.spacing = unit(0, "pt"),
strip.background = element_blank(),
strip.text.y.left = element_text(angle = 0))
(请注意,我也没有使用汇总数据框,因为 ggplot2 中的汇总统计信息就足够了。)
问题是您错过了在geom_errobar
和geom_point
中设置分组变量。 从文档:
position_dodge() 要求在 global 或 geom_* 层中指定分组变量。
尝试这个:
library(dplyr)
library(ggplot2)
ggplot(gohome,aes(y=disthome, x=dcsz)) +
#add bars and the preserve part keeps all bars same width
geom_bar(stat="identity",
position=position_dodge(),
data=gohome.disthome,
aes(x=dcsz, y=meandisthome, fill = decide)) +
#overlay data points
geom_point(aes(group = decide), position=position_dodge(width = 0.9)) +
#add error bars of means
geom_errorbar(data=gohome.disthome,stat="Identity",
position=position_dodge(width = 0.9),
aes(x=dcsz,
group = decide,
y=meandisthome,ymin=meandisthome-sedisthome,ymax=meandisthome+sedisthome), width = 0.5)+
#flip axis
coord_flip()
编辑经过大量谷歌搜索并检查了几个组合,我能想出的获得相同宽度的条的最佳解决方案是使用tidyr::complete(decide, dcsz)
简单地填充 dataframe 。
gohome <- data.frame(decide,dcsz,disthome) %>%
tidyr::complete(decide, dcsz)
gohome.disthome <- gohome %>% group_by(dcsz,decide) %>%
summarise(meandisthome = mean(na.omit(disthome)), sedisthome=sd(na.omit(disthome))/sqrt(n()))
#> `summarise()` regrouping output by 'dcsz' (override with `.groups` argument)
ggplot(gohome,aes(y=disthome, x=dcsz)) +
#add bars and the preserve part keeps all bars same width
geom_bar(stat="identity",
position=position_dodge(),
data=gohome.disthome,
aes(x=dcsz, y=meandisthome, fill = decide)) +
#overlay data points
geom_point(aes(group = decide), position=position_dodge(width = 0.9)) +
#add error bars of means
geom_errorbar(data=gohome.disthome,stat="Identity",
position=position_dodge(width = 0.9),
aes(x=dcsz,
group = decide,
y=meandisthome,ymin=meandisthome-sedisthome,ymax=meandisthome+sedisthome), width = 0.5)+
#flip axis
coord_flip()
由reprex package (v0.3.0) 于 2020 年 6 月 29 日创建
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.