使用scipy.stats.hypergeom从SciPy的甲板上抽牌

Bri*_*ell 5 python probability scipy

我在理解SciPy 函数的文档时遇到了麻烦scipy.stats.hypergeom。在我的程序中,我考虑了各种不同类型的纸牌,并试图找到各种抽奖的可能性。该hypergeom级似乎有正是这种,但它的文档假定一堆术语知识的人,我没有。谷歌搜索使我进入Wikipedia和Wolfram MathWorld,这两个假设都假设如果您正在询问这种事情,那么您已经阅读了Dang Principia Mathematica的所有内容,并且只需要稍作回顾即可-因此它们实际上没有帮助。因为此问题是“如何将特定的代码块应用于我的问题?” 我问堆栈溢出。

我有一个问题,形式是“如果您有一副N张卡,其中M张是您感兴趣的卡,那么在前Q张卡中至少有一份感兴趣的卡的几率是多少?” 我还有一个问题是“如果您有一副N张牌,其中M张是您感兴趣的牌,则您必须从副牌中抽出几张牌,才能有90%的几率成为其中一张的副本。感兴趣的卡?” 前一个问题与SciPy文档中给出的示例问题非常接近,但这不是一回事,而且方法列表对我来说都是行话-我无法确切地说出其中哪一个是我需要的。我也无法确定要针对后一种类型的问题使用哪种方法。

scipy.stats.hypergeom实际使用的方法是什么?它们的论据是什么?如何将它们应用于我的问题?假装我是一个中等程度的高中生,而不是数学博士候选人。

Hug*_*ell 4

scipy.stats.hypergeom.pmf(k, M, n, N)
Run Code Online (Sandbox Code Playgroud)

返回概率:从 M 张卡片中,其中 n 张已被标记,如果您随机选择 N 张卡片而不放回,则正好有 k 张卡片将被标记。

所以你可以得到你想要的答案(使用你的变量名)

def pick_Q(N, M, Q):
    """
    Given a deck of N cards, where M are marked,
    and Q cards are taken randomly without replacement,
    return the probability that at least one marked card is taken.
    """
    return sum(scipy.stats.hypergeom.pmf(k, N, M, Q) for k in xrange(1,Q+1))
Run Code Online (Sandbox Code Playgroud)

(1张牌被标记、2张牌被标记、3张牌被标记……N张牌被标记的几率之和)。

幸运的是,有一种更快的方法 - 至少一张标记卡被拿走的概率是没有标记卡被拿走的概率的另一面。所以你可以这样做

def pick_Q(N, M, Q):
    """
    Given a deck of N cards, where M are marked,
    and Q cards are taken randomly without replacement,
    return the probability that at least one marked card is taken.
    """
    return 1. - scipy.stats.hypergeom.pmf(0, N, M, Q)
Run Code Online (Sandbox Code Playgroud)

对于你的第二个问题,似乎没有任何功能可以满足你的要求;但是,你可以从

def how_many_to_pick(N, M, prob):
    """
    Given a deck of N cards, M of which are marked,
    how many do you have to pick randomly without replacement
    to have at least prob probability of picking at least one marked card?
    """
    for q in xrange(1, M+1):
        if pick_Q(N, M, q) >= prob:
            return q
    raise ValueError("Could not find a value for q")
Run Code Online (Sandbox Code Playgroud)

编辑:

scipy.stats.hypergeom.cdf(k, M, n, N)
Run Code Online (Sandbox Code Playgroud)

给定一副 M 张牌,其中 n 张已标记,随机挑选 N 张而不放回,求出k 或更少标记的牌被挑选的几率。(您可以将其视为 .pmf 的积分)

那么 .sf(k, M, n, N) 是 .cdf 的反面 -超过 k 张标记牌被选中的几率。

例如,

 k      pmf(k,52,13,4)   cdf(k,52,13,4)   sf(k,52,13,4)
     (exactly k picked)  ( <= k picked)   ( > k picked)
---  -----------------  ---------------  --------------
 0       0.303817527      0.303817527      0.696182473
 1       0.438847539      0.742665066      0.257334934
 2       0.213493397      0.956158463      0.043841537
 3       0.041200480      0.997358944      0.002641056
 4       0.002641056      1.000000000      0.000000000
Run Code Online (Sandbox Code Playgroud)

编辑2:

实际上,这提供了另一种编写 pick_Q 函数的方式 - “挑选 1 张或更多标记的卡片”可以改写为“挑选超过 0 张标记的卡片”,所以

def pick_Q(N, M, Q):
    """
    Given a deck of N cards, where M are marked,
    and Q cards are taken randomly without replacement,
    return the probability that at least one marked card is taken.
    """
    return scipy.stats.hypergeom.sf(0, N, M, Q)
Run Code Online (Sandbox Code Playgroud)