2010-03-09 48 views
52

numpy.average() tiene una opción de pesos, pero numpy.std() no. ¿Alguien tiene sugerencias para una solución alternativa?Desviación estándar ponderada en NumPy?

+0

Por cierto, el cálculo de std dev ponderada en realidad es un tema bastante complejo - hay más de una manera de hacerlo. Vea aquí para una gran discusión: https://www.stata.com/support/faqs/statistics/weights-and-summary-statistics/ – JohnE

Respuesta

80

¿Qué le parece el siguiente breve "cálculo manual"?

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

¿Por qué no usar 'numpy.average' nuevamente para la varianza? – user2357112

+4

Solo quería señalar que esto dará la varianza sesgada. Para tamaños de muestra pequeños, es posible que desee volver a escalar la varianza (antes de sqrt) para obtener la varianza imparcial. Consulte https://en.wikipedia.org/wiki/Weighted_variance#Weighted_sample_variance – Corey

+1

Sí, el estimador de varianza imparcial sería ligeramente diferente. Esta respuesta da la desviación estándar, ya que la pregunta solicita una versión ponderada de 'numpy.std()'. – EOL

6

No parece haber tal función en numpy/scipy todavía, pero hay un ticket que propone esta funcionalidad adicional. Incluido allí encontrará Statistics.py que implementa las desviaciones estándar ponderadas.

13

Hay una clase de statsmodels para calcular las estadísticas ponderadas: 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 característica interesante de esta clase es que si se quiere calcular diferentes propiedades estadísticas llamadas posteriores serán muy rápido porque los resultados ya calculados (incluso intermedios) se almacenan en caché.

1

hay un muy buen ejemplo propuesto por 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)

Cuestiones relacionadas