【问题标题】:Random sampling to give an exact sum随机抽样以给出准确的总和
【发布时间】:2018-08-07 12:50:48
【问题描述】:

我想对 1000 到 100000 之间的 140 个数字进行采样,使这 140 个数字的总和约为 200 万(2000000):

sample(1000:100000,140)

这样:

sum(sample(1000:100000,140)) = 2000000

有什么方法可以实现吗?

【问题讨论】:

  • 您从哪个分布中采样?
  • 我没有任何特定的分布。它可以是任何东西
  • 大约是 200 万还是准确的?你需要多近的距离
  • 如果它可以是任何东西.. 生成 70 个从 1 到 140 的数字而不替换,将这些位置的平局设置为 2000000/70=28571.42857,否则设置为 0,总和将是 2000000,而分布将是伯努利。
  • 目前问题描述有太多歧义。 a) 是否需要精确的总和 b) 是从实数还是整数中进行采样?

标签: r random sampling


【解决方案1】:

这里有一些获得接近 200 万的 hacky 方法。希望有人会发布更聪明的解决方案。

在这个选项中,我们使用prob 参数来使更小的值更有可能,并且我们通过反复试验来选择指数。此方法严重倾向于在 OP 中指定的范围内选择较低的值。

x1 = sample(1000:100000,140, prob=(1e5:1e3)^5.5)
mean(replicate(100, sum(sample(1000:100000,140, prob=(1e5:1e3)^5.5))))
[1] 2015620

在此选项中,我们从截断的法线(在您给定的边界处截断)进行采样。我们最初将平均值设置为 2e6/140=14285.71。但是,如果标准差大到足以导致下边界附近有很多值,则截断会使均值偏高,因此我们添加了通过反复试验选择的校正。

library(truncnorm)
x2 = rtruncnorm(140, 1e3, 1e5, mean=0.82*2e6/140, sd=1e4)
mean(replicate(1000, sum(rtruncnorm(140, 1e3, 1e5, mean=0.82*2e6/140, sd=1e4))))
[1] 2008050

如果您设置的标准差较小,则无需进行校正。但是,通过这种方式,您得到的远离均值的值会更少。

mean(replicate(1000, sum(rtruncnorm(140, 1e3, 1e5, mean=2e6/140, sd=0.5e4))))
[1] 2008494

在任何一种情况下,sample 方法的指数或对截断法线的校正都可以通过自动搜索来选择,该搜索具有平均和与 200 万之间的差异的容差。

以下是输出的一些典型分布:

【讨论】:

    【解决方案2】:

    这是一个尝试,试图改变上键。这个想法是当总和越来越高时减少上限。

    sup<- 100000
    tir <- vector(length = 140)
    for(i in 1:140){
      print(i)
      tir[i] <- sample(1000:sup,1)
      sup <- max(1001,min(sup,abs(2000000 - sum(tir,na.rm = T))/(140-i)*2))
    }
    sum(tir)
    [1] 2001751
    

    【讨论】:

      【解决方案3】:

      这是一种命中注定的方法。基本思想是找到 140 个总和为 2000000 的数字与将 1:2000000 分成 140 个部分相同,需要 139 个切点。另外,请注意,最小值 1000 有点烦人。只需从所有问题数据中减去它并在最后添加回来:

      rand.nums <- function(a,b,n,k){
        #finds n random integers in range a:b which sum to k
        while(TRUE){
          x <- sample(1:(k - n*a),n-1, replace = TRUE) #cutpoints
          x <- sort(x)
          x <- c(x,k-n*a) - c(0,x)
          if(max(x) <= b-a) return(a+x)
        }
      }
      

      然后rand.nums(1000,100000,140,2000000) 计算出给定范围内的 140 个整数,总和为 2000000。对于这些参数选择,函数几乎立即返回。对于参数的其他选择,解决方案可能是不可能的,或者受到如此严格的限制,以至于偶然找到一个实际上是不可能的。因此,在使用该功能时需要谨慎。可以通过添加 maxtrials 参数来修改它,如果超过了 maxtrials 却没有找到解决方案,则返回 NA

      【讨论】:

      • 我喜欢这个主意。对于某些范围n,切点为x &lt;- sample(n, 139),数字为ans &lt;- diff(c(1, sort(x), n))。我们有length(ans) == 140sum(ans) == n。可能有一个边缘情况错误——sample(n) 包含 1。
      • @MartinMorgan 我稍微调整了一下。我注意到在原始算法中,可能的最小数字是 1001 而不是 1000。允许一些切点相同将允许在添加 1000 之前选择 0。
      【解决方案4】:

      存在一种生成此类随机数的算法。

      最初为MATLAB创建,有一个R实现:

      Surrogate::RandVec

      来自 MATLAB 脚本注释的引用:

      %   This generates an n by m array x, each of whose m columns
      % contains n random values lying in the interval [a,b], but
      % subject to the condition that their sum be equal to s.  The
      % scalar value s must accordingly satisfy n*a <= s <= n*b.  The
      % distribution of values is uniform in the sense that it has the
      % conditional probability distribution of a uniform distribution
      % over the whole n-cube, given that the sum of the x's is s.
      %
      %   The scalar v, if requested, returns with the total
      % n-1 dimensional volume (content) of the subset satisfying
      % this condition.  Consequently if v, considered as a function
      % of s and divided by sqrt(n), is integrated with respect to s
      % from s = a to s = b, the result would necessarily be the
      % n-dimensional volume of the whole cube, namely (b-a)^n.
      %
      %   This algorithm does no "rejecting" on the sets of x's it
      % obtains.  It is designed to generate only those that satisfy all
      % the above conditions and to do so with a uniform distribution.
      % It accomplishes this by decomposing the space of all possible x
      % sets (columns) into n-1 dimensional simplexes.  (Line segments,
      % triangles, and tetrahedra, are one-, two-, and three-dimensional
      % examples of simplexes, respectively.)  It makes use of three
      % different sets of 'rand' variables, one to locate values
      % uniformly within each type of simplex, another to randomly
      % select representatives of each different type of simplex in
      % proportion to their volume, and a third to perform random
      % permutations to provide an even distribution of simplex choices
      % among like types.  For example, with n equal to 3 and s set at,
      % say, 40% of the way from a towards b, there will be 2 different
      % types of simplex, in this case triangles, each with its own
      % area, and 6 different versions of each from permutations, for
      % a total of 12 triangles, and these all fit together to form a
      % particular planar non-regular hexagon in 3 dimensions, with v
      % returned set equal to the hexagon's area.
      %
      % Roger Stafford - Jan. 19, 2006
      

      例子:

      test <- Surrogate::RandVec(a=1000, b=100000, s=2000000, n=140, m=1, Seed=sample(1:1000, size = 1))
      sum(test$RandVecOutput)
      # 2000000
      hist(test$RandVecOutput)
      

      【讨论】:

      • 也许还值得显示anyDuplicated(test$RandVecOutput) # 0 来说明没有欺骗/没有替代品。
      • 是否可以重复替换?
      • @Hardikgupta 我误认为替换与此答案相关。随机向量是实数,而不是属于 1000:100000 的整数。
      • @Hardikgupta 在这个算法中没有什么特别限制替换的,但是从 99000 中得到 140 个数字的重复是非常不幸的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      • 1970-01-01
      • 2018-12-03
      • 2016-09-06
      • 1970-01-01
      相关资源
      最近更新 更多