当样本中的 prob 参数总和为 less/greater 而不是 1 时会发生什么?
What happens when prob argument in sample sums to less/greater than 1?
我们知道sample
中的prob
参数是用来分配权重的概率。
例如,
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 怎么办?它会给出什么输出?我认为这会导致错误,但它提供了一些价值。
当概率总和大于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
的文档,其中有
The optional prob argument can be used to give a vector of weights for obtaining the elements of the vector being sampled. They need not sum to one, but they should be non-negative and not all zero. If replace is true, Walker's alias method (Ripley, 1987) is used when there are more than 200 reasonably probable values: this gives results incompatible with those from R < 2.2.0.
所以它说 prob
参数不需要总和为 1,但没有说明当它总和不为 1 时预期的结果是什么?我不确定我是否遗漏了文档的任何部分。有人知道吗?
如前所述,权重归一化为总和为 1,如下所示:
> x/sum(x)
[1] 0.15384615 0.38461538 0.38461538 0.07692308
这与您的模拟表格数据匹配:
# 1 2 3 4
#0.1544 0.3839 0.3848 0.0768
好问题。文档对此不清楚,但可以通过查看源代码来回答这个问题。
如果你看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
通过了这些检查,则会生成一个指向底层双精度数组的指针,并将其传递给 random.c 中另一个名为 FixUpProbs
的函数,定义为 here.
此函数检查 prob
的每个成员,如果 prob
的任何元素不是正有限双精度,则抛出错误。然后,它通过将每个数字除以所有数字的总和来标准化数字。因此,代码中固有的 prob
总和为 1 根本没有偏好。也就是说,即使您输入的 prob
总和为 1,该函数仍会计算总和并将每个数字除以它。
因此,参数命名不当。它应该是 "weights",正如这里的其他人所指出的那样。公平地说,文档只说 prob
应该是权重向量,而不是绝对概率。
所以根据我对代码的阅读,prob
参数的行为应该是:
prob
可以完全不存在,在这种情况下抽样默认为相等权重。
- 如果
prob
的任何数字小于零、无穷大或 NA,函数将抛出异常。
- 如果
prob
中的任何一个值不是数字,则应抛出错误,因为在传递给 C 代码的 SEXP 中它们将被解释为 NA
。
prob
的长度必须与 x
相同,否则 C 代码会抛出
- 如果您指定了
replace=T
,您可以将零概率作为 prob
的一个或多个元素传递,只要您至少有一个非零概率。
- 如果您指定
replace=F
,您请求的样本数必须小于或等于prob
中的非零元素数。本质上,如果您要求 FixUpProbs
以零概率进行采样,它就会抛出异常。
- 一个有效的
prob
向量将被归一化为总和为 1 并用作采样权重。
作为此行为的一个有趣的副作用,如果您通过设置 probs = c(1, odds)
在 2 个备选方案之间进行选择,这允许您使用赔率而不是概率
我们知道sample
中的prob
参数是用来分配权重的概率。
例如,
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 怎么办?它会给出什么输出?我认为这会导致错误,但它提供了一些价值。
当概率总和大于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
的文档,其中有
The optional prob argument can be used to give a vector of weights for obtaining the elements of the vector being sampled. They need not sum to one, but they should be non-negative and not all zero. If replace is true, Walker's alias method (Ripley, 1987) is used when there are more than 200 reasonably probable values: this gives results incompatible with those from R < 2.2.0.
所以它说 prob
参数不需要总和为 1,但没有说明当它总和不为 1 时预期的结果是什么?我不确定我是否遗漏了文档的任何部分。有人知道吗?
如前所述,权重归一化为总和为 1,如下所示:
> x/sum(x)
[1] 0.15384615 0.38461538 0.38461538 0.07692308
这与您的模拟表格数据匹配:
# 1 2 3 4
#0.1544 0.3839 0.3848 0.0768
好问题。文档对此不清楚,但可以通过查看源代码来回答这个问题。
如果你看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
通过了这些检查,则会生成一个指向底层双精度数组的指针,并将其传递给 random.c 中另一个名为 FixUpProbs
的函数,定义为 here.
此函数检查 prob
的每个成员,如果 prob
的任何元素不是正有限双精度,则抛出错误。然后,它通过将每个数字除以所有数字的总和来标准化数字。因此,代码中固有的 prob
总和为 1 根本没有偏好。也就是说,即使您输入的 prob
总和为 1,该函数仍会计算总和并将每个数字除以它。
因此,参数命名不当。它应该是 "weights",正如这里的其他人所指出的那样。公平地说,文档只说 prob
应该是权重向量,而不是绝对概率。
所以根据我对代码的阅读,prob
参数的行为应该是:
prob
可以完全不存在,在这种情况下抽样默认为相等权重。- 如果
prob
的任何数字小于零、无穷大或 NA,函数将抛出异常。 - 如果
prob
中的任何一个值不是数字,则应抛出错误,因为在传递给 C 代码的 SEXP 中它们将被解释为NA
。 prob
的长度必须与x
相同,否则 C 代码会抛出- 如果您指定了
replace=T
,您可以将零概率作为prob
的一个或多个元素传递,只要您至少有一个非零概率。 - 如果您指定
replace=F
,您请求的样本数必须小于或等于prob
中的非零元素数。本质上,如果您要求FixUpProbs
以零概率进行采样,它就会抛出异常。 - 一个有效的
prob
向量将被归一化为总和为 1 并用作采样权重。
作为此行为的一个有趣的副作用,如果您通过设置 probs = c(1, odds)