2013-02-21 2 views
16

J'essaye d'enrouler ma tête autour des méthodes de Pandas groupby. Je voudrais écrire une fonction qui fait des fonctions d'agrégation et retourne ensuite un DataFrame Pandas. Voici un exemple grossièrement simplifié utilisant sum(). Je sais qu'il existe des moyens plus faciles à faire des sommes simples, dans la vie réelle ma fonction est plus complexe:retournant agrégé dataframe de pandas groupby

import pandas as pd 
df = pd.DataFrame({'col1': ['A', 'A', 'B', 'B'], 'col2':[1.0, 2, 3, 4]}) 

In [3]: df 
Out[3]: 
    col1 col2 
0 A  1 
1 A  2 
2 B  3 
3 B  4 

def func2(df): 
    dfout = pd.DataFrame({ 'col1' : df['col1'].unique() , 
          'someData': sum(df['col2']) }) 
    return dfout 

t = df.groupby('col1').apply(func2) 

In [6]: t 
Out[6]: 
     col1 someData 
col1     
A 0 A   3 
B 0 B   7 

Je ne pensais pas avoir col1 là-dedans deux fois n'a pas non plus je pense que l'indice de mystère regardant la chose. Je pensais vraiment que je voudrais juste obtenir col1 & someData.

Dans mon application réelle, je regroupe plus d'une colonne et j'aimerais vraiment récupérer un objet DataFrame et non un objet Series.
Des idées pour une solution ou une explication sur ce que Pandas est en train de faire dans mon exemple ci-dessus?

----- ----- ajouté Informations

je aurais dû commencer par cet exemple, je pense:

In [13]: import pandas as pd 

In [14]: df = pd.DataFrame({'col1':['A','A','A','B','B','B'], 'col2':['C','D','D','D','C','C'], 'col3':[.1,.2,.4,.6,.8,1]}) 

In [15]: df 
Out[15]: 
    col1 col2 col3 
0 A C 0.1 
1 A D 0.2 
2 A D 0.4 
3 B D 0.6 
4 B C 0.8 
5 B C 1.0 

In [16]: def func3(df): 
    ....:   dfout = sum(df['col3']**2) 
    ....:   return dfout 
    ....: 

In [17]: t = df.groupby(['col1', 'col2']).apply(func3) 

In [18]: t 
Out[18]: 
col1 col2 
A  C  0.01 
     D  0.20 
B  C  1.64 
     D  0.36 

Dans l'illustration ci-dessus le résultat de la fonction apply() est une série Pandas. Et il manque les colonnes groupby de la df.groupby. L'essence de ce à quoi je me bats est comment créer une fonction que j'applique à un groupe en lui retournant à la fois le résultat de la fonction ET les colonnes sur lesquelles il a été groupé?

----- ------ encore une autre mise à jour

Il semble que si je le fais alors:

pd.DataFrame(t).reset_index() 

je reviens un dataframe qui est vraiment proche de ce que j'étais après.

+1

BTW, ce tutoriel par l'un des programmeurs de pandas m'a aidé à comprendre la mécanique de GroupBy et l'agrégation des pandas géants: https://www.youtube.com/watch?v=MxRMXhjXZos – Zelazny7

+0

Dans l'exemple que vous avez joint en annexe , quel est le but du groupby (il va juste trouver dupes), vous pouvez juste faire une application à df lui-même et l'ajouter comme une colonne: 'df ['func3'] = df.appliquer (ligne lambda: ligne ['col2'] ** 2, axe = 1) '. ? –

+0

Les données sont un peu trop simples pour l'exemple, j'en ai peur. Je vais mettre à jour l'exemple. –

Répondre

6

La raison pour laquelle vous voyez les colonnes avec 0 est parce que la sortie de .unique() est un tableau.

La meilleure façon de comprendre comment votre application va travailler est d'inspecter chaque groupe sage l'action:

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

In [12]: g.get_group('A') 
Out[12]: 
    col1 col2 
0 A  1 
1 A  2 

In [13]: g.get_group('A')['col1'].unique() 
Out[13]: array([A], dtype=object) 

In [14]: sum(g.get_group('A')['col2']) 
Out[14]: 3.0 

La plupart du temps, vous voulez que ce soit une valeur agrégée .

La sortie de grouped.apply aura toujours les étiquettes de groupe sous forme d'index (les valeurs uniques de « col1 »), de sorte que votre construction exemple de col1 me semble un peu obtus.

Remarque: Pour afficher 'col1' (l'index) dans une colonne, vous pouvez appeler reset_index, dans ce cas.

In [15]: g.sum().reset_index() 
Out[15]: 
    col1 col2 
0 A  3 
1 B  7 
+0

Merci pour l'explication sur le tableau. J'apporte clairement mon bagage R à Python. –

+0

pour une fonction arbitraire que j'applique, le groupby semble déposer mes colonnes de regroupement du résultat et retourne seulement une série de réponses. Il est clair que l'utilisation de la méthode sum() contourne cela, mais cela n'est pas utile pour les fonctions personnalisées qui ne sont pas implémentées en tant que méthodes groupby. J'ai ajouté un exemple à ma question pour mieux illustrer. –

+0

@JDLong êtes-vous groupby sur chaque colonne? (pour moi, cela semble une chose étrange à faire, mais je suis d'accord que la sortie est un peu bizarre: ne pas avoir le MultiIndex des colonnes): s –