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?
Répondre
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))
Pourquoi ne pas utiliser 'numpy.average' de nouveau pour la variance? – user2357112
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
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
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.
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.
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)
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