如何将曲线拟合到直方图上

5

我已经探索了关于这个主题的类似问题,但是在我的直方图上产生一个漂亮的曲线有些困难。我知道有些人可能认为这是重复的,但我目前没有找到任何可以帮助解决我的问题的东西。

虽然这里看不到数据,但以下是我正在使用的一些变量,这样你就可以在下面的代码中看到它们代表什么。

Differences <- subset(Score_Differences, select = Difference, drop = T)
m = mean(Differences)
std = sqrt(var(Differences))

这是我生成的第一条曲线(代码看起来最常见且易于生成,但曲线本身并不很适合)。
hist(Differences, density = 15, breaks = 15, probability = TRUE, xlab = "Score Differences", ylim = c(0,.1), main = "Normal Curve for Score Differences")
curve(dnorm(x,m,std),col = "Red", lwd = 2, add = TRUE)

enter image description here

我非常喜欢这个,但不喜欢曲线进入负区域。
hist(Differences, probability = TRUE)
lines(density(Differences), col = "Red", lwd = 2)
lines(density(Differences, adjust = 2), lwd = 2, col = "Blue")

enter image description here

这是与第一个相同的直方图,但附带频率。仍然不太好看。
h = hist(Differences, density = 15, breaks = 15, xlab = "Score Differences", main = "Normal Curve for Score Differences")
xfit = seq(min(Differences),max(Differences))
yfit = dnorm(xfit,m,std)
yfit = yfit*diff(h$mids[1:2])*length(Differences)
lines(xfit, yfit, col = "Red", lwd = 2)

enter image description here

尝试了另一种方法,但仍没有成功。可能是因为在明显不正常的数据情况下使用了qnorm,曲线再次向负方向倾斜。

sample_x = seq(qnorm(.001, m, std), qnorm(.999, m, std), length.out = l)
binwidth = 3
breaks = seq(floor(min(Differences)), ceiling(max(Differences)), binwidth)
hist(Differences, breaks)
lines(sample_x, l*dnorm(sample_x, m, std)*binwidth, col = "Red")

enter image description here

唯一看起来好看的曲线是第二个,但是曲线向负方向倾斜。
我的问题是:“在直方图上放置曲线是否有“标准方法”?”这些数据显然不是正常的。我在这里介绍的3种程序都来自类似的帖子,但我显然遇到了一些问题。我觉得拟合曲线的所有方法都取决于你正在处理的数据。

解决方案更新

感谢Zheyuan Li和其他人!我会将此保留作为自己的参考,也希望能对其他人有所帮助。

hist(Differences, probability = TRUE)
lines(density(Differences, cut = 0), col = "Red", lwd = 2)
lines(density(Differences, adjust = 2, cut = 0), lwd = 2, col = "Blue")

enter image description here


在我不事先知道分布的情况下(即,所有经验性场景),我使用核密度估计(有时不使用直方图)。如果你的目标是查看数据与特定分布的匹配程度,那么你可以将核密度估计图与已知分布一起绘制出来。 - lmo
@lmo 我喜欢那个想法。不过似乎我的内核向负方向偏离了直方图。这有点烦人,但没关系。谢谢你们两个。 - Brandon
这实际上是一个统计学问题。有很多方法可以逼近密度估计,但以原则性的方式进行需要与统计学家坐下来讨论调查的科学背景。 - IRTFM
1个回答

3

好的,您只是纠结于密度超出“自然范围”的事实。那么,只需将cut = 0即可。您可能想阅读plot.density extends “xlim” beyond the range of my data. Why and how to fix it?了解原因。在那个答案中,我使用了fromto。但现在我正在使用cut

## consider a mixture, that does not follow any parametric distribution family
## note, by construction, this is a strictly positive random variable
set.seed(0)
x <- rbeta(1000, 3, 5) + rexp(1000, 0.5)

## (kernel) density estimation offers a flexible nonparametric approach
d <- density(x, cut = 0)

## you can plot histogram and density on the density scale
hist(x, prob = TRUE, breaks = 50)
lines(d, col = 2)

enter image description here

注意,在cut = 0的情况下,密度估计严格限定在range(x)内。在这个范围之外,密度为0。


啊!现在我明白了。哇,这非常方便。大部分情况下,我觉得我做得还不错。感谢您的澄清和耐心。非常感谢。 - Brandon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接