Suma pandy według grupowania, ale wyklucz niektóre kolumny

88

Jaki jest najlepszy sposób wykonania grupowania w ramce danych Pandas, ale wykluczyć niektóre kolumny z tej grupy? np. mam następującą ramkę danych:

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

Chcę pogrupować według kolumn Country i Item_Code i obliczyć tylko sumę wierszy należących do kolumn Y1961, Y1962 i Y1963. Wynikowa ramka danych powinna wyglądać następująco:

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

Teraz robię to:

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

Jednak sumuje to również wartości w kolumnie Item_Code. Czy istnieje sposób, w jaki mogę określić, które kolumny należy uwzględnić w sum()operacji, a które wykluczyć?

user308827
źródło

Odpowiedzi:

117

Możesz wybrać kolumny grupy według:

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

Zauważ, że przekazana lista musi być podzbiorem kolumn, w przeciwnym razie zobaczysz KeyError.

Andy Hayden
źródło
1
Jak uwzględnić liczbę rekordów dla każdego kraju i kodu towaru w innej kolumnie?
Sushant Kulkarni
Możesz utworzyć fikcyjną kolumnę przed grupowaniem, która zawiera tylko 1, a następnie suma zsumuje te, tworząc liczbę.
Matt W.,
Jeśli chcesz tylko wykluczyć jedną lub dwie kolumny, otrzymujesz wszystkie nazwy kolumn, tak jak w, listColumns = list(df.columns)a następnie usuwasz kolumny, których nie chcesz, listColumns.remove('Y1964')i na koniec wykonaj podsumowanie:df.groupby(['Country', 'Item_Code'])[listColumns].sum()
Roberto Stelling
Wielkie dzięki. Mogę zmusić grupę do pracy, ale nie część dotyczącą wyboru. Lista kolumn, które umieściłem, znajduje się w ramce danych, ale wciąż podnosi wartość ValueError:cannot reindex from a duplicate axis
Bowen Liu
@BowenLiu, jeśli masz wiele kolumn o tej samej nazwie, wyświetli ten błąd. W takim przypadku będziesz musiał użyć iloc do lub loc, aby uzyskać żądane kolumny, myślę, że będziesz musiał to zrobić przed grupowaniem.
Andy Hayden
40

aggFunkcja zrobi to za Ciebie. Przekaż kolumny i działaj jako dykt z kolumną, wyjście:

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

Spowoduje to wyświetlenie tylko grupy według kolumn i określonych kolumn zagregowanych. W tym przykładzie zawarłem dwie funkcje agowe zastosowane do „Y1962”.

Aby uzyskać dokładnie to, co chciałeś zobaczyć, uwzględnij inne kolumny w grupie według i zastosuj sumy do zmiennych Y w ramce:

df.groupby(['Code', 'Country', 'Item_Code', 'Item', 'Ele_Code', 'Unit']).agg({'Y1961': np.sum, 'Y1962': np.sum, 'Y1963': np.sum})
leroyJr
źródło
1
dzięki, czy można to uogólnić? Mam wiele kolumn w formacie Y1961 ... więc generuję taką listę: yrs = ['Y' + str (x) for x in range (1961, 2010 + 1, 1)]. Czy Twoje rozwiązanie może wykorzystywać „rok” w środku agu?
user308827
Naprawdę podoba mi się ten pomysł. Sztuczka polega na skonstruowaniu tego dyktu z wartością będącą funkcją numpy sum. I odwrotnie, jeśli wszystko, co chcesz zrobić, to zsumować wszystkie pozostałe kolumny, pierwotne rozwiązanie zadziałałoby, gdyby wszystkie kolumny grupuj według kolumn były zawarte w instrukcji grupuj według.
leroyJr
11

Jeśli szukasz bardziej uogólnionego sposobu zastosowania do wielu kolumn, możesz utworzyć listę nazw kolumn i przekazać ją jako indeks zgrupowanej ramki danych. W Twoim przypadku na przykład:

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

df.groupby('Country')[columns].agg('sum')
Super gwiazda
źródło