在条形图上添加误差线

5

我有两个向量。我想制作第一个向量的条形图(很简单,对吧)。问题在于第二个向量的每个元素都是第一个向量每个元素的标准差(本身是4个其他值的平均值)。我该怎么做?

涉及的向量:

-4.6521175 0.145839723
 1.1744100 0.342278694
-0.2581400 0.003776341
-0.3452675 0.073241199
-2.3823650 0.095008502
 0.5625125 0.021627196

即,如何将第二列向量的元素作为误差线添加到第一列向量中相应的元素中?

enter image description here

注意: 在你询问之前,我已经在这个网站上进行了广泛的搜索并进行了大量的谷歌搜索,但我的问题有些更加具体,即我所找到的与我需要的不符。

2个回答

14

我个人认为arrows()是这种图形的最佳选择:

df <- data.frame(bar = c(-4.6521175, 1.1744100, -0.2581400,  -0.3452675, -2.3823650, 0.5625125),
error = c(0.145839723, 0.342278694, 0.003776341, 0.073241199, 0.095008502, 0.021627196))

foo <- barplot(df$bar,ylim=c(-6,2),border=NA)
arrows(x0=foo,y0=df$bar+df$error,y1=df$bar-df$error,angle=90,code=3,length=0.1)

输入图像描述

两个细节:

  1. barplot() 中的 border=NA 可以移除条形图周围的边框,因此您可以看到第三个条形图周围的误差线。由于第三个误差值非常小,所以误差线几乎与条形图边框重合。

  2. 我使用 arrows() 中的 length 参数来缩小水平误差线的宽度,这对于我们有更多条形图的情况尤其重要。默认值为 length=0.25

但是,请注意“炸药图”具有重大缺点。您提到数据仅来自每个条形图的四个原始点。在这种情况下,最好只绘制原始数据的(抖动的)散点图。


2
太聪明了。我从来没有想过将箭头倾斜以使其看起来像误差线。 - thelatemail
我必须承认,那真是太棒了。要公正地给予赞扬。但有没有办法减小箭头的宽度?当数据点过多时,箭头会相互重叠。 - Stefan
@Stefan:非常好的观点。我编辑了我的答案,包括arrows()中的length参数(并在barplot()中使用border=NA来美化问题)。 - Stephan Kolassa

8

使用ggplot2中的geom_bargeom_errorbar实现:

library(ggplot2)
ggplot(df, aes(x=row.names(df), y=V1)) +
  geom_bar(stat="identity", fill="grey") +
  geom_errorbar(aes(ymin = V1 - V2, ymax = V1 + V2), width=0.6) +
  theme_classic() 

这将导致:

enter image description here

如果您想要移除x轴上的数字,可以添加如下代码:
  theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

将其添加到您的ggplot代码中。


使用的数据:

df <- read.table(text="-4.6521175 0.145839723
 1.1744100 0.342278694
-0.2581400 0.003776341
-0.3452675 0.073241199
-2.3823650 0.095008502
 0.5625125 0.021627196", header=FALSE)

作为对 你的评论 的回应,当你想绘制如此大量的条形图时,有两种可能的解决方案:

1:仅包含一部分坐标轴标签:

ggplot(df2, aes(x=as.numeric(row.names(df2)), y=V1)) +
  geom_bar(stat="identity", fill="grey", width=0.7) +
  geom_errorbar(aes(ymin = V1 - V2, ymax = V1 + V2), width=0.5) +
  scale_x_continuous(breaks=c(1,seq(10,200,10)), expand=c(0,0)) +
  theme_classic() +
  theme(axis.text.x=element_text(size = 6, angle = 90, vjust = 0.5))

这将给出:

enter image description here

可以看出,在图表中塞入太多的条形并不理想。因此,请参考备选方案2。
2:创建一个分组变量,可用于创建小面板:
df2$id <- rep(letters[1:20], each=10)

ggplot(df2, aes(x=as.numeric(row.names(df2)), y=V1)) +
  geom_bar(stat="identity", fill="grey", width=0.7) +
  geom_errorbar(aes(ymin = V1 - V2, ymax = V1 + V2), width=0.5) +
  scale_x_continuous(breaks=as.numeric(row.names(df2))) +
  facet_wrap(~ id, scales = "free_x") +
  theme_bw() +
  theme(axis.text.x=element_text(angle = 90, vjust = 0.5))

这将给出:

enter image description here

使用了最后两个示例的数据:

df2 <- data.frame(V1=sample(df$V1, 200, replace=TRUE),
                  V2=sample(df$V2, 200, replace=TRUE))

非常感谢Jaap和Stephan。如果我要从文件中读取值(因为实际上它们来自那里),该怎么办?该文件没有标题。我执行x=read.table('some.file'),现在我需要将涉及的两个向量(x$V1,x$V2)传递给ggplot。我该怎么做? - Stefan
1
@Stefan 为了减少数字所需的空间,您可以使用 theme(axis.text.x = element_text(size = 6, angle = 90, vjust = 0.5)) - Jaap
哎呀,抱歉,我误点了。 - Stefan
Jaap,我尝试使用theme(),但似乎元素数量太多,它们会绕过轴。我在轴的开头看到数字100。 - Stefan
再次向您致敬,尊敬的先生。非常感谢您。 - Stefan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接