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

use*_*421 85 r histogram curve-fitting r-faq

R中是否有适合直方图曲线的函数?

假设您有以下直方图

hist(c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4)))
Run Code Online (Sandbox Code Playgroud)

它看起来很正常,但它是偏斜的.我想要拟合一条倾斜的正常曲线来包裹这个直方图.

这个问题相当基本,但我似乎无法在互联网上找到R的答案.

Dir*_*tel 149

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

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
Run Code Online (Sandbox Code Playgroud)

编辑很久以后:

这是一个稍微装扮一点的版本:

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) 
Run Code Online (Sandbox Code Playgroud)

以及它产生的图表:

在此输入图像描述

  • +1 - 您是否可以反过来做,即调整密度图以适合直方图? (3认同)
  • 我建议给`lines(density(X,na.rm = TRUE)`提供额外的参数,因为向量可能包含NA值. (2认同)

Thi*_*rry 29

使用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()
Run Code Online (Sandbox Code Playgroud)

或模仿Dirk解决方案的结果

ggplot(dataset, aes(x = X)) + 
  geom_histogram(aes(y = ..density..), binwidth = 5) + 
  geom_density()
Run Code Online (Sandbox Code Playgroud)


Joh*_*son 26

这是我的方式:

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

奖励练习是用ggplot2包来做的...

  • 我认为你误解了原始海报和所有其他答案都非常满足于使用非参数估计 - 如旧式直方图或更现代的数据驱动的密度估计.如果您有充分的理由怀疑分布,参数估计是很好的.但事实并非如此. (3认同)
  • 但这仍然需要首先估算您的分布参数. (2认同)

fma*_*ark 11

Dirk解释了如何在直方图上绘制密度函数.但是有时候你可能想要采用偏态正态分布的强假设,而不是密度.您可以估计分布的参数并使用sn包绘制它:

> 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 
Run Code Online (Sandbox Code Playgroud)

偏斜正态分布式数据图

对于更偏斜的数据,这可能更有效:

另一个偏正正常的情节