【问题标题】:random subsample with uniform distribution in RR中均匀分布的随机子样本
【发布时间】:2016-11-04 10:37:21
【问题描述】:

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

【问题讨论】:

    标签: r random uniform-distribution


    【解决方案1】:

    如何:将VI的范围划分为等宽的bin,并将数据放入这些bin中。分布中间的 bin 中的数据将多于末端的数据。随机选择 bin(以相同的概率),然后从 bin 中选择一项。

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

    像这样的非均匀抽样的一个后果是,您可能会一遍又一遍地从尾部选择相同的项目。我看不出有什么办法。这似乎是不可避免的后果。但我可能错了。

    【讨论】:

      【解决方案2】:

      具有反向输入分布加权的示例

      啊哈!我想到了第二种解决方案,我认为它可能比我的第一种解决方案更好,我将其保留在下面的重复目标分布最近匹配选择部分下。

      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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-01-21
          • 1970-01-01
          • 2011-08-08
          • 2021-12-28
          • 1970-01-01
          • 2020-04-04
          • 2020-06-04
          相关资源
          最近更新 更多