在R中的GGPLOT2中一起使用stat_function和facet_wrap

我试图用GGPLOT2绘制格型数据,然后在样本数据上叠加一个正态分布来说明底层数据有多远。 我希望有一个正常的发展方向与面板具有相同的意思和定义。

这里是一个例子:

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) 

这一切都很好,并产生一个很好的数据面板图。 如何在顶部添加正常的dist? 看来我会使用stat_function,但是这个失败:

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

看来stat_function与facet_wrapfunction不兼容。 我如何让这两个玩得很好?

– – – – – – 编辑 – – – – –

我试图整合来自下面两个答案的想法,但我仍然不在那里:

使用两个答案的组合我可以破解在一起:

 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) 

这是非常接近的…除了一些正常的dist绘图错误:

在这里输入图像描述

我在这里做错了什么?

stat_function被devise为在每个面板上覆盖相同的function。 (没有明显的方法来匹配不同面板的function参数)。

正如伊恩所build议的,最好的方法是自己生成正常的曲线,并将它们作为一个单独的数据集(这是以前出错的地方 – 合并对这个例子没有意义,如果仔细观察,看到这就是为什么你得到奇怪的锯齿图案)。

以下是我如何解决这个问题:

 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) 

在这里输入图像描述

我想你需要提供更多的信息。 这似乎工作:

  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 

我们为每个面板提供相同的平均值和sd参数。 获取面板的具体手段和标准偏差留给读者的练习*;)

'*'换句话说,不知道如何做…

我认为你最好的select是用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 

如果你不想手动生成正态分布线图,仍然使用stat_function,并排显示graphics – 那么你可以考虑使用“Cookbook for R”上发布的“多槽”函数,作为facet_wrap的替代品。 您可以从这里复制多槽代码到您的项目。

复制代码后,请执行以下操作:

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

在这里输入图像描述