2016-05-10 15 views
7

Zuerst sagen, dass ich neu zu Pandas bin.Python pandas: Spalte zu gruppierten DataFrame mit Methodenverkettung hinzufügen

Ich versuche, eine neue Spalte in einem DataFrame zu erstellen. Ich kann das wie in meinem Beispiel gezeigt machen. Aber ich möchte dies durch Verkettung von Methoden tun, also muss ich keine neuen Variablen zuweisen. Lassen Sie mich zuerst, was ich erreichen will, und dem, was ich habe dies bisher getan:

In [1]: 
import numpy as np 
from pandas import Series,DataFrame 
import pandas as pd 

In [2]: 
np.random.seed(10) 
df=pd.DataFrame(np.random.randint(1,5,size=(10, 3)), columns=list('ABC')) 
df 

Out [2]: 
A B C 
2 2 1 
4 1 2 
4 1 2 
2 1 2 
2 3 1 
2 1 3 
1 3 1 
4 1 1 
4 4 3 
1 4 3 
In [3]: 
filtered_DF = df[df['B']<2].copy() 
grouped_DF = filtered_DF.groupby('A') 
filtered_DF['C_Share_By_Group'] =filtered_DF.C.div(grouped_DF.C.transform("sum")) 
filtered_DF 

Out [3]: 
A B C C_Share_By_Group 
4 1 2    0.4 
4 1 2    0.4 
2 1 2    0.4 
2 1 3    0.6 
4 1 1    0.2 

ich die gleiche Sache durch Verkettung Methoden erreichen wollen. In R mit dplyr Paket, würde ich in der Lage sein, etwas zu tun:

df %>% 
    filter(B<2) %>% 
    group_by(A) %>% 
    mutate('C_Share_By_Group'=C/sum(C)) 

Im pandas documentation es sagt, dass mutate in R (dplyr) zu assign in Pandas gleich ist, aber assign funktioniert nicht auf einem gruppierten Objekt. Wenn ich versuche, etwas zu gruppiert Datenrahmen zuweisen, erhalte ich eine Fehlermeldung:

"AttributeError: Cannot access callable attribute 'assign' of 'DataFrameGroupBy' objects, try using the 'apply' method"

ich folgende ausprobiert haben, aber nicht wissen, wie die neue Spalte hinzuzufügen, oder ob es überhaupt möglich ist, dies zu erreichen, von Verkettungs Methoden:

(df.loc[df.B<2] 
    .groupby('A') 
    #****WHAT GOES HERE?**** apply(something)? 
) 
+0

Willkommen in der Welt traurig aus funktional imperative Programmierung. Sie können die Transformation in Python verwenden –

Antwort

7

können Sie versuchen, assign:

print df[df['B']<2].assign(C_Share_By_Group=lambda df: 
         df.C 
         .div(df.groupby('A') 
          .C 
          .transform("sum"))) 

    A B C C_Share_By_Group 
1 4 1 2    0.4 
2 4 1 2    0.4 
3 2 1 2    0.4 
5 2 1 3    0.6 
7 4 1 1    0.2 
+0

Vielen Dank für den Versuch. Ich glaube einfach nicht, dass dies die Antwort ist, nach der ich gesucht habe. Eine der Schönheiten der Methodenverkettung besteht darin, dass Sie die Dinge nicht zweimal machen müssen, da Sie die Ausgabe der Methode weitergeben. In Ihrem Ansatz filtern Sie den gleichen Datenrahmen dreimal ('df ['B'] <2]'). – LauH

+0

Danke. Sie haben Recht, also wurde die Antwort bearbeitet und unnötiger Code entfernt. Bitte überprüfen Sie es jetzt. – jezrael

+0

Ich habe versucht, Ihren Code auszuführen, aber das Ergebnis entspricht nicht meinem Code. C_Share_By_Group 0,250000 0,250000 0,285714 0,428571 0,125000 – LauH

Verwandte Themen