Les pandas totalisent par groupby, mais excluent certaines colonnes

88

Quelle est la meilleure façon de faire un groupby sur un dataframe Pandas, mais d'exclure certaines colonnes de ce groupby? Par exemple, j'ai le dataframe suivant:

Code   Country      Item_Code   Item    Ele_Code    Unit    Y1961    Y1962   Y1963
2      Afghanistan  15          Wheat   5312        Ha      10       20      30
2      Afghanistan  25          Maize   5312        Ha      10       20      30
4      Angola       15          Wheat   7312        Ha      30       40      50
4      Angola       25          Maize   7312        Ha      30       40      50

Je veux regrouper par la colonne Country et Item_Code et calculer uniquement la somme des lignes tombant sous les colonnes Y1961, Y1962 et Y1963. Le dataframe résultant devrait ressembler à ceci:

Code   Country      Item_Code   Item    Ele_Code    Unit    Y1961    Y1962   Y1963
2      Afghanistan  15          C3      5312        Ha      20       40       60
4      Angola       25          C4      7312        Ha      60       80      100

En ce moment, je fais ceci:

df.groupby('Country').sum()

Cependant, cela ajoute également les valeurs de la colonne Item_Code. Existe-t-il un moyen de spécifier les colonnes à inclure dans l' sum()opération et celles à exclure?

user308827
la source

Réponses:

117

Vous pouvez sélectionner les colonnes d'un groupe par:

In [11]: df.groupby(['Country', 'Item_Code'])[["Y1961", "Y1962", "Y1963"]].sum()
Out[11]:
                       Y1961  Y1962  Y1963
Country     Item_Code
Afghanistan 15            10     20     30
            25            10     20     30
Angola      15            30     40     50
            25            30     40     50

Notez que la liste passée doit être un sous-ensemble des colonnes sinon vous verrez une KeyError.

Andy Hayden
la source
1
Comment inclure le nombre d'enregistrements pour chaque pays et code d'article dans une autre colonne?
Sushant Kulkarni
Vous pouvez créer une colonne fictive avant de grouper par celle qui contient juste 1. alors somme les additionnera pour créer un décompte.
Matt W.
Si vous voulez simplement exclure une colonne ou deux, alors vous obtenez tous les noms de colonnes comme dans listColumns = list(df.columns)puis vous supprimez les colonnes que vous ne voulez pas, listColumns.remove('Y1964')et enfin faites votre addition:df.groupby(['Country', 'Item_Code'])[listColumns].sum()
Roberto Stelling
Merci beaucoup. Je peux faire fonctionner le groupby, mais pas la partie sélection. La liste des colonnes que j'ai insérées fait partie du dataframe, mais elle continue d'augmenter ValueError:cannot reindex from a duplicate axis
Bowen Liu
@BowenLiu si vous avez plusieurs colonnes avec le même nom, cela affichera cette erreur. Dans ce cas, vous devrez utiliser iloc to ou loc pour obtenir les colonnes que vous voulez, je pense que vous devrez le faire avant le groupby.
Andy Hayden
40

La aggfonction le fera pour vous. Passez les colonnes et fonctionnent comme un dict avec colonne, sortie:

df.groupby(['Country', 'Item_Code']).agg({'Y1961': np.sum, 'Y1962': [np.sum, np.mean]})  # Added example for two output columns from a single input column

Cela affichera uniquement le groupe par colonnes et les colonnes d'agrégation spécifiées. Dans cet exemple, j'ai inclus deux fonctions agg appliquées à «Y1962».

Pour obtenir exactement ce que vous espériez voir, incluez les autres colonnes du groupe par et appliquez des sommes aux variables Y dans le cadre:

df.groupby(['Code', 'Country', 'Item_Code', 'Item', 'Ele_Code', 'Unit']).agg({'Y1961': np.sum, 'Y1962': np.sum, 'Y1963': np.sum})
leroyJr
la source
1
merci, cela peut-il être généralisé? J'ai beaucoup de colonnes de la forme Y1961 ... donc je génère une liste comme celle-ci: yrs = ['Y' + str (x) pour x in range (1961, 2010 + 1, 1)]. Votre solution peut-elle utiliser «yrs» à l'intérieur d'agg?
user308827
J'aime vraiment cette idée. L'astuce consiste à construire ce dict avec la valeur étant la fonction somme numpy. À l'inverse, si tout ce que vous voulez faire est de faire la somme de toutes les colonnes restantes, votre solution originale fonctionnera si toutes les colonnes group by sont incluses dans l'instruction group by.
leroyJr
11

Si vous recherchez une manière plus générale d'appliquer à de nombreuses colonnes, vous pouvez créer une liste de noms de colonnes et la transmettre en tant qu'index du dataframe groupé. Dans votre cas, par exemple:

columns = ['Y'+str(i) for year in range(1967, 2011)]

df.groupby('Country')[columns].agg('sum')
Superstar
la source