用密度曲线叠加直方图
Posted
技术标签:
【中文标题】用密度曲线叠加直方图【英文标题】:Overlay histogram with density curve 【发布时间】:2011-08-06 23:33:46 【问题描述】:我正在尝试制作密度值的直方图,并将其与密度函数曲线(不是密度估计值)叠加。
使用一个简单的标准正常示例,这里是一些数据:
x <- rnorm(1000)
我能做到:
q <- qplot( x, geom="histogram")
q + stat_function( fun = dnorm )
但这给出了直方图的频率比例而不是密度。使用..density..
,我可以在直方图上得到正确的比例:
q <- qplot( x,..density.., geom="histogram")
q
但是现在这给出了一个错误:
q + stat_function( fun = dnorm )
有什么我没看到的吗?
另一个问题,有没有办法绘制函数的曲线,比如curve()
,但不是作为层?
【问题讨论】:
问题是您已经使用 ..density.. 在qplot
中为您的绘图定义了一个全局 y。这让stat_function
感到困惑。最简单的解决方法是写qplot(x, geom = 'blank') + geom_histogram(aes(y = ..density..)) + stat_function(fun = dnorm)
。下面看我的详细回答
相当于curve(dnorm, -4, 4)
将是qplot(x = -4:4, stat = 'function', fun = dnorm, geom = 'line')
啊,对了,我尝试将函数作为第一个参数,但现在看看出了什么问题。谢谢!
【参考方案1】:
给你!
# create some data to work with
x = rnorm(1000);
# overlay histogram, empirical density and normal density
p0 = qplot(x, geom = 'blank') +
geom_line(aes(y = ..density.., colour = 'Empirical'), stat = 'density') +
stat_function(fun = dnorm, aes(colour = 'Normal')) +
geom_histogram(aes(y = ..density..), alpha = 0.4) +
scale_colour_manual(name = 'Density', values = c('red', 'blue')) +
theme(legend.position = c(0.85, 0.85))
print(p0)
【讨论】:
P.S.如果使用真实数据,请确保将经验均值和 sd 参数传递给 dnorm 函数,请参阅 stat_function 语法帮助。 只是出于好奇:如何使用 ggplot() 函数来完成?我几乎不理解 ggplot() 的工作方式,所以我觉得用这种方法处理我的东西有点奇怪。 @Jemus42 你可以把第一行换成这样的东西 "ggplot(data.frame(x), aes(x=x)) +" @Jemus42 为什么会这样?如果没有将 args 中的 mean 和 sd 传递给 stat_function,我什么也得不到。 叠加直方图和密度估计存在一个问题,即密度估计实际上应该移动半个 bin 宽度,以实现最准确和美观的呈现。我一直无法弄清楚如何做到这一点。有接受者吗?【参考方案2】:Ramnath 答案的更简单的替代方案,传递观察到的平均值和标准差,并使用 ggplot
而不是 qplot
:
df <- data.frame(x = rnorm(1000, 2, 2))
# overlay histogram and normal density
ggplot(df, aes(x)) +
geom_histogram(aes(y = stat(density))) +
stat_function(
fun = dnorm,
args = list(mean = mean(df$x), sd = sd(df$x)),
lwd = 2,
col = 'red'
)
【讨论】:
这是一个非常方便的答案,因为它提供了一种绘制直方图和密度曲线的方法,即使它们属于不同的分布,如果需要(就像我一样)。谢谢! 最初的问题是关于拟合密度曲线,而不是特别是单个高斯曲线。如果您想查看此解决方案为何不起作用,请尝试将数据设置为df <- data.frame(x = c(rnorm(1000, 2, 2), rnorm(1000, 12, 2)))
@Megatron,不,OP 要求“密度函数的曲线(不是密度估计)”。所以我仍然认为这是正确的。您的示例表明,在某些情况下,正态密度函数可能不能很好地描述数据,但这不是重点。【参考方案3】:
从ggplot2
使用geom_density()
怎么样?像这样:
df <- data.frame(x = rnorm(1000, 2, 2))
ggplot(df, aes(x)) +
geom_histogram(aes(y=..density..)) + # scale histogram y
geom_density(col = "red")
这也适用于多模态分布,例如:
df <- data.frame(x = c(rnorm(1000, 2, 2), rnorm(1000, 12, 2), rnorm(500, -8, 2)))
ggplot(df, aes(x)) +
geom_histogram(aes(y=..density..)) + # scale histogram y
geom_density(col = "red")
【讨论】:
因为 OP 要求 “密度函数的曲线(不是密度估计)”。geom_density
给出密度估计。
也许不是 OP 所要求的,但这确实对我正在寻找的东西有所帮助!以上是关于用密度曲线叠加直方图的主要内容,如果未能解决你的问题,请参考以下文章
R语言自定义编写函数生成学生化残差的直方图(dist of studentized residuals),并叠加标准正太曲线核密度曲线轴须图rug曲线检验模型是否满足正态性(normality)
Python中Pandas/Matplotlib中直方图和密度的叠加
r语言中,画出了频率分布直方图,怎么在图上添加概率分布曲线?
R语言plotly可视化:plotly可视化多个数据集归一化直方图(historgram)并在直方图中添加密度曲线kde(核密度估计的密度曲线density plot)