1
votes

existe-t-il un moyen plus efficace d'énumérer la probabilité pour chacun des résultats possibles d'une variable aléatoire discrète en python ou R?

Je calcule le pmf théoriquement en Python. voici le code.

>>> 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])

ce morceau de code simule 1 lancer de 3 pièces justes. les résultats possibles sont {0,1,2,3}. la dernière ligne de code calcule respectivement la probabilité pour chacun des résultats possibles.

Je dois mettre 10 'a_coin' dans np.meshgrid (a_coin, ..., a_coin) si je veux calculer le pmf pour lancer 10 pièces justes, ce qui semble ennuyeux et inefficace.

la question est, y a-t-il un moyen plus efficace de faire cela en python ou R?


1 commentaires

Utilisez des formules mathématiques? Coeffs binomiaux etc ...


3 Réponses :


1
votes

Voici comment le faire dans R:

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

La fonction choose vous donne les coefficients binomiaux. Pour les transformer en probabilités, divisez simplement par leurs sommations:

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

Il ne semble pas que vous vouliez vraiment énumérer autant que calculer. Si vous avez besoin d'énumérer les résultats de 10 tirages binomiaux "équitables" successifs, vous pouvez utiliser combn 11 fois.


0 commentaires

0
votes

En utilisant les bibliothèques standard Python, vous pouvez obtenir des probabilités sous forme de nombres rationnels (c'est la solution exacte), par exemple

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

Cela pourrait être facilement converti en flottants, par exemple

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)]


0 commentaires

1
votes

Voici une solution fft basée sur numpy :

>>> 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])

Par exemple:

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]


0 commentaires