将密度曲线拟合到R中的直方图

Posted

技术标签:

【中文标题】将密度曲线拟合到R中的直方图【英文标题】:Fitting a density curve to a histogram in R 【发布时间】:2010-12-02 14:57:37 【问题描述】:

R 中有没有一个函数可以将曲线拟合到直方图?

假设您有以下直方图

hist(c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4)))

它看起来很正常,但它是歪斜的。我想拟合一条倾斜的正态曲线以环绕该直方图。

这个问题比较基础,但是我好像在网上找不到 R 的答案。

【问题讨论】:

您想找到 m 和 s 以使高斯分布 N(m,s) 适合您的数据吗? 我不确定这是什么意思... >_> @mathee:我认为他的意思是 m = 平均值,s = 标准差。高斯分布是正态分布的别称。 【参考方案1】:

一些 cmets 要求将密度估计线缩放到直方图的峰值,以便 y 轴保持为计数而不是密度。为了实现这一点,我编写了一个小函数来自动拉取最大 bin 高度并相应地缩放密度函数的 y 维度。

hist_dens <- function(x, breaks = "Scott", main = "title", xlab = "x", ylab = "count") 
  
  dens <- density(x, na.rm = T)
  
  raw_hist <- hist(x, breaks = breaks, plot = F)
  
  scale <- max(raw_hist$counts)/max(raw_hist$density)
  
  hist(x, breaks = breaks, prob = F, main = main, xlab = xlab, ylab = ylab)
  
  lines(list(x = dens$x, y = scale * dens$y), col = "red", lwd = 2)
  


hist_dens(rweibull(1000, 2))

由reprex package (v2.0.1) 于 2021 年 12 月 19 日创建

【讨论】:

【参考方案2】:

这是核密度估计,请点击this link查看概念及其参数的精彩插图。

曲线的形状主要取决于两个元素:1)内核(通常是Epanechnikov or Gaussian),它通过输入和加权所有数据来为x坐标中的每个值估计y坐标中的一个点;它是对称的,通常是一个集成为一个的正函数; 2)带宽,越大曲线越平滑,越小曲线越摆动。

针对不同的需求,应用不同的包,可以参考这个文档:Density estimation in R。而对于多元变量,您可以转向multivariate kernel density estimation。

【讨论】:

【参考方案3】:

我遇到了同样的问题,但 Dirk 的解决方案似乎不起作用。 我每次都收到这个警告信息

"prob" is not a graphical parameter

我通读了?hist,发现了freq: a logical vector set TRUE by default.

对我有用的代码是

hist(x,freq=FALSE)
lines(density(x),na.rm=TRUE)

【讨论】:

【参考方案4】:

ggplot2 很容易做到这一点

library(ggplot2)
dataset <- data.frame(X = c(rep(65, times=5), rep(25, times=5), 
                            rep(35, times=10), rep(45, times=4)))
ggplot(dataset, aes(x = X)) + 
  geom_histogram(aes(y = ..density..)) + 
  geom_density()

或模仿德克解决方案的结果

ggplot(dataset, aes(x = X)) + 
  geom_histogram(aes(y = ..density..), binwidth = 5) + 
  geom_density()

【讨论】:

【参考方案5】:

如果我正确理解您的问题,那么您可能需要密度估计和直方图:

X <- c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4))
hist(X, prob=TRUE)            # prob=TRUE for probabilities not counts
lines(density(X))             # add a density estimate with defaults
lines(density(X, adjust=2), lty="dotted")   # add another "smoother" density

稍后再编辑:

这是一个稍微打扮的版本:

X <- c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4))
hist(X, prob=TRUE, col="grey")# prob=TRUE for probabilities not counts
lines(density(X), col="blue", lwd=2) # add a density estimate with defaults
lines(density(X, adjust=2), lty="dotted", col="darkgreen", lwd=2) 

连同它产生的图表:

【讨论】:

+1 - 你也可以反过来做,即调整密度图以适应直方图吗? 我建议给 lines(density(X,na.rm= TRUE) 额外的参数,因为向量可能包含 NA 值。 我刚刚添加了一个新答案below,它具有调整密度图以适应直方图的功能。【参考方案6】:

这是我的做法:

foo <- rnorm(100, mean=1, sd=2)
hist(foo, prob=TRUE)
curve(dnorm(x, mean=mean(foo), sd=sd(foo)), add=TRUE)

一个额外的练习是使用 ggplot2 包来做到这一点......

【讨论】:

但是,如果你想要一些偏斜的东西,你可以从上面做密度示例,转换你的数据(例如 foo.log <- log(foo) 并尝试上面的方法),或者尝试拟合偏态分布,例如 gamma 或对数正态(对数正态相当于取对数并拟合正态,顺便说一句)。 但这仍然需要首先估计您的分布参数。 这与简单讨论 R 有点远,因为我们正在更多地研究理论统计,但您可以尝试 Gamma 的此链接:en.wikipedia.org/wiki/Gamma_distribution#Parameter_estimation 对于对数正态,只需获取日志(假设所有数据都是正数)并使用对数转换的数据。对于任何更高级的东西,我认为您必须使用统计教科书。 我认为您误解了原始海报以及所有其他答案都非常满足于使用非参数估计 - 例如老式直方图或更现代的数据驱动密度估计.如果您有充分的理由怀疑分布,则参数估计非常有用。但这里不是这样。【参考方案7】:

Dirk 解释了如何在直方图上绘制密度函数。但有时您可能希望采用更强有力的偏态正态分布假设并绘制它而不是密度。您可以估计分布的参数并使用sn package 绘制它:

> sn.mle(y=c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4)))
$call
sn.mle(y = c(rep(65, times = 5), rep(25, times = 5), rep(35, 
    times = 10), rep(45, times = 4)))

$cp
    mean     s.d. skewness 
41.46228 12.47892  0.99527 

这可能更适合偏斜正常的数据:

【讨论】:

以上是关于将密度曲线拟合到R中的直方图的主要内容,如果未能解决你的问题,请参考以下文章

excel曲线拟合中的决定系数R平方是如何求出来的?

R语言rms包生存分析之限制性立方样条(RCS, Restricted cubic spline)分析:拟合连续性自变量和事件风险之间的关系并绘制直方图平滑曲线双Y轴于同一个图像中

拟合和比较 R 中的多个 sigmoid 曲线

Scipy曲线拟合无法将数据准确拟合到傅里叶级数

r语言怎么画y=x1+x2+x3的曲线拟合图

excel在模拟曲线时的R值是如何计算的,代表啥意思?