web-dev-qa-db-fra.com

Calculer la fonction de distribution cumulative (CDF) en Python

Comment puis-je calculer en python la fonction de distribution cumulative (CDF) ?

Je veux le calculer à partir d'un tableau de points que j'ai (distribution discrète), et non à l'aide des distributions continues que scipy, par exemple.

8
wizbcn

(Il est possible que mon interprétation de la question soit fausse. Si la question est de savoir comment passer d’un PDF discret à un CDF discret, alors np.cumsum divisé par une constante appropriée suffira si les échantillons sont équidistants. Si le tableau n'est pas à égale distance, alors np.cumsum du tableau multiplié par les distances entre les points fera l'affaire.) 

Si vous avez un tableau d'échantillons discret et que vous souhaitez connaître le CDF de l'échantillon, vous pouvez simplement trier le tableau. Si vous regardez le résultat trié, vous réaliserez que la plus petite valeur représente 0% et la plus grande valeur 100%. Si vous voulez connaître la valeur à 50% de la distribution, il suffit de regarder l'élément de tableau qui se trouve au milieu du tableau trié.

Voyons cela de plus près avec un exemple simple:

import matplotlib.pyplot as plt
import numpy as np

# create some randomly ddistributed data:
data = np.random.randn(10000)

# sort the data:
data_sorted = np.sort(data)

# calculate the proportional values of samples
p = 1. * arange(len(data)) / (len(data) - 1)

# plot the sorted data:
fig = figure()
ax1 = fig.add_subplot(121)
ax1.plot(p, data_sorted)
ax1.set_xlabel('$p$')
ax1.set_ylabel('$x$')

ax2 = fig.add_subplot(122)
ax2.plot(data_sorted, p)
ax2.set_xlabel('$x$')
ax2.set_ylabel('$p$')

Cela donne le graphique suivant où le graphique de droite est la fonction de distribution cumulative traditionnelle. Cela devrait refléter le CDF du processus derrière les points, mais naturellement ce n'est pas tant que le nombre de points est fini.

cumulative distribution function

Cette fonction est facile à inverser, cela dépend de votre application et du formulaire dont vous avez besoin.

18
DrV

En supposant que vous sachiez comment vos données sont distribuées (c’est-à-dire que vous connaissez le pdf de vos données), alors scipy prend en charge les données discrètes lors du calcul des cdf.

import numpy as np
import scipy
import matplotlib.pyplot as plt
import seaborn as sns

x = np.random.randn(10000) # generate samples from normal distribution (discrete data)
norm_cdf = scipy.stats.norm.cdf(x) # calculate the cdf - also discrete

# plot the cdf
sns.lineplot(x=x, y=norm_cdf)
plt.show()

 enter image description here

Nous pouvons même imprimer les premières valeurs de la cdf pour montrer qu'elles sont discrètes

print(norm_cdf[:10])
>>> array([0.39216484, 0.09554546, 0.71268696, 0.5007396 , 0.76484329,
       0.37920836, 0.86010018, 0.9191937 , 0.46374527, 0.4576634 ])

La même méthode pour calculer le fichier cdf fonctionne également pour plusieurs dimensions: nous utilisons les données 2D ci-dessous pour illustrer

mu = np.zeros(2) # mean vector
cov = np.array([[1,0.6],[0.6,1]]) # covariance matrix
# generate 2d normally distributed samples using 0 mean and the covariance matrix above
x = np.random.multivariate_normal(mean=mu, cov=cov, size=1000) # 1000 samples
norm_cdf = scipy.stats.norm.cdf(x)
print(norm_cdf.shape)
>>> (1000, 2)

Dans les exemples ci-dessus, je savais auparavant que mes données étaient normalement distribuées. C'est pourquoi j'ai utilisé scipy.stats.norm() - il existe plusieurs types de supports scipy pour les distributions. Mais encore une fois, vous devez savoir au préalable comment vos données sont distribuées pour utiliser ces fonctions. Si vous ne savez pas comment vos données sont distribuées et que vous utilisez simplement une distribution pour calculer le fichier cdf, vous obtiendrez probablement des résultats incorrects.

0
PyRsquared