2010-03-09 17 views
52

numpy.average() a une option de poids, mais pas numpy.std(). Quelqu'un at-il des suggestions pour une solution de contournement?Écart-type pondéré en NumPy?

+0

BTW, calcul de dev pondéré std est en fait un sujet assez complexe - il y a plus d'une façon de le faire. Voir ici pour une bonne discussion: https://www.stata.com/support/faqs/statistics/weights-and-summary-statistics/ – JohnE

Répondre

80

Que diriez-vous du court "calcul manuel" suivant?

def weighted_avg_and_std(values, weights): 
    """ 
    Return the weighted average and standard deviation. 

    values, weights -- Numpy ndarrays with the same shape. 
    """ 
    average = numpy.average(values, weights=weights) 
    # Fast and numerically precise: 
    variance = numpy.average((values-average)**2, weights=weights) 
    return (average, math.sqrt(variance)) 
+2

Pourquoi ne pas utiliser 'numpy.average' de nouveau pour la variance? – user2357112

+4

Je voulais juste souligner que cela donnera la variance biaisée. Pour de petits échantillons, vous pouvez rééchelonner la variance (avant sqrt) pour obtenir la variance non biaisée. Voir https://en.wikipedia.org/wiki/Weighted_variance#Weighted_sample_variance – Corey

+1

Ouais, l'estimateur de la variance sans biais serait légèrement différent. Cette réponse donne l'écart-type, puisque la question demande une version pondérée de 'numpy.std()'. – EOL

6

Il ne semble pas encore exister une telle fonction dans numpy/scipy, mais il existe une ticket proposant cette fonctionnalité supplémentaire. Vous trouverez ici Statistics.py qui implémente des écarts-types pondérés.

13

Il y a une classe statsmodels pour calculer les statistiques pondérées: statsmodels.stats.weightstats.DescrStatsW:

from statsmodels.stats.weightstats import DescrStatsW 

array = np.array([1,2,1,2,1,2,1,3]) 
weights = np.ones_like(array) 
weights[3] = 100 

weighted_stats = DescrStatsW(array, weights=weights, ddof=0) 

weighted_stats.mean  # weighted mean of data (equivalent to np.average(array, weights=weights)) 
# 1.97196261682243 

weighted_stats.std  # standard deviation with default degrees of freedom correction 
# 0.21434289609681711 

weighted_stats.std_mean # standard deviation of weighted mean 
# 0.020818822467555047 

weighted_stats.var  # variance with default degrees of freedom correction 
# 0.045942877107170932 

La belle caractéristique de cette classe est que si vous voulez calculer des propriétés statistiques des appels ultérieurs seront très rapides, car les résultats déjà calculés (même intermédiaires) sont mis en cache.

1

Il est un très bon exemple proposé par gaborous:

import pandas as pd 
import numpy as np 
# X is the dataset, as a Pandas' DataFrame 
mean = mean = np.ma.average(X, axis=0, weights=weights) # Computing the 
weighted sample mean (fast, efficient and precise) 

# Convert to a Pandas' Series (it's just aesthetic and more 
# ergonomic; no difference in computed values) 
mean = pd.Series(mean, index=list(X.keys())) 
xm = X-mean # xm = X diff to mean 
xm = xm.fillna(0) # fill NaN with 0 (because anyway a variance of 0 is 
just void, but at least it keeps the other covariance's values computed 
correctly)) 
sigma2 = 1./(w.sum()-1) * xm.mul(w, axis=0).T.dot(xm); # Compute the 
unbiased weighted sample covariance 

Correct equation for weighted unbiased sample covariance, URL (version: 2016-06-28)