Statistics: combinations in Python

前端 未结 18 1403
南旧
南旧 2020-11-27 10:14

I need to compute combinatorials (nCr) in Python but cannot find the function to do that in math, numpy or stat libraries. Something

相关标签:
18条回答
  • 2020-11-27 10:44

    This function is very optimazed.

    def nCk(n,k):
        m=0
        if k==0:
            m=1
        if k==1:
            m=n
        if k>=2:
            num,dem,op1,op2=1,1,k,n
            while(op1>=1):
                num*=op2
                dem*=op1
                op1-=1
                op2-=1
            m=num//dem
        return m
    
    0 讨论(0)
  • 2020-11-27 10:45

    If you want an exact result, use sympy.binomial. It seems to be the fastest method, hands down.

    x = 1000000
    y = 234050
    
    %timeit scipy.misc.comb(x, y, exact=True)
    1 loops, best of 3: 1min 27s per loop
    
    %timeit gmpy.comb(x, y)
    1 loops, best of 3: 1.97 s per loop
    
    %timeit int(sympy.binomial(x, y))
    100000 loops, best of 3: 5.06 µs per loop
    
    0 讨论(0)
  • 2020-11-27 10:46

    Starting Python 3.8, the standard library now includes the math.comb function to compute the binomial coefficient:

    math.comb(n, k)

    which is the number of ways to choose k items from n items without repetition
    n! / (k! (n - k)!):

    import math
    math.comb(10, 5) # 252
    
    0 讨论(0)
  • 2020-11-27 10:48

    See scipy.special.comb (scipy.misc.comb in older versions of scipy). When exact is False, it uses the gammaln function to obtain good precision without taking much time. In the exact case it returns an arbitrary-precision integer, which might take a long time to compute.

    0 讨论(0)
  • 2020-11-27 10:48

    You can write 2 simple functions that actually turns out to be about 5-8 times faster than using scipy.special.comb. In fact, you don't need to import any extra packages, and the function is quite easily readable. The trick is to use memoization to store previously computed values, and using the definition of nCr

    # create a memoization dictionary
    memo = {}
    def factorial(n):
        """
        Calculate the factorial of an input using memoization
        :param n: int
        :rtype value: int
        """
        if n in [1,0]:
            return 1
        if n in memo:
            return memo[n]
        value = n*factorial(n-1)
        memo[n] = value
        return value
    
    def ncr(n, k):
        """
        Choose k elements from a set of n elements - n must be larger than or equal to k
        :param n: int
        :param k: int
        :rtype: int
        """
        return factorial(n)/(factorial(k)*factorial(n-k))
    

    If we compare times

    from scipy.special import comb
    %timeit comb(100,48)
    >>> 100000 loops, best of 3: 6.78 µs per loop
    
    %timeit ncr(100,48)
    >>> 1000000 loops, best of 3: 1.39 µs per loop
    
    0 讨论(0)
  • 2020-11-27 10:48

    It's pretty easy with sympy.

    import sympy
    
    comb = sympy.binomial(n, r)
    
    0 讨论(0)
提交回复
热议问题