当样本中的 prob 参数总和小于/大于 1 时会发生什么?

Ron*_*hah 11 r sample

我们知道prob参数 insample用于分配权重的概率。

例如,

table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.4, 0.3, 0.1)))/1e6

#  1   2   3   4 
#0.2 0.4 0.3 0.1 


table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.4, 0.3, 0.1)))/1e6

#    1     2     3     4 
#0.200 0.400 0.299 0.100 
Run Code Online (Sandbox Code Playgroud)

在这个例子中,概率之和正好是 1 (0.2 + 0.4 + 0.3 + 0.1),因此它给出了预期的比率,但如果概率之和不为 1 呢?它会给出什么输出?我认为这会导致错误,但它提供了一些价值。

当概率总和大于 1 时。

table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.5, 0.5, 0.1)))/1e6

#     1      2      3      4 
#0.1544 0.3839 0.3848 0.0768 

table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.5, 0.5, 0.1)))/1e6

#     1      2      3      4 
#0.1544 0.3842 0.3848 0.0767 
Run Code Online (Sandbox Code Playgroud)

当概率总和小于 1 时

table(sample(1:4, 1e6, replace = TRUE, prob = c(0.1, 0.1, 0.5, 0.1)))/1e6

#    1     2     3     4 
#0.124 0.125 0.625 0.125 

table(sample(1:4, 1e6, replace = TRUE, prob = c(0.1, 0.1, 0.5, 0.1)))/1e6

#    1     2     3     4 
#0.125 0.125 0.625 0.125 
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,多次运行会给出不等于的输出,prob但结果也不是随机的。在这种情况下,数字是如何分布的?它在哪里记录?

我尝试在互联网上搜索,但没有找到任何相关信息。我查看了文档,?sample其中有

可选的 prob 参数可用于给出权重向量,以获取被采样向量的元素。它们的总和不必为 1,但它们应该是非负数且不能全为零。如果 replace 为真,则当存在超过 200 个合理可能的值时使用 Walker 的别名方法 (Ripley, 1987):这会产生与来自 R < 2.2.0 的结果不兼容的结果。

所以它说这个prob论点不需要总和为 1,但没有说明当它总和不为 1 时预期是什么?我不确定我是否遗漏了文档的任何部分。有人有任何想法吗?

All*_*ron 11

好问题。文档对此不清楚,但可以通过查看源代码来回答这个问题。

如果您查看 R 代码,sample总是调用另一个 R 函数,sample.int如果您将单个数字传递xsample,它将sample.int用于创建小于或等于该数字的整数向量,而如果x是向量,则用于sample.int生成小于或等于 的整数样本length(x),然后使用它对 x 进行子集化。

现在,如果您检查函数sample.int,它看起来像这样:

function (n, size = n, replace = FALSE, prob = NULL, useHash = (!replace && 
    is.null(prob) && size <= n/2 && n > 1e+07)) 
{
    if (useHash) 
        .Internal(sample2(n, size))
    else .Internal(sample(n, size, replace, prob))
}
Run Code Online (Sandbox Code Playgroud)

.Internal意味着任何采样都是通过调用用 C 编写的编译代码完成的:在这种情况下,它是函数do_sample在 src/main/random.c 中定义

如果您查看此 C 代码,请do_sample检查它是否已传递prob向量。如果不是,则在相等权重的假设下进行采样。如果prob存在,该函数确保它是数字而不是 NA。如果prob通过这些检查,则会生成一个指向底层双精度数组的指针,并将其传递给 random.c 中另一个名为 的函数,在此处FixUpProbs定义。

此函数检查 的每个成员prob并在 的任何元素prob不是正有限双精度时抛出错误。然后它通过将每个数字除以所有数字的总和来标准化这些数字。因此prob,对于代码中固有的总和为 1,根本没有偏好。也就是说,即使prob输入中的总和为 1,该函数仍会计算总和并将每个数字除以它。

因此,该参数命名不当。正如这里的其他人指出的那样,它应该是“权重”。公平地说,文档只说prob应该是权重向量,而不是绝对概率。

所以prob我阅读代码的参数的行为应该是:

  1. prob 可以完全不存在,在这种情况下,采样默认为相等的权重。
  2. 如果 的任何prob数字小于零,或者是无限的,或者 NA,函数将抛出。
  3. 如果任何prob值是非数字的,则应该抛出错误,因为它们将被解释为NA传递给 C 代码的 SEXP。
  4. prob必须x与 C 代码抛出的长度相同
  5. prob如果您指定了replace=T,您可以将零概率作为 的一个或多个元素传递,只要您至少有一个非零概率。
  6. 如果指定replace=F,则请求的样本数必须小于或等于 中的非零元素数prob。本质上,FixUpProbs如果您要求它以零概率进行采样,则会抛出。
  7. 有效prob向量将归一化为总和为 1 并用作采样权重。

作为这种行为的一个有趣的副作用,如果您通过设置 probs = 在 2 个备选方案之间进行选择,则这允许您使用赔率而不是概率 c(1, odds)

  • 感谢您提供了经过充分研究的答案。关于最后的总结,特别是第 5) 点。`sample(1:4, 1, prob = c(0, 2, 3, 4))` 似乎和 `table(replicate(1e6, Sample(1:4, 1, prob = c(0, 2, 3, 4))))` 与 `replace = FALSE`。正如文档中提到的“它们的总和不需要为一,但它们应该是非负数并且不全为零”。那么,使用 `replace = FALSE` 时,一个(或多个但不是全部)值的概率为 0 是可以的吗? (2认同)
  • 好点@RonakShah。实际上,只有_强制_以零概率采样时它才会抛出异常。所以你可能可以做 `sample(1:4, 2, prob = c(0, 0, 2, 3), Replace = F)` ,但是如果你指定 n=3,那么一旦 3 和 4 出现在采样,它会尝试以 0 的概率采样 1 或 2 并抛出。目前无法测试此... (2认同)
  • @RonakShah 我现在已经测试过它,这确实是行为。答案已更新。 (2认同)

Rom*_*rik 7

如前所述,权重被归一化为总和为 1,可以证明:

> x/sum(x)
[1] 0.15384615 0.38461538 0.38461538 0.07692308
Run Code Online (Sandbox Code Playgroud)

这与您的模拟表格数据相匹配:

#     1      2      3      4 
#0.1544 0.3839 0.3848 0.0768 
Run Code Online (Sandbox Code Playgroud)