Pandas teilen DataFrame nach Spaltenwert auf


76

Ich habe DataFramemit Spalte Sales.

Wie kann ich es basierend auf dem SalesWert in 2 aufteilen ?

Erstens DataFramewerden Daten mit 'Sales' < sund zweitens mit'Sales' >= s


Wie teile ich den Datenrahmen basierend auf den Spaltenwerten in mehrere Datenrahmen auf? Wenn ich den Datenrahmen basierend auf 'Sales'> s1 und 'Sales' <s2 aufteilen möchte?
Ganesh MS

Antworten:


103

Sie können verwenden boolean indexing:

df = pd.DataFrame({'Sales':[10,20,30,40,50], 'A':[3,4,7,6,1]})
print (df)
   A  Sales
0  3     10
1  4     20
2  7     30
3  6     40
4  1     50

s = 30

df1 = df[df['Sales'] >= s]
print (df1)
   A  Sales
2  7     30
3  6     40
4  1     50

df2 = df[df['Sales'] < s]
print (df2)
   A  Sales
0  3     10
1  4     20

Es ist auch möglich zu invertieren maskdurch ~:

mask = df['Sales'] >= s
df1 = df[mask]
df2 = df[~mask]
print (df1)
   A  Sales
2  7     30
3  6     40
4  1     50

print (df2)
   A  Sales
0  3     10
1  4     20

print (mask)
0    False
1    False
2     True
3     True
4     True
Name: Sales, dtype: bool

print (~mask)
0     True
1     True
2    False
3    False
4    False
Name: Sales, dtype: bool

7
Gibt es eine Möglichkeit, dies zu tun, ohne den Datenrahmen zweimal in Scheiben schneiden zu müssen? Denn auf diese Weise müssen wir den Index nur einmal verschieben, um df1 zu erstellen, und ein anderes Mal für genau die gleiche Bedingung für df2. Aber ich kann nicht herausfinden, wie man beide Datenrahmen in einer einzigen Zeile
erhält

1
Leider denke ich, dass es nur diese Lösung gibt - siehe Kochbuch .
Jezrael

Was ist der Leistungsunterschied zwischen der Verwendung maskund dem herkömmlichen Schneiden? Meine Tests zeigen, dass die Maske etwas schneller ist, aber keinen großen Unterschied
3pitt

@ Mike Palmice Hmm, wenn Sie denken, der erste oder zweite Absatz ist von der gleichen Leistung, liegt es an Ihnen, welche Methode für Sie besser ist. Zweitens sollte besser sein, wenn mehrere Male kombiniert werden muss oder wenn eine Maske wiederverwendet werden muss, auch wenn einige lange, komplizierte Masken besser lesbar sein sollten.
Jezrael

1
Nicht genau, aber ich habe es herausgefunden, indem ich eine for-Schleife gemacht habe. Durchlaufen jedes eindeutigen Spaltenwerts und anschließendes Teilen des df durch den Wert durch Schneiden. Eigentlich nicht allzu schwer, ich weiß nicht einmal, warum ich gefragt habe. Trotzdem danke.
Odisseo

48

Mit können groupbySie in zwei Datenrahmen wie teilen

In [1047]: df1, df2 = [x for _, x in df.groupby(df['Sales'] < 30)]

In [1048]: df1
Out[1048]:
   A  Sales
2  7     30
3  6     40
4  1     50

In [1049]: df2
Out[1049]:
   A  Sales
0  3     10
1  4     20

3
Diese Operation scheint wesentlich teurer zu sein als die beiden Optionen von Jezrael, obwohl syntaktisch eleganter imo
3pitt

3
Dies entspricht nicht vollständig den Optionen von Jezrael. Wenn einer der Datensätze nach dem Teilen leer ist, gibt group by eine Liste mit nur einem Element zurück und kann nicht in df1 und df2 entpackt werden.
Hgrey

21

Verwenden von "groupby" und Listenverständnis:

Speichern des gesamten geteilten Datenrahmens in der Listenvariablen und Zugreifen auf jeden der getrennten Datenrahmen über deren Index.

DF = pd.DataFrame({'chr':["chr3","chr3","chr7","chr6","chr1"],'pos':[10,20,30,40,50],})
ans = [pd.DataFrame(y) for x, y in DF.groupby('chr', as_index=False)]

Zugriff auf den getrennten DF wie folgt:

ans[0]
ans[1]
ans[len(ans)-1] # this is the last separated DF

Zugriff auf den Spaltenwert des getrennten DF wie folgt:

ansI_chr=ans[i].chr 

Das ist eine großartige Antwort!
Taylrl

8
Ich denke, Sie können vereinfachen, ans = [y for x, y in DF.groupby('chr', as_index=False)]da y bereits ein DataFrame ist
C8H10N4O2

1
Diese Antwort hängt nicht von der Anzahl der Teilungen ab. Es sollte zur Nummer 1 gewählt werden. Es muss nur gemäß dem Kommentar von @ C8H10N4O2 aktualisiert werden
msarafzadeh
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.