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)

470voto

Wouter Overmeire Punkte 63916

Ich bin mir nicht ganz sicher, was Sie wollen, und Ihre letzte Codezeile ist auch nicht hilfreich, aber egal:

Die "verkettete" Filterung erfolgt durch "Verkettung" der Kriterien im booleschen Index.

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

Wenn Sie Methoden verketten möchten, können Sie Ihre eigene Maskenmethode hinzufügen und diese verwenden.

In [90]: def mask(df, key, value):
   ....:     return df[df[key] == value]
   ....:

In [92]: pandas.DataFrame.mask = mask

In [93]: df = pandas.DataFrame(np.random.randint(0, 10, (4,4)), index=list('abcd'), columns=list('ABCD'))

In [95]: df.ix['d','A'] = df.ix['a', 'A']

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 [97]: df.mask('A', 1)
Out[97]:
   A  B  C  D
a  1  4  9  1
d  1  3  9  6

In [98]: df.mask('A', 1).mask('D', 6)
Out[98]:
   A  B  C  D
d  1  3  9  6

156voto

bscan Punkte 2626

Filter können mit Hilfe eines Pandas verkettet werden Abfrage :

df = pd.DataFrame(np.random.randn(30, 3), columns=['a','b','c'])
df_filtered = df.query('a > 0').query('0 < b < 2')

Filter können auch in einer einzigen Abfrage kombiniert werden:

df_filtered = df.query('a > 0 and 0 < b < 2')

75voto

Daniel Punkte 25675

Die Antwort von @lodagro ist großartig. Ich würde sie erweitern, indem ich die Maskenfunktion verallgemeinere als:

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

Dann können Sie Dinge tun wie:

df.mask(lambda x: x[0] < 0).mask(lambda x: x[1] > 0)

40voto

Rafael Barbosa Punkte 1010

Seit Version 0.18.1 die .loc Methode akzeptiert einen Callable zur Auswahl. Zusammen mit Lambda-Funktionen können Sie sehr flexible verkettbare Filter erstellen:

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
df.loc[lambda df: df.A == 80]  # equivalent to df[df.A == 80] but chainable

df.sort_values('A').loc[lambda df: df.A > 80].loc[lambda df: df.B > df.A]

Wenn Sie nur filtern wollen, können Sie auch die .loc .

33voto

Pietro Battiston Punkte 7097

Pandas bietet zwei Alternativen zur Antwort von Wouter Overmeire, die kein Overriding erfordern. Die eine ist .loc[.] mit einem Callable, wie in

df_filtered = df.loc[lambda x: x['column'] == value]

das andere ist .pipe() wie in

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

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