2017-08-15 101 views
4

我发现代码来计算R的密度曲线下面积的总和不幸的是,我不明白为什么总有一个额外的〜“0.000976”的区域...为什么密度曲线下的面积总和总是大于1(R)?

nb.data = 500000 
y = rnorm(nb.data,10,2) 

de = density(y) 

require(zoo) 
sum(diff(de$x[order(de$x)])*rollmean(de$y[order(de$x)],2)) 

[1] 1.000976 

为什么是这样吗?

它应该等于1,对不对?

+0

舍入错误? – jmoon

+0

会有一种方法来纠正这个问题吗? –

+0

与其他语言一样,我想。我发现[this](https://stackoverflow.com/questions/6759910/preventing-rounding-errors)特别有用,但我不确定它适用于您的情况有多好。 – jmoon

回答

7

这种差异不仅是由于舍入误差或浮点运算。你有效地在由density计算的点之间线性插值,然后在这个近似下计算原始函数的面积(即你使用trapzoidal rule积分曲线),这意味着你高估了曲线区域的面积在向下凹陷的区域凹陷并低估它。这里是从维基百科的文章展示了系统误差的示例图像:


Trapezoidal rule illustration

图片由Intégration_num_trapèzes.svg:Scalerderivative工作:Cdang(谈话) - Intégration_num_trapèzes.svg,CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=8541370


由于正常分布具有更多向上凹的区域(即两个尾部),整体估计过高。正如另一个答案中提到的,使用更高的分辨率(即增加N)有助于最大限度地减少错误。您也可以使用不同的数值积分方法获得更好的结果(例如Simpson's rule)。

但是,没有数值积分方法会给你一个确切的答案,并且即使存在,返回值density也只是实际分布的近似值。 (对于真实数据,真实分布是未知的。)

如果你想要的是看到一个已知的密度函数积分为1的满意,您可以在正常的密度函数使用integrate

> integrate(dnorm, lower=-Inf, upper=Inf, mean=10, sd=2) 
1 with absolute error < 4.9e-06 
+0

确实,我认为这会更具挑战性!积分更好。 –

8

这就是微积分。使用更高n(默认为512)更准确结果

set.seed(42) 
de = density(rnorm(500000, 10, 2)) 
sum(diff(sort(de$x)) * 0.5 * (de$y[-1] + head(de$y, -1))) 
#[1] 1.00098 

set.seed(42) 
de = density(rnorm(500000, 10, 2), n = 1000) 
sum(diff(sort(de$x)) * 0.5 * (de$y[-1] + head(de$y, -1))) 
#[1] 1.000491 

set.seed(42) 
de = density(rnorm(500000, 10, 2), n = 10000) 
sum(diff(sort(de$x)) * 0.5 * (de$y[-1] + head(de$y, -1))) 
#[1] 1.000031 

set.seed(42) 
de = density(rnorm(500000, 10, 2), n = 100000) 
sum(diff(sort(de$x)) * 0.5 * (de$y[-1] + head(de$y, -1))) 
#[1] 1.000004 

set.seed(42) 
de = density(rnorm(500000, 10, 2), n = 1000000) 
sum(diff(sort(de$x)) * 0.5 * (de$y[-1] + head(de$y, -1))) 
#[1] 1