L'asymétrie est un paramètre permettant de mesurer la symétrie d'un ensemble de données et le kurtosis pour mesurer le poids de ses queues par rapport à une distribution normale, voir par exemple ici .
scipy.stats
fournit un moyen facile de calculer ces deux quantités, voir scipy.stats.kurtosis
et scipy.stats.skew
.
D'après ma compréhension, l'asymétrie et le kurtosis d'un distribution normale devraient tous deux être égaux à 0 en utilisant les fonctions susmentionnées. Ce n'est cependant pas le cas avec mon code:
import numpy as np
from scipy.stats import kurtosis
from scipy.stats import skew
x = np.linspace( -5, 5, 1000 )
y = 1./(np.sqrt(2.*np.pi)) * np.exp( -.5*(x)**2 ) # normal distribution
print( 'excess kurtosis of normal distribution (should be 0): {}'.format( kurtosis(y) ))
print( 'skewness of normal distribution (should be 0): {}'.format( skew(y) ))
La sortie est:
kurtose en excès de distribution normale (doit être 0): -0,307393087742
asymétrie de la distribution normale (doit être 0): 1.11082371392
Qu'est-ce que je fais mal ?
Les versions que j'utilise sont
python: 2.7.6
scipy : 0.17.1
numpy : 1.12.1
Ces fonctions calculent les moments de la distribution de la densité de probabilité (c'est pourquoi il ne prend qu'un paramètre) et ne se soucient pas de la "forme fonctionnelle" des valeurs.
Celles-ci sont destinées à des "ensembles de données aléatoires" (considérez-les comme des mesures telles que la moyenne, l'écart type, la variance):
import numpy as np
from scipy.stats import kurtosis, skew
x = np.random.normal(0, 2, 10000) # create random values based on a normal distribution
print( 'excess kurtosis of normal distribution (should be 0): {}'.format( kurtosis(x) ))
print( 'skewness of normal distribution (should be 0): {}'.format( skew(x) ))
qui donne:
excess kurtosis of normal distribution (should be 0): -0.024291887786943356
skewness of normal distribution (should be 0): 0.009666157036010928
changer le nombre de valeurs aléatoires augmente la précision:
x = np.random.normal(0, 2, 10000000)
Menant à:
excess kurtosis of normal distribution (should be 0): -0.00010309478605163847
skewness of normal distribution (should be 0): -0.0006751744848755031
Dans votre cas, la fonction "suppose" que chaque valeur a la même "probabilité" (car les valeurs sont distribuées de manière égale et que chaque valeur n'apparaît qu'une seule fois), donc du point de vue de skew
et kurtosis
il s'agit d'une densité de probabilité non gaussienne (vous ne savez pas exactement de quoi il s'agit), ce qui explique pourquoi les valeurs obtenues ne sont même pas proches de 0
:
import numpy as np
from scipy.stats import kurtosis, skew
x_random = np.random.normal(0, 2, 10000)
x = np.linspace( -5, 5, 10000 )
y = 1./(np.sqrt(2.*np.pi)) * np.exp( -.5*(x)**2 ) # normal distribution
import matplotlib.pyplot as plt
f, (ax1, ax2) = plt.subplots(1, 2)
ax1.hist(x_random, bins='auto')
ax1.set_title('probability density (random)')
ax2.hist(y, bins='auto')
ax2.set_title('(your dataset)')
plt.tight_layout()
Vous utilisez comme données la "forme" de la fonction de densité. Ces fonctions sont destinées à être utilisées avec des données échantillonnées à partir d'une distribution. Si vous échantillonnez à partir de la distribution, vous obtiendrez des statistiques d'échantillon qui s'approcheront de la valeur correcte à mesure que vous augmentez la taille de l'échantillon. Pour tracer les données, je recommanderais un histogramme.
%matplotlib inline
import numpy as np
import pandas as pd
from scipy.stats import kurtosis
from scipy.stats import skew
import matplotlib.pyplot as plt
plt.style.use('ggplot')
data = np.random.normal(0, 1, 10000000)
np.var(data)
plt.hist(data, bins=60)
print("mean : ", np.mean(data))
print("var : ", np.var(data))
print("skew : ",skew(data))
print("kurt : ",kurtosis(data))
Sortie:
mean : 0.000410213500847
var : 0.999827716979
skew : 0.00012294118186476907
kurt : 0.0033554829466604374
Sauf si vous utilisez une expression analytique, il est extrêmement improbable que vous obteniez un zéro lorsque vous utilisez des données.