web-dev-qa-db-fra.com

Calculer la moyenne pondérée à l'aide d'un pandas / cadre de données

J'ai le tableau suivant. Je veux calculer une moyenne pondérée groupée par chaque date en fonction de la formule ci-dessous. Je peux le faire en utilisant du code conventionnel standard, mais en supposant que ces données sont dans un pandas dataframe, y a-t-il un moyen plus facile d'y parvenir plutôt que par itération?

Date        ID      wt      value   w_avg
01/01/2012  100     0.50    60      0.791666667
01/01/2012  101     0.75    80
01/01/2012  102     1.00    100
01/02/2012  201     0.50    100     0.722222222
01/02/2012  202     1.00    80

01/01/2012 w_avg = 0,5 * (60/somme (60,80,100)) + 0,75 * (80/somme (60,80,100)) + 1,0 * (100/somme (60,80,100))

01/02/2012 w_avg = 0,5 * (100/somme (100,80)) + 1,0 * (80/somme (100,80))

29
mike01010

Je pense que je le ferais avec deux groupbys.

Tout d'abord pour calculer la "moyenne pondérée":

In [11]: g = df.groupby('Date')

In [12]: df.value / g.value.transform("sum") * df.wt
Out[12]:
0    0.125000
1    0.250000
2    0.416667
3    0.277778
4    0.444444
dtype: float64

Si vous définissez cela comme une colonne, vous pouvez le grouper dessus:

In [13]: df['wa'] = df.value / g.value.transform("sum") * df.wt

Maintenant, la somme de cette colonne est la souhaitée:

In [14]: g.wa.sum()
Out[14]:
Date
01/01/2012    0.791667
01/02/2012    0.722222
Name: wa, dtype: float64

ou potentiellement:

In [15]: g.wa.transform("sum")
Out[15]:
0    0.791667
1    0.791667
2    0.791667
3    0.722222
4    0.722222
Name: wa, dtype: float64
22
Andy Hayden

Créons d'abord l'exemple pandas dataframe:

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: index = pd.Index(['01/01/2012','01/01/2012','01/01/2012','01/02/2012','01/02/2012'], name='Date')

In [4]: df = pd.DataFrame({'ID':[100,101,102,201,202],'wt':[.5,.75,1,.5,1],'value':[60,80,100,100,80]},index=index)

Ensuite, la moyenne de "wt" pondérée par "valeur" et regroupée par l'indice est obtenue comme suit:

In [5]: df.groupby(df.index).apply(lambda x: np.average(x.wt, weights=x.value))
Out[5]: 
Date
01/01/2012    0.791667
01/02/2012    0.722222
dtype: float64

Alternativement, on peut également définir une fonction:

In [5]: def grouped_weighted_avg(values, weights, by):
   ...:     return (values * weights).groupby(by).sum() / weights.groupby(by).sum()

In [6]: grouped_weighted_avg(values=df.wt, weights=df.value, by=df.index)
Out[6]: 
Date
01/01/2012    0.791667
01/02/2012    0.722222
dtype: float64
19
kadee

J'ai enregistré la table dans le fichier .csv

df=pd.read_csv('book1.csv')

grouped=df.groupby('Date')
g_wavg= lambda x: np.average(x.wt, weights=x.value)
grouped.apply(g_wavg)
6
user15051990

Je pense que ce qui suit est une solution élégante à ce problème: ( fonction d'agrégation Pandas DataFrame utilisant plusieurs colonnes )

grouped = df.groupby('Date')

def wavg(group):
    d = group['value']
    w = group['wt']
    return (d * w).sum() / w.sum()

grouped.apply(wavg)
5
Anish Sugathan