korzystanie z funkcji stat i facet wrap razem w ggplot2 w R

Próbuję wykreślić dane typu kratowego za pomocą ggplot2, a następnie nałożyć rozkład normalny na przykładowe dane, aby zilustrować, jak daleko od normalnych danych jest. Chciałbym, aby normalny dist na górze miał taką samą średnią i stdev jak panel.

Oto przykład:

library(ggplot2)

#make some example data
dd<-data.frame(matrix(rnorm(144, mean=2, sd=2),72,2),c(rep("A",24),rep("B",24),rep("C",24)))
colnames(dd) <- c("x_value", "Predicted_value",  "State_CD")

#This works
pg <- ggplot(dd) + geom_density(aes(x=Predicted_value)) +  facet_wrap(~State_CD)
print(pg)

To wszystko działa świetnie i tworzy ładny wykres trzech paneli danych. Jak dodać normalny dist na górze? Wygląda na to, że użyłbym stat_function, ale to

#this fails
pg <- ggplot(dd) + geom_density(aes(x=Predicted_value)) + stat_function(fun=dnorm) +  facet_wrap(~State_CD)
print(pg)

Wygląda na to, że stat_function nie dogaduje się z funkcją facet_wrap. Jak sprawić, by ci dwaj grali ładnie?

------------edytuj---------

Próbowałem zintegrować pomysły z dwóch z poniższych odpowiedzi i nadal mnie tam nie ma:

Korzystając z kombinacji obu odpowiedzi mogę zhakować razem to:

library(ggplot)
library(plyr)

#make some example data
dd<-data.frame(matrix(rnorm(108, mean=2, sd=2),36,2),c(rep("A",24),rep("B",24),rep("C",24)))
colnames(dd) <- c("x_value", "Predicted_value",  "State_CD")

DevMeanSt <- ddply(dd, c("State_CD"), function(df)mean(df$Predicted_value)) 
colnames(DevMeanSt) <- c("State_CD", "mean")
DevSdSt <- ddply(dd, c("State_CD"), function(df)sd(df$Predicted_value) )
colnames(DevSdSt) <- c("State_CD", "sd")
DevStatsSt <- merge(DevMeanSt, DevSdSt)

pg <- ggplot(dd, aes(x=Predicted_value))
pg <- pg + geom_density()
pg <- pg + stat_function(fun=dnorm, colour='red', args=list(mean=DevStatsSt$mean, sd=DevStatsSt$sd))
pg <- pg + facet_wrap(~State_CD)
print(pg)
Co jest naprawdę blisko... tylko że coś jest nie tak z normalnym dist plotdata = ]}

Tutaj wpisz opis obrazka

Co ja tu robię źle?
Author: JD Long, 2009-09-04

4 answers

stat_function jest przeznaczony do nakładania tej samej funkcji w każdym panelu. (Nie ma oczywistego sposobu dopasowania parametrów funkcji do różnych paneli).

Jak sugeruje Ian, najlepszym sposobem jest wygenerowanie normalnych krzywych samodzielnie i wykreśl je jako oddzielny zestaw danych (tutaj wcześniej się nie zgadzałeś - łączenie nie ma sensu w tym przykładzie i jeśli przyjrzysz się uważnie, zobaczysz, że właśnie dlatego otrzymujesz dziwny wzór piłokształtny).

Oto jak rozwiązałbym ten problem:

dd <- data.frame(
  predicted = rnorm(72, mean = 2, sd = 2),
  state = rep(c("A", "B", "C"), each = 24)
) 

grid <- with(dd, seq(min(predicted), max(predicted), length = 100))
normaldens <- ddply(dd, "state", function(df) {
  data.frame( 
    predicted = grid,
    density = dnorm(grid, mean(df$predicted), sd(df$predicted))
  )
})

ggplot(dd, aes(predicted))  + 
  geom_density() + 
  geom_line(aes(y = density), data = normaldens, colour = "red") +
  facet_wrap(~ state) 

