簡體   English   中英

R中均勻分布的隨機子樣本

[英]random subsample with uniform distribution in R

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

示例:

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

這個怎么樣:把VI的范圍分成等寬的bins,把數據放到這些bins里。 分布中間的 bin 中的數據將多於末端的數據。 在 bin 中隨機選擇(等概率),然后從 bin 中選擇一項。

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

像這樣的非均勻采樣的一個后果是您可能會一遍又一遍地從尾部選擇相同的項目。 我看不出有什么辦法解決這個問題; 這似乎是不可避免的后果。 但我可能錯了。

具有反向輸入分布權重的樣本

啊哈! 我想到了第二個解決方案,我認為它可能比我的第一個更好,我將其保留在下面的重復目標分布最近匹配選擇部分下。

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);

歷史統一

一個警告是findInterval()在技​​術上不會找到最近的元素,它會找到小於或等於搜索值的元素。 我認為這不會對結果產生任何重大影響; 至多,它會以一種統一的方式無限偏向選擇更小的值。 如果你真的想要,你可以看看存在的各種 find-nearest 選項,例如參見R: find Nearest index

您可以在具有不同種子的循環中使用 R 中 stats 包中的runif函數。 假設您想要制作 100 個子樣本並在最后合並它們,那么這應該可以完成工作:

list_of_uniformsamples <- vector("list", length = 100)
for (i in 1:100){
set.seed(123+i)
list_of_uniformsamples[[i]] <- round(runif(1000, min=1, max=Number_of_observations))
}
pool_of_uniform_samples <- unlist(list_of_uniformsamples)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM