在 ggplot2 中使用计数数据向直方图添加密度线

Posted

技术标签:

【中文标题】在 ggplot2 中使用计数数据向直方图添加密度线【英文标题】:Adding a density line to a histogram with count data in ggplot2 【发布时间】:2015-02-24 01:04:13 【问题描述】:

我想在直方图中添加一条密度线(实际上是正常密度)。

假设我有以下数据。我可以通过ggplot2绘制直方图:

set.seed(123)    
df <- data.frame(x = rbeta(10000, shape1 = 2, shape2 = 4))

ggplot(df, aes(x = x)) + geom_histogram(colour = "black", fill = "white", 
                                        binwidth = 0.01) 

我可以使用以下方法添加密度线:

ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y = ..density..),colour = "black", fill = "white", 
                 binwidth = 0.01) + 
  stat_function(fun = dnorm, args = list(mean = mean(df$x), sd = sd(df$x)))

但这不是我真正想要的,我希望这条密度线适合计数数据。

我发现了一个类似的帖子 (HERE) 提供了解决此问题的方法。但在我的情况下它不起作用。我需要一个任意的扩展因子来得到我想要的。这根本无法概括:

ef <- 100 # Expansion factor

ggplot(df, aes(x = x)) + 
  geom_histogram(colour = "black", fill = "white", binwidth = 0.01) + 
  stat_function(fun = function(x, mean, sd, n) 
    n * dnorm(x = x, mean = mean, sd = sd), 
    args = list(mean = mean(df$x), sd = sd(df$x), n = ef))

我可以用来概括这一点的任何线索

首先到正态分布, 然后到任何其他 bin 大小, 最后对任何其他发行版都非常有帮助。

【问题讨论】:

您的意思是两张图表图像相同吗?您好像上传了两次同一个 MASS 包中使用fitdistr(...) 来适应分布。 【参考方案1】:

拟合分布函数并不是凭空发生的。你必须明确地做到这一点。一种方法是在 MASS 包中使用 fitdistr(...)

library(MASS)    # for fitsidtr(...)
# excellent fit (of course...)
ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y=..density..),colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=dbeta,args=fitdistr(df$x,"beta",start=list(shape1=1,shape2=1))$estimate)

# horrible fit - no surprise here
ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y=..density..),colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=dnorm,args=fitdistr(df$x,"normal")$estimate)

# mediocre fit - also not surprising...
ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y=..density..),colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=dgamma,args=fitdistr(df$x,"gamma")$estimate)

编辑:回应 OP 的评论。

比例因子是 binwidth ✕ 样本大小。

ggplot(df, aes(x = x)) + 
  geom_histogram(colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=function(x,shape1,shape2)0.01*nrow(df)*dbeta(x,shape1,shape2),
                args=fitdistr(df$x,"beta",start=list(shape1=1,shape2=1))$estimate)

【讨论】:

感谢对不同分布的概括。我的最终目标是将这些线拟合到计数数据而不是密度。您对如何做到这一点有任何见解吗? (我想获得与原帖第三个情节相同的情节。) 公式 (0.01*nrow(df)*dbeta(x,shape1,shape2)) 中的 0.01 值不能推广到不同的 binwidth 或样本大小。假设我的样本大小为 2474(而不是 10000)和 0.03(而不是 0.01)。我认为 0.01 应该是 bin 宽度的函数,也可能是样本大小的函数。 它绝对可推广的。 0.01 是 binwidth。因此,如果您使用binwidth=0.03,那么您将在对stat_function(...) 的调用中使用fun=function(x,shape1,shape2)0.03*nrow(df)*dbeta(x,shape1,shape2)。当然,计数都会改变。 我的错误,它可以推广到不同的 bin 大小和样本大小。感谢您的解决方案。

以上是关于在 ggplot2 中使用计数数据向直方图添加密度线的主要内容,如果未能解决你的问题,请参考以下文章

R语言使用ggplot2包使用geom_density()函数绘制分组密度图(添加直方图分组颜色配置)实战(density plot)

R语言ggplot2可视化:可视化人口金字塔图直方图(堆叠直方图连续变量堆叠直方图离散变量堆叠直方图)密度图箱图(添加抖动数据点tufte箱图多分类变量分组箱图)小提琴图

ggplot2中具有分组密度线的直方图

在 ggplot2 中创建密度直方图?

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

R语言ggplot2可视化:可视化堆叠的直方图添加每个分组的每个bin的计数标签在堆叠直方图的bin中的每个分组部分添加数值标签