2017-08-16 1 views
2

Supposons que j'ai deux nivelé dataframeComment agréger des sous-données dans des pandas?

In [1]: index = pd.MultiIndex.from_tuples([(i,j) for i in range(3) 
     :           for j in range(1+i)], names=list('ij')) 
     : df = pd.DataFrame(0.1*np.arange(2*len(index)).reshape(-1,2), 
     :     columns=list('xy'), index=index) 
     : df 
Out[1]: 
     x y 
i j 
0 0 0.0 0.1 
1 0 0.2 0.3 
    1 0.4 0.5 
2 0 0.6 0.7 
    1 0.8 0.9 
    2 1.0 1.1 

multi-indexé et je veux exécuter une fonction personnalisée sur chaque sous-trame de données:

In [2]: def my_aggr_func(subdf): 
     :  return subdf['x'].mean()/subdf['y'].mean() 
     : 
     : level0 = df.index.levels[0].values 
     : pd.DataFrame({'mean_ratio': [my_aggr_func(df.loc[i]) for i in level0]}, 
     :    index=pd.Index(level0, name=index.names[0])) 
Out[2]: 
    mean_ratio 
i 
0 0.000000 
1 0.750000 
2 0.888889 

Y at-il une façon élégante de le faire avec df.groupby('i').agg(__something__) ou quelque chose de similaire?

Répondre

2

Besoin GroupBy.apply, qui travaille avec DataFrame:

df1 = df.groupby('i').apply(my_aggr_func).to_frame('mean_ratio') 
print (df1) 
    mean_ratio 
i    
0 0.000000 
1 0.750000 
2 0.888889 
+1

Merci! J'ai complètement oublié "appliquer". –

1

Vous n'avez pas besoin de la fonction personnalisée. Vous pouvez calculer les 'moyens de groupe' avec agg puis effectuer un eval pour obtenir le ratio que vous voulez.

df.groupby('i').agg('mean').eval('x/y') 

i 
0 0.000000 
1 0.750000 
2 0.888889 
dtype: float64 
+0

Je veux quelque chose de plus sophistiqué. Par exemple, ajustez 'y (x)' avec des paramètres de fonction et de sortie. –

+0

Je vous conseille d'accepter la réponse de @ jezrael et d'en poser une autre avec votre problème spécifique. Souvent, quelqu'un sur SO peut aider à trouver une solution plus sophistiquée à votre problème plus sophistiqué. Et si 'fit 'signifie régression, vous pourriez envisager de mettre une balise' sklearn' et 'numpy' sur votre nouvelle question. De cette façon, les autres personnes intelligentes qui suivent ces balises et non «[pandas]» le verront également. – piRSquared