如何在 R 中按组计算 SD,而不会丢失在 ggplot2 中绘图仍然需要的列?

How to calculate SD by group in R, without losing columns still needed for plotting in ggplot2?

我有一个“场景”(27x) 的数据集,其中 A、B 和 C 是模型的某些输入值,值是变量的结果。

现在我想用 ggplot 制作一个分组条形图(y 上的值,x 上的因子 B,由 A 填充。我想根据因子 C 引起的变化制作误差线。

我的数据集(已简化)大致采用以下格式:

data <- data.frame(matrix(ncol=0, nrow=27))
data$value <- runif(27, min=10, max=60)
data$A <- factor((rep(1:9, each=3)))
data$B <- factor((rep(1:3, each=9)))
data$C <- factor(rep(rep(1:3),9))

看起来像:

     value A B C
1 27.76710 1 1 1
2 34.71762 1 1 2
3 20.72895 1 1 3
4 34.83710 2 1 1
5 31.44144 2 1 2
6 13.11038 2 1 3
etc

ggplot 将是

ggplot(data, aes(fill=A, y=value, x=B)) + 
  geom_bar(stat="identity",position=position_dodge())+
  geom_errorbar(aes(ymin=?????, ymax=????), width=.2,
                position=position_dodge(.9))

所以我正在为 ymin 和 ymax 苦苦挣扎。可以是value+sd或者-sd,但是我还没有计算sd。

我现在的方法是使用 A 组的 dplyr 摘要。这给了我:

data %>% 
group_by(A) %>% 
summarise(mean=mean(value), sd = sd(value))

  A      mean    sd
  <fct> <dbl> <dbl>
1 1      27.7  6.99
2 2      26.5 11.7 
3 3      33.7 21.9 
4 4      27.7  6.99
etc

这很好,但是,现在我丢失了所有其他列(在这种情况下,我的 ggplot 仍然需要 B)。我怎样才能仍然计算平均值和 sd 并保留所有其他列?

或者有其他方法可以达到我需要的效果吗? (我可以手动重新添加 B 列,但我想知道将来是否还有其他方法,并且在某些情况下 B 不容易重新制作)

AB 的每个组合都有三行数据,因此您当前的代码实际上是在每个 x 轴位置重叠绘制三个条。您可以通过为条形添加透明度来看到这一点。

ggplot(data, aes(fill=A, y=value, x=B)) + 
  geom_bar(stat="identity", position=position_dodge(), alpha=0.3)

看起来您实际上是在尝试执行以下操作(但如果我误解了请告诉我):

pd = position_dodge(0.92)

data %>% 
  group_by(A,B) %>% 
  summarise(mean=mean(value), sd=sd(value)) %>% 
  ggplot(aes(fill=A, x=B)) + 
  geom_col(aes(y=mean), position=pd)+
  geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), position=pd, width=0.2)

分面是另一种选择:

data %>% 
  group_by(A,B) %>% 
  summarise(mean=mean(value), sd=sd(value)) %>% 
  ggplot(aes(x=A)) + 
    geom_col(aes(y=mean), fill=hcl(240,100,65)) +
    geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), width=0.2) +
    facet_grid(. ~ B, labeller=label_both, space="free_x", scales="free_x")

但是你真的需要酒吧吗?

data %>% 
  group_by(A,B) %>% 
  summarise(mean=mean(value), sd=sd(value)) %>% 
  ggplot(aes(x=A)) + 
  geom_pointrange(aes(y=mean, ymin=mean-sd, ymax=mean+sd), shape=21, fill="red", 
                  fatten=6, stroke=0.3) +
  facet_grid(. ~ B, labeller=label_both, space="free_x", scales="free_x")

我们也可以在 ggplot 中进行计算,使用 stat_summary:

data %>% 
  ggplot(aes(x=A, y=value)) + 
  stat_summary(fun.data=mean_sdl, fun.args=list(mult=1), geom="pointrange", 
               shape=21, fill="red", fatten=6, stroke=0.3) +
  facet_grid(. ~ B, labeller=label_both, space="free_x", scales="free_x")

不管怎样,剧情是这样的: