繁体   English   中英

如何将 geom_point、geom_bar 和 geom_errobar 与 position_dodge 对齐

[英]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_dodge2preserve='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_errobargeom_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM