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

例如,

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

在此示例中,概率之和恰好为1(0.2 + 0.4 + 0.3 + 0.1),因此它给出了预期的比率,但是如果概率之和不等于1怎么办?它会给出什么输出?我以为会导致错误,但可以提供一些值(value)。

当概率总和大于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

当概率总和小于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

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

我尝试在互联网上搜索,但未找到任何相关信息。我浏览了?sample的文档,该文档具有



因此,它说prob参数不必求和为1,但是当不求和为1时却不告诉期望什么?我不确定是否缺少文档的任何部分。有人有什么主意吗?

最佳答案

好问题。文档尚不清楚,但是可以通过查看源代码来回答问题。

如果查看R代码,sample始终调用另一个R函数sample.int如果将单个数字x传递给sample,它将使用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))
}
.Internal表示可以通过调用用C编写的已编译代码来完成任何采样:在这种情况下,它是do_sample函数,定义为here in src/main/random.c

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

此函数检查prob的每个成员,如果prob的任何元素不是正有限 double 数,则将引发错误。然后通过将每个数除以所有总和来归一化这些数字。因此,根本没有偏好将prob总和为1的固有代码。也就是说,即使输入中的prob总和为1,该函数仍会计算总和并将每个数字除以总和。

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

因此,根据我对代码的阅读,prob参数的行为应为:
  • prob可能完全不存在,在这种情况下,默认情况下采样权重相等。
  • 如果prob的任何数字小于零,无穷大或不适用,则函数将抛出。
  • 如果任何prob值是非数字的,则应该引发错误,因为它们在传递给C代码的SEXP中将被解释为NA
  • prob的长度必须与x相同,否则C代码会抛出
  • 如果您已指定prob,则可以将零概率作为replace=T的一个或多个元素传递,只要您具有至少一个非零概率即可。
  • 如果指定replace=F,则请求的样本数必须小于或等于prob中的非零元素数。本质上,如果您要求FixUpProbs进行采样的概率为零,则将抛出prob
  • 有效的c(1, odds)向量将被归一化为1,并用作采样权重。

  • 作为此行为的一个有趣的副作用,如果您通过设置probs = ojit_code在2个备选方案之间进行选择,则可以使用赔率代替概率

    关于r - 样本中的prob参数总和小于/大于1时会发生什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59918865/

    10-11 17:49