Pandas group-by et sum

207

J'utilise ce bloc de données:

Fruit   Date      Name  Number
Apples  10/6/2016 Bob    7
Apples  10/6/2016 Bob    8
Apples  10/6/2016 Mike   9
Apples  10/7/2016 Steve 10
Apples  10/7/2016 Bob    1
Oranges 10/7/2016 Bob    2
Oranges 10/6/2016 Tom   15
Oranges 10/6/2016 Mike  57
Oranges 10/6/2016 Bob   65
Oranges 10/7/2016 Tony   1
Grapes  10/7/2016 Bob    1
Grapes  10/7/2016 Tom   87
Grapes  10/7/2016 Bob   22
Grapes  10/7/2016 Bob   12
Grapes  10/7/2016 Tony  15

Je veux agréger cela par nom puis par fruit pour obtenir un nombre total de fruits par nom.

Bob,Apples,16 ( for example )

J'ai essayé de regrouper par nom et fruit, mais comment obtenir le nombre total de fruits.

Trying_hard
la source

Réponses:

211

Utilisation GroupBy.sum:

df.groupby(['Fruit','Name']).sum()

Out[31]: 
               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Grapes  Bob        35
        Tom        87
        Tony       15
Oranges Bob        67
        Mike       57
        Tom        15
        Tony        1
Steven G
la source
95
Comment les pandas peuvent-ils savoir que je veux additionner le col nommé Number?
Kingname
12
@Kingname c'est la dernière colonne à gauche si vous supprimez NAME et FRUIT. si vous ajoutez 2 colonnes à gauche, cela résumerait les deux colonnes
Steven G
9
Comment spécifier quelle colonne additionner?
tgdn
36
@tgdn df.groupby (['Nom', 'Fruit']) ['Numéro']. sum ()
Steven G
2
@StevenG Pour que la réponse fournie résume une colonne spécifique, la sortie se présente sous la forme d'une série Pandas au lieu de Dataframe. D'après le commentaire de Jakub Kukul (dans la réponse ci-dessous), nous pouvons utiliser des crochets doubles autour de «Number» pour obtenir un Dataframe.
skdhfgeq2134
179

Vous pouvez également utiliser la fonction agg,

df.groupby(['Name', 'Fruit'])['Number'].agg('sum')
Saurabh
la source
1
Cela diffère de la réponse acceptée en ce que cela renvoie un Seriestandis que l'autre renvoie un GroupByobjet.
Gaurang Tandon
11
@GaurangTandon pour obtenir un DataFrameobjet à la place (comme dans la réponse acceptée), utilisez des crochets doubles autour 'Number', c'est-à-dire:df.groupby(['Name', 'Fruit'])[['Number']].agg('sum')
Jakub Kukul
1
Très utile pour nettoyer le rapport de requête mal encodé.
avirr
93

Si vous souhaitez conserver les colonnes d'origine Fruitet Name, utilisez reset_index(). Sinon, Fruitil Namefera partie de l'index.

df.groupby(['Fruit','Name'])['Number'].sum().reset_index()

Fruit   Name       Number
Apples  Bob        16
Apples  Mike        9
Apples  Steve      10
Grapes  Bob        35
Grapes  Tom        87
Grapes  Tony       15
Oranges Bob        67
Oranges Mike       57
Oranges Tom        15
Oranges Tony        1

Comme on le voit dans les autres réponses:

df.groupby(['Fruit','Name'])['Number'].sum()

               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Grapes  Bob        35
        Tom        87
        Tony       15
Oranges Bob        67
        Mike       57
        Tom        15
        Tony        1
Gazala Muhamed
la source
43

Les deux autres réponses accomplissent ce que vous voulez.

Vous pouvez utiliser la pivotfonctionnalité pour organiser les données dans un joli tableau

df.groupby(['Fruit','Name'],as_index = False).sum().pivot('Fruit','Name').fillna(0)



Name    Bob     Mike    Steve   Tom    Tony
Fruit                   
Apples  16.0    9.0     10.0    0.0     0.0
Grapes  35.0    0.0     0.0     87.0    15.0
Oranges 67.0    57.0    0.0     15.0    1.0
Demetri Pananos
la source
19
df.groupby(['Fruit','Name'])['Number'].sum()

Vous pouvez sélectionner différentes colonnes pour additionner les nombres.

jared
la source
7

Vous pouvez définir la groupbycolonne pour index ensuite utiliser sumaveclevel

df.set_index(['Fruit','Name']).sum(level=[0,1])
Out[175]: 
               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Oranges Bob        67
        Tom        15
        Mike       57
        Tony        1
Grapes  Bob        35
        Tom        87
        Tony       15
YOBEN_S
la source
3

Une variation sur la fonction .agg (); offre la possibilité (1) de conserver le type DataFrame, (2) d'appliquer des moyennes, des comptes, des sommations, etc. et (3) permet de grouper sur plusieurs colonnes tout en conservant la lisibilité.

df.groupby(['att1', 'att2']).agg({'att1': "count", 'att3': "sum",'att4': 'mean'})

en utilisant vos valeurs ...

df.groupby(['Name', 'Fruit']).agg({'Number': "sum"})
xxyjoel
la source