2016-07-01 89 views
1

我有一個大的數據集,其中包含植被指數(VI)的觀測值。我使用R隨機對數據進行二次採樣,同時保持分佈(相對頻率)均勻(在整個VI範圍內的觀測量相等)。我一直無法獲得相當均勻的分佈。R中均勻分佈的隨機子樣本

實施例:

norm<-rnorm(1000, mean = .5, sd = .25) # I have this 

hist(norm) #that is distributed like this 

hist(unif<-runif(1000, min=0, max=1)) # but I want to resample the data to look like this 
+0

如果您想從一組1000中採樣1000個值,那麼只有一種方法可以完成整個設置。在不添加新值的情況下更改分佈的唯一方法是對原始集合中存在的*個元素進行抽樣。例如,從原始1000中取100個值。如果您能夠澄清您在此處查看的設置大小,這將有所幫助。 – bgoldst

回答

2

這樣如何:劃分的VI切成等寬的頻段的範圍內,並把數據轉換成這些塊。在分配中間的箱子中將會有更多的數據,而不是尾數。隨機選擇(等概率),然後從箱中選擇一個項目。

該想法的一種變化是隨機選擇VI範圍內的點(等概率),然後找到落在從(x-dx/2)到(x + dx/2) 2)其中dx足夠大以至少能夠捕獲少數數據。然後從該區間選擇一個數據(等概率)。有可能有更多的變化。

這樣的非均勻採樣的一個後果就是你可能反覆從尾部選擇相同的項目。我沒有看到解決辦法。這似乎是不可避免的後果。但我可能是錯的。

1

帶反向輸入分佈權重的樣本

啊哈!我想到了第二個解決方案,我認爲它可能比我的第一個解決方案更好,我已經在下保留了下面的重複目標分佈最近匹配選擇

sample()函數具有prob參數,它允許我們指定輸入向量元素的概率權重。我們可以使用這個參數來增加選擇輸入分佈稀疏段(即尾部)中出現的元素的概率,並降低選擇密集段(即中心)中出現的元素的概率。我想密度函數的簡單算術反轉dnorm()就足夠了:

測試數據

set.seed(1L); 
normSize <- 1e4L; normMean <- 0.5; normSD <- 0.25; 
norm <- rnorm(normSize,normMean,normSD); 

解決方案

unifSize <- 1e3L; unifMin <- 0; unifMax <- 1; 
normForUnif <- norm[norm>=unifMin & norm<=unifMax]; 
d <- dnorm(normForUnif,normMean,normSD); 
unif <- sample(normForUnif,unifSize,prob=1/d); 
hist(unif); 

hist-unif-1


重複目標分佈最接近匹配選擇

從您的目標(統一)分佈生成一組隨機偏差。對於每個偏差,從最接近它的輸入(正態)分佈中查找元素。考慮爲樣本選擇的元素。

重複上述操作,直到唯一選擇的數量達到或超過樣本所需的大小。如果超過了所需的大小,請將其截斷爲所需的大小。


我們可以用findInterval()查找每個均勻偏離最接近偏離正常。這需要幾個調解才能正確。我們必須對正態分佈向量進行排序,因爲findInterval()要求vec進行排序。我們必須通過存在於輸入集中的不低於零的最低值,而不是使用零,即目標分佈的真正最小值,因爲我們將最小值傳遞給runif();否則,統一偏差低於該值將與均勻分佈的可接受最小值以下的輸入元素相匹配。另外,爲了提高效率,在運行調用findInterval()的循環之前,最好從正態分佈向量中移除不在目標分佈的可接受範圍內的所有值(即[0,1]),以便它們將不參與匹配算法。他們並不需要,因爲無論如何都無法匹配。

如果目標樣本大小比輸入分佈向量小足夠的餘量,則應該消除所得樣本中輸入分佈的任何痕跡。

測試數據

set.seed(1L); 
normSize <- 1e6L; normMean <- 0.5; normSD <- 0.25; 
norm <- rnorm(normSize,normMean,normSD); 

解決方案

unifSize <- 200L; unifMin <- 0; unifMax <- 1; 
normVec <- sort(norm[norm>=unifMin & norm<=unifMax]); 
inds <- integer(); 
repeat { 
    inds <- unique(c(inds,findInterval(runif(unifSize*2L,normVec[1L],unifMax),normVec))); 
    if (length(inds)>=unifSize) break; 
}; 
length(inds) <- unifSize; 
unif <- normVec[inds]; 
hist(unif); 

hist-unif

一個需要注意的是,findInterval()沒有技術上找到最近元素,它找到的元素小於或等於的搜索值。我認爲這不會對結果產生重大影響;最多隻能以一種統一的方式對選擇偏向於較小的值進行微小的偏差。如果你真的想,你可以看看現存的各種找到最近的選項,例如見R: find nearest index