将错误栏添加到ggplot时出错

时间:2015-09-02 09:18:41

标签: r ggplot2 bar-chart errorbar

亲爱的Stackoverflow用户,

我想画一个带有误差条的三个独立变量的分组条形图。我使用ggplot和geom_bar将我的图表基于Stacked Overflow(分组条形图中的堆积条形)上的示例。当我根据帮助页面的示例添加geom_errorbar时,出现以下错误: Error in if (empty(data)) { : missing value where TRUE/FALSE needed

这是我使用的脚本:

treatment<-rep(c(rep(c(1),8),rep(c(2),8)),2)
origin<-rep(c("A","B"),16)
time<-c(rep(c(5),16),rep(c(10),16))
sulfide<-c(0,10,5,8,9,6,16,18,20,25,50,46,17,58,39,43,20,25,50,46,17,58,39,43,100,120,103,104,150,160,200,180)

Reed<-data.frame(treatment,origin,time,sulfide)

# specify factor types
Reed$treatment<-as.factor(Reed$treatment)
Reed$origin<-as.character(Reed$origin)
Reed$time<-as.factor(Reed$time)

library(ggplot2)
library(scales)

#draw plot
ggplot() +geom_bar(data=Reed, aes(y = sulfide, x = treatment, fill=origin), stat="identity",position="dodge") +theme_bw() + facet_grid( ~ time)+xlab("treatment") +ylab("Sulfide")+ggtitle("Time)")

这是我添加错误栏的方式:

ErrorBars <- function(x, y, upper, lower=upper, length=0.03,...{if(length(x) != length(y) | length(y) !=length(lower) | length(lower) != length(upper))stop("vectors must be same length")arrows(x,y+upper, x, y-lower, angle=90, code=3, length=length, ...)}#function for errorbars

SE<- function(x) sqrt(var(x,na.rm=TRUE)/length(na.omit(x))) #function for SE

Reed$trt<- paste(Reed$treatment,Reed$origin,sep="")#combine treatment and origin to a column 
mean_Reed<-data.frame(tapply(Reed$sulfide,list(Reed$trt,Reed$time),mean,na.rm=TRUE)) #mean
SE_Reed<-data.frame(tapply(Reed$sulfide,list(Reed$trt, Reed$time),SE)) # SE 

limits <- aes(ymax = mean_Reed + SE_Reed, ymin=mean_Reed - SE_Reed)# Define the top and bottom of the errorbars

#plot with error bars:
ggplot() +geom_bar(data=Reed, aes(y = sulfide, x = treatment, fill=origin), stat="identity",position="dodge") +theme_bw() + facet_grid( ~ time)+xlab("treatment") +ylab("Sulfide")+ggtitle("Time)"+ geom_errorbar(limits, width=.2,position="dodge") 

我真的找不到我做错了什么。 我希望你能帮助我:)。

2 个答案:

答案 0 :(得分:2)

如果要通过制作摘要数据集来构建误差线,则只需要以正确的格式获取该数据集。这有很多选择;我将使用 dplyr 。请注意,我将此数据集中的绘图中的所有分组变量保留在&#34; tidy&#34;格式,每个变量都在一个单独的列中。

library(dplyr)
meandat = Reed %>% 
    group_by(treatment, time, origin) %>%
    summarise(mean = mean(sulfide, na.rm = TRUE), se = SE(sulfide))

Source: local data frame [8 x 5]
Groups: treatment, time [?]

  treatment   time origin   mean        se
     (fctr) (fctr)  (chr)  (dbl)     (dbl)
1         1      5      A   7.50  3.378856
2         1      5      B  10.50  2.629956
3         1     10      A  31.50  7.858117
4         1     10      B  43.00  6.819091
5         2      5      A  31.50  7.858117
6         2      5      B  43.00  6.819091
7         2     10      A 138.25 23.552689
8         2     10      B 141.00 17.540429

现在可以通过geom_errorbar添加错误栏。您会看到我在ggplot内全局设置美学,以节省自己不得不重新输入其中一些,但您可以根据需要更改此项。我使用position_dodge来在每个条上正确放置误差线。

ggplot(data = Reed, aes(y = sulfide, x = treatment, fill=origin)) +
    geom_bar(stat="identity", position="dodge") +
    theme_bw() + 
    facet_grid( ~ time)+
    xlab("treatment") +
    ylab("Sulfide")+
    ggtitle("Time")+ 
    geom_errorbar(data = meandat, aes(ymin = mean - se, ymax = mean + se, y = mean), 
                position = position_dodge(width = .9))

enter image description here

您实际上可以通过stat_summary执行所有这些操作,而不是手动计算摘要统计信息&#34;#34;。一个例子是here。代码看起来像这样,并给出与上面相同的情节。

ggplot(data = Reed, aes(y = sulfide, x = treatment, fill=origin)) +
    geom_bar(stat="identity",position="dodge") +
    theme_bw() + 
    facet_grid( ~ time) +
    xlab("treatment") +
    ylab("Sulfide") +
    ggtitle("Time") + 
    stat_summary(geom = "errorbar", fun.data = mean_cl_normal, mult = 1, 
               position = position_dodge(width = .9))

我一直在使用 ggplot2 的开发版本,ggplot2_1.0.1.9003,发现我需要通过stat_summary添加fun.args个函数参数。这看起来像fun.args = list(mult = 1),以获得1个标准误差的误差条。

答案 1 :(得分:2)

暂且不考虑错误条的问题,你的情节会出现更严重的问题。您有treatmenttimeorigin各2个值,总共8个组合,但32个硫化物值 - 因此每个组合有4个硫化物值。当您使用例如

绘制此图时
ggplot(data=Reed) +
  geom_bar(aes(y = sulfide, x = treatment, fill=origin), stat="identity",position="dodge") +
  facet_grid( ~ time)+xlab("treatment") +ylab("Sulfide")

您正在以相同的颜色绘制所有四个硫化物值的条形图。这具有仅显示最大值的效果。有点难以相信这是你的意图,即使你做到了,也有更好的方法。例如,如果您想为每个因素组合绘制sulfide的平均值,您可以这样做。

ggp <- ggplot(data=Reed, aes(y = sulfide, x = as.factor(treatment), group=origin)) +
  geom_bar(aes(fill=origin), stat="summary", fun.y=mean, position="dodge") +
  theme_bw() + 
  facet_grid( ~ time)+xlab("treatment") +ylab("Sulfide")+ggtitle("Time")
ggp

这使用stat="summary"使用汇总函数meanfun.y=mean)自动汇总结果。

可以使用类似的方法非常简单地添加错误栏:

se <- function(y) sd(y)/length(y)   # to calculate standard error in the mean
ggp+stat_summary(geom="errorbar",position=position_dodge(width=0.85),
                 fun.data=function(y)c(ymin=mean(y)-se(y),ymax=mean(y)+se(y)), width=0.1)

请注意,无需在外部汇总数据 - ggplot为您执行此操作。

最后,这种方法有助于使用许多内置函数来产生更多统计严谨性的置信限制。

ggp+stat_summary(fun.data=mean_cl_normal, conf.int=0.95,
                 geom="errorbar",position=position_dodge(width=0.85), width=0.1)

所以在这里我们使用ggplot内置函数mean_cl_normal计算平均值的95%置信限,假设数据遵循正态分布(因此,均值将遵循t -分配)。我们使用参数conf.int=...来指定所需的置信区间,但默认值为0.95,因此在此示例中确实没有必要。

此类型还有其他一些功能:请参阅the documentation及其中的链接以获取解释。