帶反向輸入分佈權重的樣本
啊哈!我想到了第二個解決方案,我認爲它可能比我的第一個解決方案更好,我已經在下保留了下面的重複目標分佈最近匹配選擇。
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);
重複目標分佈最接近匹配選擇
從您的目標(統一)分佈生成一組隨機偏差。對於每個偏差,從最接近它的輸入(正態)分佈中查找元素。考慮爲樣本選擇的元素。
重複上述操作,直到唯一選擇的數量達到或超過樣本所需的大小。如果超過了所需的大小,請將其截斷爲所需的大小。
我們可以用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()
沒有技術上找到最近元素,它找到的元素小於或等於的搜索值。我認爲這不會對結果產生重大影響;最多隻能以一種統一的方式對選擇偏向於較小的值進行微小的偏差。如果你真的想,你可以看看現存的各種找到最近的選項,例如見R: find nearest index。
如果您想從一組1000中採樣1000個值,那麼只有一種方法可以完成整個設置。在不添加新值的情況下更改分佈的唯一方法是對原始集合中存在的*個元素進行抽樣。例如,從原始1000中取100個值。如果您能夠澄清您在此處查看的設置大小,這將有所幫助。 – bgoldst