/ / Błąd podczas dodawania błędów do ggplot - r, ggplot2, bar-chart, errorbar

Błąd podczas dodawania błędów do ggplot - r, ggplot2, bar-chart, errorbar

Drodzy użytkownicy Stackoverflow,

Chciałbym narysować zgrupowany barplot z trzemazmienne niezależne z paskami błędów. Oparłem swój wykres na przykładzie na Stacked Overflow (stosy słupków w zgrupowanych prętach), używając ggplot z geom_bar. Kiedy dodaję geom_errorbar zgodnie z przykładami stron pomocy, pojawia się następujący błąd: Error in if (empty(data)) { : missing value where TRUE/FALSE needed

To jest skrypt, którego używam:

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)")

Oto, jak dodałem paski błędów:

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")

Naprawdę nie mogę znaleźć tego, co robię źle. Mam nadzieję że możesz mi pomóc:)

Odpowiedzi:

2 dla odpowiedzi № 1

Pomijając kwestię słupków błędów na chwilę, jest znacznie poważniejszy problem z twoją fabułą. treatment, time, i origin, w sumie 8 kombinacji, ale 32 wartości siarczku - więc istnieją 4 wartości siarczku dla każdej kombinacji. Podczas kreślenia tego przy użyciu np.

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

kreślisz paski dla wszystkie cztery wartości siarczków jeden na drugim w całymtaki sam kolor. Skutkuje to wyświetlaniem tylko wartości maksymalnej. Trochę trudno jest uwierzyć, że to jest to, co zamierzałeś, a nawet jeśli zrobiłeś, to jest lepszy sposób na zrobienie tego. Na przykład, jeśli chcesz wykreślić średnią wartość sulfide dla każdej kombinacji czynników możesz to zrobić w ten sposób.

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

To wykorzystuje stat="summary" aby automatycznie podsumować wynik za pomocą funkcji agregującej mean (fun.y=mean).

Podobne podejście można zastosować, aby po prostu dodać paski błędów:

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)

Zauważ, że nie ma potrzeby agregowania danych na zewnątrz - ggplot robi to za Ciebie.

Wreszcie, takie podejście pozwala na użycie wielu wbudowanych funkcji do generowania limitów ufności z większą dokładnością statystyczną.

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

Więc tutaj używamy ggplot wbudowana funkcja mean_cl_normal obliczyć granice ufności 95% średniej, zakładając, że dane następują po normalnym rozkładzie (i że w związku z tym środki będą następować po t-dystrybucji). Używamy argumentu conf.int=... aby określić żądany przedział ufności, ale wartość domyślna to 0,95, więc naprawdę nie było to konieczne w tym przykładzie.

Istnieje jeszcze kilka innych funkcji tego typu: patrz dokumentacja i linki do nich w celu wyjaśnienia.


2 dla odpowiedzi nr 2

Jeśli chcesz zbudować paski błędów, tworząc zestaw danych podsumowujących, wystarczy pobrać ten zestaw danych w odpowiednim formacie. Istnieje wiele opcji na to; Użyję dplyr. Uwaga: Zachowuję wszystkie zmienne grupowania z wykresu w tym zbiorze danych w "tidy" formacie, z każdą zmienną w osobnej kolumnie.

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

Teraz paski błędów można dodać za pośrednictwem geom_errorbar. Zobaczysz, że ustawiam estetykę na całym świecie ggplot aby zaoszczędzić sobie konieczności ponownego wpisywania niektórych z nich, ale możesz to zmienić w dowolny sposób. używam position_dodge aby poprawnie umieścić paski błędów na każdym pasku.

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))

wprowadź opis obrazu tutaj

Możesz to zrobić w całości stat_summaryzamiast obliczać statystyki podsumowujące "ręcznie". Przykładem jest tutaj. Kod wyglądałby tak i daje tę samą fabułę, co powyżej.

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))

Używałem wersji rozwojowej ggplot2, ggplot2_1.0.1.9003, i okazało się, że muszę dodać stat_summary argumenty funkcji via fun.args. To by wyglądało fun.args = list(mult = 1) aby uzyskać paski błędów z 1 standardowym błędem.