Gewichtete Standardabweichung in NumPy

75

numpy.average()hat eine Gewichtsoption, numpy.std()tut dies aber nicht. Hat jemand Vorschläge für eine Problemumgehung?

YGA
quelle
Übrigens ist die Berechnung des gewichteten Standardentwicklers ein ziemlich komplexes Thema - es gibt mehr als einen Weg, dies zu tun. Eine großartige Diskussion finden Sie hier: stata.com/support/faqs/statistics/…
JohnE

Antworten:

128

Wie wäre es mit der folgenden kurzen "manuellen Berechnung"?

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))
Eric O Lebigot
quelle
6
Warum nicht noch numpy.averageeinmal für die Varianz verwenden?
user2357112 unterstützt Monica
4
Ich wollte nur darauf hinweisen, dass dies die voreingenommene Varianz ergibt. Bei kleinen Stichprobengrößen möchten Sie möglicherweise die Varianz (vor sqrt) neu skalieren, um die unverzerrte Varianz zu erhalten. Siehe en.wikipedia.org/wiki/…
Corey
1
Ja, der unverzerrte Varianzschätzer wäre etwas anders. Diese Antwort gibt die Standardabweichung an, da die Frage nach einer gewichteten Version von fragt numpy.std().
Eric O Lebigot
1
Danke für diese Lösung ... aber warum benutzt du math.sqrtstatt np.sqrtam Ende?
Raphael
1
np.sqrt()würde funktionieren, aber weil variancees sich um ein einfaches (Numpy) Float handelt (und nicht um ein NumPy-Array), math.sqrt()ist es expliziter und angemessener (und daher im Allgemeinen schneller, wenn dies wichtig ist).
Eric O Lebigot
39

Es gibt eine Klasse statsmodels, die die Berechnung gewichteter Statistiken erleichtert : statsmodels.stats.weightstats.DescrStatsW.

Angenommen, dieser Datensatz und diese Gewichte:

import numpy as np
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

Sie initialisieren die Klasse (beachten Sie, dass Sie an dieser Stelle den Korrekturfaktor, die Delta- Freiheitsgrade , übergeben müssen):

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

Dann können Sie berechnen:

  • .meandas gewichtete Mittel :

    >>> weighted_stats.mean      
    1.97196261682243
    
  • .stddie gewichtete Standardabweichung :

    >>> weighted_stats.std       
    0.21434289609681711
    
  • .vardie gewichtete Varianz :

    >>> weighted_stats.var       
    0.045942877107170932
    
  • .std_meander Standardfehler des gewichteten Mittelwerts:

    >>> weighted_stats.std_mean  
    0.020818822467555047
    

    Nur für den Fall, dass Sie an der Beziehung zwischen dem Standardfehler und der Standardabweichung interessiert sind: Der Standardfehler wird (für ddof == 0) als gewichtete Standardabweichung geteilt durch die Quadratwurzel der Summe der Gewichte minus 1 berechnet ( entsprechende Quelle für die statsmodelsVersion) 0,9 auf GitHub ):

    standard_error = standard_deviation / sqrt(sum(weights) - 1)
    
MSeifert
quelle
Informationen zur einfachen Berechnung des gewichteten Variationskoeffizienten finden Sie in dieser Antwort .
Acumenus
14

Hier ist noch eine Option:

np.sqrt(np.cov(values, aweights=weights))
Löwe
quelle
6

Es scheint noch keine solche Funktion in numpy / scipy zu geben, aber es gibt ein Ticket , das diese zusätzliche Funktionalität vorschlägt. Dort finden Sie Statistics.py, das gewichtete Standardabweichungen implementiert.

unutbu
quelle
1

Es gibt ein sehr gutes Beispiel von 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

Richtige Gleichung für gewichtete unverzerrte Stichproben-Kovarianz, URL (Version: 28.06.2016)

abah
quelle