Pandas summieren sich nach Gruppen, schließen jedoch bestimmte Spalten aus

86

Was ist der beste Weg, um einen Groupby in einem Pandas-Datenrahmen durchzuführen, aber einige Spalten von diesem Groupby auszuschließen? zB habe ich folgenden Datenrahmen:

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

Ich möchte nach der Spalte Country und Item_Code gruppieren und nur die Summe der Zeilen berechnen, die unter die Spalten Y1961, Y1962 und Y1963 fallen. Der resultierende Datenrahmen sollte folgendermaßen aussehen:

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

Im Moment mache ich das:

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

Dies addiert jedoch auch die Werte in der Spalte Item_Code. Kann ich auf irgendeine Weise angeben, welche Spalten in die sum()Operation aufgenommen und welche ausgeschlossen werden sollen?

user308827
quelle

Antworten:

117

Sie können die Spalten einer Gruppe auswählen nach:

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

Beachten Sie, dass die übergebene Liste eine Teilmenge der Spalten sein muss, da sonst ein KeyError angezeigt wird.

Andy Hayden
quelle
1
Wie kann die Anzahl der Datensätze für jedes Land und jeden Artikelcode als weitere Spalte eingefügt werden?
Sushant Kulkarni
Sie können vor der Gruppierung eine Dummy-Spalte erstellen, die nur 1 enthält. Dann summiert die Summe diejenigen, die eine Zählung erstellen.
Matt W.
Wenn Sie nur eine oder zwei Spalten ausschließen möchten, erhalten Sie alle Spaltennamen wie in, listColumns = list(df.columns)dann entfernen Sie die nicht gewünschten Spalten listColumns.remove('Y1964')und führen schließlich Ihre Summierung durch:df.groupby(['Country', 'Item_Code'])[listColumns].sum()
Roberto Stelling
Vielen Dank. Ich kann die Gruppe zum Arbeiten bringen, aber nicht den Auswahlteil. Die Liste der Spalten, die ich eingefügt habe, befindet sich im Datenrahmen, erhöht aber immer wieder ValueError:cannot reindex from a duplicate axis
Bowen Liu
@BowenLiu Wenn Sie mehrere Spalten mit demselben Namen haben, wird dieser Fehler angezeigt. In diesem Fall müssen Sie iloc to oder loc verwenden, um die gewünschten Spalten abzurufen. Ich denke, Sie müssen dies vor dem Groupby tun.
Andy Hayden
40

Die aggFunktion erledigt dies für Sie. Übergeben Sie die Spalten und fungieren Sie als Diktat mit Spalte, Ausgabe:

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

Dadurch werden nur die Gruppe nach Spalten und die angegebenen Aggregatspalten angezeigt. In diesem Beispiel habe ich zwei Agg-Funktionen eingefügt, die auf 'Y1962' angewendet wurden.

Um genau das zu erhalten, was Sie sich erhofft hatten, haben Sie die anderen Spalten in die Gruppe von aufgenommen und Summen auf die Y-Variablen im Frame angewendet:

df.groupby(['Code', 'Country', 'Item_Code', 'Item', 'Ele_Code', 'Unit']).agg({'Y1961': np.sum, 'Y1962': np.sum, 'Y1963': np.sum})
leroyJr
quelle
1
danke, kann das verallgemeinert werden? Ich habe viele Spalten der Form Y1961 ... also erstelle ich eine Liste wie diese: yrs = ['Y' + str (x) für x im Bereich (1961, 2010 + 1, 1)]. Kann Ihre Lösung "Jahre" in agg verwenden?
user308827
Diese Idee gefällt mir sehr gut. Der Trick besteht darin, dieses Diktat so zu konstruieren, dass der Wert die Zahlensummenfunktion ist. Umgekehrt würde Ihre ursprüngliche Lösung funktionieren, wenn Sie nur alle verbleibenden Spalten summieren möchten, wenn alle Spalten nach Gruppe in der Anweisung "Gruppe nach" enthalten sind.
leroyJr
11

Wenn Sie nach einer allgemeineren Methode suchen, um sie auf viele Spalten anzuwenden, können Sie eine Liste mit Spaltennamen erstellen und diese als Index des gruppierten Datenrahmens übergeben. In Ihrem Fall zum Beispiel:

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

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