421 Stimmen

pandas: Zeilen von DataFrame mit Operatorverkettung filtern

Die meisten Operationen in pandas kann mit der Verkettung von Operatoren erreicht werden ( groupby , aggregate , apply usw.), aber die einzige Möglichkeit, die ich gefunden habe, um Zeilen zu filtern, ist über die normale Klammerindizierung

df_filtered = df[df['column'] == value]

Dies ist unattraktiv, da es erfordert, dass ich die df auf eine Variable übertragen werden, bevor man nach deren Werten filtern kann. Gibt es etwas, das mehr wie das Folgende aussieht?

df_filtered = df.mask(lambda x: x['column'] == value)

18voto

piRSquared Punkte 269273

Ich biete dies als weitere Beispiele an. Dies ist die gleiche Antwort wie https://stackoverflow.com/a/28159296/

Ich werde weitere Änderungen vornehmen, um diesen Beitrag nützlicher zu machen.

pandas.DataFrame.query
query wurde genau für diesen Zweck geschaffen. Betrachten Sie den Datenrahmen df

import pandas as pd
import numpy as np

np.random.seed([3,1415])
df = pd.DataFrame(
    np.random.randint(10, size=(10, 5)),
    columns=list('ABCDE')
)

df

   A  B  C  D  E
0  0  2  7  3  8
1  7  0  6  8  6
2  0  2  0  4  9
3  7  3  2  4  3
4  3  6  7  7  4
5  5  3  7  5  9
6  8  7  6  4  7
7  6  2  6  6  5
8  2  8  7  5  8
9  4  7  6  1  5

Verwenden wir query um alle Zeilen zu filtern, in denen D > B

df.query('D > B')

   A  B  C  D  E
0  0  2  7  3  8
1  7  0  6  8  6
2  0  2  0  4  9
3  7  3  2  4  3
4  3  6  7  7  4
5  5  3  7  5  9
7  6  2  6  6  5

Die wir verketten

df.query('D > B').query('C > B')
# equivalent to
# df.query('D > B and C > B')
# but defeats the purpose of demonstrating chaining

   A  B  C  D  E
0  0  2  7  3  8
1  7  0  6  8  6
4  3  6  7  7  4
5  5  3  7  5  9
7  6  2  6  6  5

12voto

Stewbaca Punkte 525

Meine Antwort ist ähnlich wie die der anderen. Wenn Sie keine neue Funktion erstellen möchten, können Sie verwenden, was Pandas bereits für Sie definiert hat. Verwenden Sie die Pipe-Methode.

df.pipe(lambda d: d[d['column'] == value])

10voto

sharon Punkte 4266

Ich hatte dieselbe Frage, nur dass ich die Kriterien zu einer ODER-Bedingung kombinieren wollte. Das von Wouter Overmeire angegebene Format kombiniert die Kriterien zu einer UND-Bedingung, so dass beide erfüllt sein müssen:

In [96]: df
Out[96]:
   A  B  C  D
a  1  4  9  1
b  4  5  0  2
c  5  5  1  0
d  1  3  9  6

In [99]: df[(df.A == 1) & (df.D == 6)]
Out[99]:
   A  B  C  D
d  1  3  9  6

Aber ich habe festgestellt, dass, wenn man jede Bedingung in (... == True) und die Kriterien mit einer Pipe verbinden, werden die Kriterien zu einer ODER-Bedingung kombiniert, die immer dann erfüllt ist, wenn eines der beiden Kriterien wahr ist:

df[((df.A==1) == True) | ((df.D==6) == True)]

7voto

Ken T Punkte 1924

Ich möchte nur eine Demonstration hinzufügen mit loc um nicht nur nach Zeilen, sondern auch nach Spalten zu filtern und einige Vorzüge der verketteten Operation zu nutzen.

Der folgende Code kann die Zeilen nach Wert filtern.

df_filtered = df.loc[df['column'] == value]

Wenn Sie es ein wenig ändern, können Sie die Spalten auch filtern.

df_filtered = df.loc[df['column'] == value, ['year', 'column']]

Warum brauchen wir also eine verkettete Methode? Die Antwort ist, dass sie einfach zu lesen ist, wenn man viele Operationen hat. Zum Beispiel,

res =  df\
    .loc[df['station']=='USA', ['TEMP', 'RF']]\
    .groupby('year')\
    .agg(np.nanmean)

4voto

dantes_419 Punkte 189

Wenn Sie alle gebräuchlichen booleschen Masken sowie eine Allzweckmaske anwenden möchten, können Sie Folgendes in eine Datei packen und dann einfach alle Masken wie folgt zuweisen:

pd.DataFrame = apply_masks()

Uso:

A = pd.DataFrame(np.random.randn(4, 4), columns=["A", "B", "C", "D"])
A.le_mask("A", 0.7).ge_mask("B", 0.2)... (May be repeated as necessary

Es ist zwar etwas umständlich, aber es kann die Dinge ein wenig sauberer machen, wenn Sie ständig Datensätze entsprechend den Filtern zerschneiden und ändern. Es gibt auch einen Allzweckfilter, der von Daniel Velkov oben in der gen_mask-Funktion angepasst wurde und den Sie mit Lambda-Funktionen oder anderweitig verwenden können, falls gewünscht.

Zu speichernde Datei (ich verwende masks.py):

import pandas as pd

def eq_mask(df, key, value):
    return df[df[key] == value]

def ge_mask(df, key, value):
    return df[df[key] >= value]

def gt_mask(df, key, value):
    return df[df[key] > value]

def le_mask(df, key, value):
    return df[df[key] <= value]

def lt_mask(df, key, value):
    return df[df[key] < value]

def ne_mask(df, key, value):
    return df[df[key] != value]

def gen_mask(df, f):
    return df[f(df)]

def apply_masks():

    pd.DataFrame.eq_mask = eq_mask
    pd.DataFrame.ge_mask = ge_mask
    pd.DataFrame.gt_mask = gt_mask
    pd.DataFrame.le_mask = le_mask
    pd.DataFrame.lt_mask = lt_mask
    pd.DataFrame.ne_mask = ne_mask
    pd.DataFrame.gen_mask = gen_mask

    return pd.DataFrame

if __name__ == '__main__':
    pass

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X