【问题标题】:Why does runif() not predict the interval maximum value?为什么 runif() 不能预测区间最大值?
【发布时间】:2017-09-06 01:49:33
【问题描述】:

我是respondingReddit AskScience 提出的问题,我遇到了关于runif() 的功能的一些奇怪的东西。我试图从 1 到 52 统一采样一组。我的第一个想法是使用 runif():

as.integer(runif(n, min = 1, max = 52))

但是,我发现该操作从未产生 52 的值。例如:

length(unique(as.integer(runif(1000000, 1, 52))))
[1] 51

出于我的目的,我只是转而使用sample()

sample(52, n, replace = TRUE)

在 runif() 文档中它指出:

runif 不会生成任何一个极值,除非 max = min 或 max-min 与 min 相比较小,尤其是对于默认参数而言。

我想知道为什么runif() 会这样。如果它试图均匀地生成样本,它似乎应该能够从集合中产生“极值”。这是一项功能吗?为什么?

【问题讨论】:

  • 恰好得到 52 的概率为 0。为什么您对没有观察到概率为 0 的预先指定的事件感到惊讶?
  • 均匀分布是连续的 - 在连续分布中对任何给定值进行采样的概率为零,只有在分布的 间隔 上才能获得有限的概率 - 所以你'即使没有实现怪癖,也不太可能最终采样52.000000...
  • 我在最初尝试执行采样时确实犯了一些错误。这让我想到了一个更有趣的问题,为什么 runif() 不会产生极值。 Ben Bolker 很好地回答了这个问题。
  • runif 一起使用的替代方法是ceiling(runif(100, min = 0, max = 52))

标签: r


【解决方案1】:

这确实是一个功能。 runifC source code 包含以下 C 代码:

/* This is true of all builtin generators, but protect against
       user-supplied ones */
    do {u = unif_rand();} while (u <= 0 || u >= 1);
return a + (b - a) * u;

这意味着 unif_rand() 可以返回 0 或 1,但 runif() 被设计为跳过那些(不太可能的)情况。

我的猜测是这样做是为了保护在边缘情况下会失败的用户代码(值恰好在范围的边界上)。

此功能是 implemented by Brian Ripley on Sep 19 2006(从 cmets 看来,0&lt;u&lt;1 自动适用于内置统一生成器,但可能不适用于用户提供的生成器)。

sample(1:52,size=n,replace=TRUE) 是实现目标的惯用方式(尽管不一定是最有效的方式)。

【讨论】:

    【解决方案2】:

    as.integertrunc 类似。它将通过将给定值截断为 0 来形成一个整数。由于值不能超过 52 (see Ben's answer),它们将始终被截断为 1 到 51 之间的值。

    使用floor(或ceiling)会看到不同的结果。 注意您必须通过添加1 来调整runifmax(或在ceiling 的情况下调整min)。另外注意在这种情况下,由于minmax 都大于0,您也可以将floor 替换为truncas.integer

    set.seed(42)
    x = floor(runif(n = 1000000, min = 1, max = 52 + 1))
    plot(prop.table(table(x)), las = 2, cex.axis = 0.75)
    

    【讨论】:

    • 是的。谢谢。我使用 as.integer() 的错误让我想到了更有趣的问题。
    • 如果您想要整数之间的均匀分布,这是有问题的:prop.table(table(round(runif(100000, 1, 10)))) 表明(例如)获得两个极值中的任何一个的机会只有一半。
    • @BenBolker,经过进一步调查,似乎floorceiling 适当调整runif 中的minmax 可能会更好:plot(prop.table(table(floor(runif(10000, 1, 52+1)))), las = 2)
    【解决方案3】:

    as.integer(51.999)

    51

    这是因为 as.integer 是如何工作的。

    如果您想从离散分布中提取数据,请使用 sample。 runif 不适用于离散分布。

    【讨论】:

    • ?runif 表示函数本身不会产生任何一个极值,因此与as.integer无关
    • 但在某种程度上,runif() 不应该返回 52 吗?但是您的观点是关于使用 as.integer()。我认为它是四舍五入的,而实际上它只是去掉了小数。
    • 如果要从离散分布中提取,请使用样本。 runif 不适用于离散分布。
    • @user runif 生成任何值的概率为 0 - 不仅仅是最终值。 OP 尝试使用as.integer 将连续分布转换为离散分布。
    • 我的观点并不是说极值点产生的可能性大于 0,而是那些极值点甚至没有被考虑到设计。请参阅@Ben 的回答。
    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 2013-02-03
    • 2020-11-13
    • 2013-05-12
    • 2020-09-06
    相关资源
    最近更新 更多