R中均匀分布的随机子样本

时间:2016-07-01 23:59:12

标签: r random uniform-distribution

我有一个包含植被指标(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

3 个答案:

答案 0 :(得分:2)

这个怎么样:将VI的范围分成相等宽度的区间,并将数据放入这些区间。在分布中间的分箱中将有比在末端更多的数据。随机选择bin(概率相等),然后从bin中选择一个项目。

该想法的一个变化是随机选择VI范围内的点(概率相等),然后找到落入(x-dx / 2)到(x + dx / 2)的区间内的数据。 )其中dx足以捕获至少一些数据。然后从该间隔中选择一个数据(概率相等)。可能还有很多变化。

非均匀采样的一个后果就是您可能会反复从尾部选择相同的项目。我没有看到解决方法;这似乎是一个不可避免的后果。但我可能错了。

答案 1 :(得分: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

答案 2 :(得分:0)

您可以在具有不同种子的循环中使用 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)