用密度曲线叠加直方图

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 &lt;- 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)

使用 ggplot2 沿平滑曲线绘制直方图或密度