R:在ggplot2

时间:2015-09-06 12:06:31

标签: r ggplot2 histogram normal-distribution

我正在寻找最优雅的方法,将正态分布拟合叠加在ggplot2的分组直方图中。我知道这个问题之前已被多次询问过,但是this onethis one等提议的选项都没有让我感到非常优雅,至少除非stat_function可以使用在数据的每个特定小节上。

将正态分布拟合叠加到我遇到的非分组直方图上的一种相对优雅的方法是使用geom_smoothmethod="nls"(除了事实之外它不是一个自启动功能,必须指定起始值):

library(ggplot2)
myhist = data.frame(size = 10:27, counts = c(1L, 3L, 5L, 6L, 9L, 14L, 13L, 23L, 31L, 40L, 42L, 22L, 14L, 7L, 4L, 2L, 2L, 1L) )
ggplot(data=myhist, aes(x=size, y=counts)) + geom_point() + 
     geom_smooth(method="nls", formula = y ~ N * dnorm(x, m, s), se=F, 
                 start=list(m=20, s=5, N=300)) 

enter image description here

我想知道这种方法是否也可用于将正态分布拟合添加到分组直方图中,如

library(devtools)
install_github("tomwenseleers/easyGgplot2",type="source")
library("easyGgplot2") # load weight data
ggplot(weight,aes(x = weight)) + 
+     geom_histogram(aes(y = ..count.., colour=sex, fill=sex),alpha=0.5,position="identity")

enter image description here

我还想知道是否有任何可能为+ stat_distrfit()定义+ stat_normfit(ggplot2}的软件包(有可能进行分组)? (我无法找到任何东西,但这似乎是一项非常普遍的任务,所以我只是想知道)

我希望代码尽可能短的原因是这是针对一门课程的,我想让事情尽可能简单......

PS geom_density不适合我的目标,我也想绘制计数/频率而不是密度。我也希望将它们放在同一个面板中,并避免使用facet_wrap

1 个答案:

答案 0 :(得分:2)

喜欢这个吗?

$this->createFormBuilder(null, array(
    'attr' => array(
          'class' => 'delete-action-form'
    )
));

我认为“优雅”在旁观者的眼中。使用## simulate your dataset - could not get easyGplot2 to load.... set.seed(1) # for reproducible example weight <- data.frame(sex=c("Female","Male"), weight=rnorm(1000,mean=c(65,67),sd=1)) library(ggplot2) library(MASS) # for fitdistr(...) get.params <- function(z) with(fitdistr(z,"normal"),estimate[1:2]) df <- aggregate(weight~sex, weight, get.params) df <- data.frame(sex=df[,1],df[,2]) x <- with(weight, seq(min(weight),max(weight),len=100)) gg <- data.frame(weight=rep(x,nrow(df)),df) gg$y <- with(gg,dnorm(x,mean,sd)) gg$y <- gg$y * aggregate(weight~sex, weight,length)$weight * diff(range(weight$weight))/30 ggplot(weight,aes(x = weight, colour=sex)) + geom_histogram(aes(y = ..count.., fill=sex), alpha=0.5,position="identity") + geom_line(data=gg, aes(y=y)) 的问题在于stat_function(...)列表无法使用args=...进行映射,正如评论中的帖子所述。因此,您必须创建一个辅助data.frame(在此示例中为aes(...)),其中包含拟合分布的x和y值,并使用gg

上面的代码使用geom_line(...)包中的fitdistr(...)来计算数据的均值和sd的最大似然估计值,按性别分组,基于正态性假设(您可以使用不同的分布如果这是有道理的)。然后通过将MASS中的范围分成100个增量来创建x轴,并计算weight的适当均值和sd。由于结果是密度,我们必须使用以下方法进行调整:

dnorm(x,...)

因为您要将其映射到计数数据。请注意,这假设您使用geom_histogram中的默认分箱(将x中的范围分成30个相等的增量)。最后,我们使用gg$y <- gg$y * aggregate(weight~sex, weight,length)$weight * diff(range(weight$weight))/30 将调用添加到geom_line(...)作为特定于图层的数据集。