есть ли более эффективный способ перечислить вероятности для каждого из возможных результатов дискретной случайной величины в python или R?

#python #r #numpy #probability

#python #r #numpy #вероятность

Вопрос:

Я теоретически вычисляю pmf на Python. вот код.

 >>> a_coin = np.array([0,1])
>>> three_coins = np.array(np.meshgrid(a_coin,a_coin,a_coin)).T.reshape(-1,3)
>>> heads = np.sum(three_coins, axis = 1)
>>> df = pd.DataFrame({'heads': heads, 'prob': 1/8})
>>> np.array(df.groupby('heads').sum()['prob'])
array([0.125, 0.375, 0.375, 0.125])
  

этот фрагмент кода имитирует 1 бросок из 3 честных монет.
возможные результаты — {0,1,2,3}.
в последней строке кода вычисляется вероятность для каждого из возможных результатов соответственно.

Я должен поместить 10 ‘a_coin’ в np.meshgrid (a_coin, …, a_coin), если я хочу вычислить pmf для подбрасывания 10 честных монет, что кажется скучным и неэффективным.

вопрос в том, есть ли более эффективный способ сделать это в python или R?

Комментарии:

1. Использовать математические формулы? Биномиальные коэффициенты и т.д…

Ответ №1:

Вот как это сделать в R:

 > sapply(0:3, choose, n=3)/sum(sapply(0:3, choose, n=3))
[1] 0.125 0.375 0.375 0.125
  

choose Функция выдает вам биномиальные коэффициенты. Чтобы превратить их в вероятности, просто разделите на их суммы:

 sapply(0:10, choose, n=10)
 [1]   1  10  45 120 210 252 210 120  45  10   1

sapply(0:10, choose, n=10)/ sum( sapply(0:10, choose, n=10))
 [1] 0.0009765625 0.0097656250 0.0439453125 0.1171875000 0.2050781250 0.2460937500 0.2050781250
 [8] 0.1171875000 0.0439453125 0.0097656250 0.0009765625
  

Похоже, вы действительно не хотели столько перечислять, сколько вычислять. Если вам нужно перечислить результаты 10 последовательных «честных» биномиальных розыгрышей, то вы могли бы использовать combn 11 раз.

Ответ №2:

Вот fft основанное numpy решение:

 import numpy as np
from scipy import fftpack

def toss(n=10, p=0.5):
    t1 = np.zeros(fftpack.next_fast_len(n 1))
    t1[:2] = 1-p, p
    f1 = fftpack.rfft(t1)
    c1 = f1[1:(len(t1) - 1) // 2 * 2   1].view(f'c{2*t1.itemsize}')
    c1 **= n
    f1[::(len(t1)   1) // 2 * 2 - 1] **= n
    return fftpack.irfft(f1)[:n 1]
  

Например:

 >>> toss(3)
array([0.125, 0.375, 0.375, 0.125])
>>> toss(10)
array([0.00097656, 0.00976562, 0.04394531, 0.1171875 , 0.20507813,
       0.24609375, 0.20507813, 0.1171875 , 0.04394531, 0.00976562,
       0.00097656])
  

Ответ №3:

Используя стандартные библиотеки Python, вы можете получить вероятности в виде рациональных чисел (это точное решение), например

 from fractions import Fraction
from math import factorial

n=30
[Fraction(factorial(n), factorial(n - j)) * Fraction(1, factorial(j) * 2 ** n) for j in range(0, n   1)]
  

Это может быть легко преобразовано в значения с плавающей точкой, например

 list(map(float, [Fraction(factorial(n), factorial(n - j)) * Fraction(1, factorial(j) * 2 ** n) for j in range(0, n   1)]))