Tutaj wpisz opis obrazka

 34
Author: hadley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 17:09:42

Myślę, że musisz podać więcej informacji. To chyba działa:

 pg <- ggplot(dd, aes(Predicted_value)) ## need aesthetics in the ggplot
 pg <- pg + geom_density() 
 ## gotta provide the arguments of the dnorm
 pg <- pg + stat_function(fun=dnorm, colour='red',            
            args=list(mean=mean(dd$Predicted_value), sd=sd(dd$Predicted_value)))
 ## wrap it!
 pg <- pg + facet_wrap(~State_CD)
 pg

Zapewniamy ten sam parametr mean I sd dla każdego panelu. Uzyskanie konkretnych środków i odchyleń standardowych jest pozostawione jako ćwiczenie dla czytelnika*;)

' * ' innymi słowy, Nie wiem, jak to zrobić...

 3
Author: Eduardo Leoni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-04 03:04:08

Myślę, że najlepiej będzie narysować linię ręcznie za pomocą geom_line.

dd<-data.frame(matrix(rnorm(144, mean=2, sd=2),72,2),c(rep("A",24),rep("B",24),rep("C",24)))
colnames(dd) <- c("x_value", "Predicted_value",  "State_CD")
dd$Predicted_value<-dd$Predicted_value*as.numeric(dd$State_CD) #make different by state

##Calculate means and standard deviations by level
means<-as.numeric(by(dd[,2],dd$State_CD,mean))
sds<-as.numeric(by(dd[,2],dd$State_CD,sd))

##Create evenly spaced evaluation points +/- 3 standard deviations away from the mean
dd$vals<-0
for(i in 1:length(levels(dd$State_CD))){
    dd$vals[dd$State_CD==levels(dd$State_CD)[i]]<-seq(from=means[i]-3*sds[i], 
                            to=means[i]+3*sds[i],
                            length.out=sum(dd$State_CD==levels(dd$State_CD)[i]))
}
##Create normal density points
dd$norm<-with(dd,dnorm(vals,means[as.numeric(State_CD)],
                        sds[as.numeric(State_CD)]))


pg <- ggplot(dd, aes(Predicted_value)) 
pg <- pg + geom_density() 
pg <- pg + geom_line(aes(x=vals,y=norm),colour="red") #Add in normal distribution
pg <- pg + facet_wrap(~State_CD,scales="free")
pg
 1
Author: Ian Fellows,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-04 14:41:52

Jeśli nie chcesz generować normalnego wykresu linii dystrybucyjnej "ręcznie", nadal używaj stat_function i wyświetlaj wykresy obok siebie -- wtedy możesz rozważyć użycie funkcji " multipot "opublikowanej w" Cookbook for R " jako alternatywy dla facet_wrap. Możesz skopiować kod multipot do swojego projektu stąd .

Po skopiowaniu kodu wykonaj następujące czynności:

# Some fake data (copied from hadley's answer)
dd <- data.frame(
  predicted = rnorm(72, mean = 2, sd = 2),
  state = rep(c("A", "B", "C"), each = 24)
) 

# Split the data by state, apply a function on each member that converts it into a 
# plot object, and return the result as a vector.
plots <- lapply(split(dd,dd$state),FUN=function(state_slice){ 
  # The code here is the plot code generation. You can do anything you would 
  # normally do for a single plot, such as calling stat_function, and you do this 
  # one slice at a time.
  ggplot(state_slice, aes(predicted)) + 
    geom_density() + 
    stat_function(fun=dnorm, 
                  args=list(mean=mean(state_slice$predicted), 
                            sd=sd(state_slice$predicted)),
                  color="red")
})

# Finally, present the plots on 3 columns.
multiplot(plotlist = plots, cols=3)

Tutaj wpisz opis obrazka

 1
Author: AmitA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 17:24:59