2017-08-15 95 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