我在寻找最优雅的方法来叠加正态分布在ggplot2
中的分组直方图中。我知道这个问题以前已经问过很多次了,但我觉得没有一个选项(比如this one或this one )是非常优雅的,至少除非可以让stat_function
处理数据的每一个特定部分。
将正态分布叠加到非分组直方图上的一种比较优雅的方法是使用geom_smooth
和method="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))
不过,我想知道这种方法是否也可以用于在分组直方图中添加正态分布。
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")
我还想知道是否有可能为+ stat_distrfit()
或+ stat_normfit(
定义ggplot2
的包(有可能进行分组)?(我什么也找不到,但这似乎是一项很普通的任务,所以我只是想知道)
我之所以希望代码尽可能简短,是因为这是为了一门课程,我想让事情尽可能简单.
PS geom_density
不适合我的目标,我也想绘制计数/频率,而不是密度。我也希望将它们放在同一个面板中,并避免使用facet_wrap
发布于 2015-09-06 10:56:44
是像这样吗?
## 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(...)
的问题是不能使用aes(...)
映射args=...
列表,正如注释中的帖子所解释的那样。因此,您必须创建一个辅助data.frame (本例中的gg
),它具有拟合分布的x和y值,并使用geom_line(...)
。
上面的代码在fitdistr(...)
包中使用MASS
来计算按性别分组的数据的平均和sd的最大可能性估计,基于正常假设(如果这有意义的话,可以使用不同的分布)。然后,它通过将weight
中的范围划分为100个增量来创建x轴,并计算适当的平均值和sd的dnorm(x,...)
。由于结果是密度,我们必须使用以下方法来调整:
gg$y <- gg$y * aggregate(weight~sex, weight,length)$weight * diff(range(weight$weight))/30
因为您想要将此映射到计数数据。请注意,这假设您在geom_histogram中使用默认的绑定(它将x中的范围划分为30个相等的增量)。最后,我们使用geom_line(...)
作为特定于层的数据集,添加对gg
的调用.
https://stackoverflow.com/questions/32423372
复制相似问题