如何在 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 不容易重新制作)
A
和 B
的每个组合都有三行数据,因此您当前的代码实际上是在每个 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")
不管怎样,剧情是这样的:
我有一个“场景”(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 不容易重新制作)
A
和 B
的每个组合都有三行数据,因此您当前的代码实际上是在每个 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")
不管怎样,剧情是这样的: