2016-11-03 15 views
5

Moje pytanie dotyczy operacji grupowej z pandami. Mam następujący DataFrame:Jak wykonać operację grupowania pand przez jedną kolumnę, ale zachować drugą w wynikowej ramce danych

In [4]: df = pd.DataFrame({"A": range(4), "B": ["PO", "PO", "PA", "PA"], "C": ["Est", "Est", "West", "West"]}) 

In [5]: df 
Out[5]: 
    A B  C 
0 0 PO Est 
1 1 PO Est 
2 2 PA West 
3 3 PA West 

To, co chciałbym zrobić: Chcę grupy przez kolumny B i zrobić pewną sumę na kolumnie A. Ale w końcu, chciałbym kolumny C, aby nadal być w DataFrame. Jeśli to zrobię:

In [8]: df.groupby(by="B").aggregate(pd.np.sum) 
Out[8]: 
    A 
B  
PA 5 
PO 1 

Wykonuje zadanie, ale brakuje kolumny C. Mogę też to zrobić:

In [9]: df.groupby(by=["B", "C"]).aggregate(pd.np.sum) 
Out[9]: 
     A 
B C  
PA West 5 
PO Est 1 

lub

In [11]: df.groupby(by=["B", "C"], as_index=False).aggregate(pd.np.sum) 
Out[11]: 
    B  C A 
0 PA West 5 
1 PO Est 1 

Ale w obu przypadkach przez grupę B i C oraz B i nie tylko utrzymuje wartość C. Czy to, co chcę zrobić, nie ma znaczenia, czy jest jakiś sposób na zrobienie tego?

Odpowiedz

8

spróbować użyć DataFrameGroupBy.agg() metodę z dict of {column -> function}:

In [6]: df.groupby('B').agg({'A':'sum', 'C':'first'}) 
Out[6]: 
     C A 
B 
PA West 5 
PO Est 1 

Od docs:

funkcji do wykorzystania na koncentrację grup. Jeśli funkcja, musi działać po przejściu do DataFrame lub po przekazaniu do DataFrame.apply. Jeśli przekazał dict, klucze muszą być nazwami kolumn DataFrame.

lub coś w tym rodzaju w zależności od celów:

In [8]: df = pd.DataFrame({"A": range(4), "B": ["PO", "PO", "PA", "PA"], "C": ["Est1", "Est2", "West1", "West2"]}) 

In [9]: df.groupby('B').agg({'A':'sum', 'C':'first'}) 
Out[9]: 
     C A 
B 
PA West1 5 
PO Est1 1 

In [10]: df['sum_A'] = df.groupby('B')['A'].transform('sum') 

In [11]: df 
Out[11]: 
    A B  C sum_A 
0 0 PO Est1  1 
1 1 PO Est2  1 
2 2 PA West1  5 
3 3 PA West2  5 
+0

To działa, jeśli 'wartość C' jest taka sama w stosunku do wszystkich wartości, które są zgrupowane. W przeciwnym razie zadanie "scal". – Khris

+0

@Khris, dziękuję za podpowiedź! Dodałem alternatywne rozwiązanie, które wykorzystuje '.transform()' method – MaxU

+0

Wonderful !! Wielkie dzięki. – Ger