Większość operacji w pandas można osiągnąć za pomocą łańcucha operatora (groupby, aggregate, apply, apply itp.), Ale jedynym sposobem, w jaki znalazłem filtrowanie wierszy indeksowanie wspornika

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

Jest to nieaktualne, ponieważ wymaga przypisania df do zmiennej przed możliwością filtrowania jego wartości. Czy jest coś więcej jak następujące?

df_filtered = df.mask(lambda x: x['column'] == value)
356
duckworthd 8 sierpień 2012, 21:25

13 odpowiedzi

Najlepsza odpowiedź

Nie jestem całkowicie pewien, co chcesz, a twoja ostatnia linia kodu też nie pomaga, ale w każdym razie:

Filtrowanie "Przykuwanie" odbywa się przez "łańcuch" kryteria w indeksie boolskim.

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

Jeśli chcesz mieszać metody, możesz dodać własną metodę maski i użyć tego.

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
416
Andrew 20 grudzień 2016, 15:23

Filtry mogą być przykutane za pomocą pandy zapytanie :

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

Filtry można również łączyć w pojedynczym zapytaniu:

df_filtered = df.query('a > 0 and 0 < b < 2')
119
Rémy Hosseinkhan Boucher 13 luty 2020, 15:56

Odpowiedź @lodagro jest świetna. Rozszerzyłbym go przez uogólnienie funkcji maski jako:

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

Wtedy możesz zrobić takie rzeczy jak:

df.mask(lambda x: x[0] < 0).mask(lambda x: x[1] > 0)
70
Daniel 9 sierpień 2012, 23:20

Ponieważ wersja 0.18.1 The {{x0 }} Metoda akceptuje wywołanie do wyboru. Wraz z funkcjami Lambda można tworzyć bardzo elastyczne filtry łańcuchowe:

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]

Jeśli wszystko, co robisz, to filtrowanie, możesz również pominąć .loc.

26
Rafael Barbosa 5 wrzesień 2017, 10:14

Oferuję to za dodatkowe przykłady. Jest to ta sama odpowiedź, co https://stackoverflow.com/a/28159296/

Dodam inne edycje, aby ten post był bardziej przydatny.

pandas.DataFrame.query
query został wykonany dokładnie w tym celu. Rozważmy dataframe 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

Użyjmy query, aby filtrować wszystkie wiersze, gdzie 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

Który łańcuchy

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
16
piRSquared 16 kwiecień 2018, 17:47

Pandas zapewnia dwie alternatywy dla odpowiedziach overmeire, które nie wymagają nadrzędnej. Jeden jest .loc[.] z kalalnym, jak w

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

Drugi to .pipe(), jak w

df_filtered = df.pipe(lambda x: x['column'] == value)
11
Pietro Battiston 22 marzec 2018, 14:44

Miałem to samo pytanie, z wyjątkiem tego, że chciałem połączyć kryteria w lub stan. Format podany przez Wouter Overmeire łączy kryteria w sposób, w którym oba muszą być spełnione:

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

Ale odkryłem, że jeśli owijasz każdy warunek w (... == True) i dołącz do kryteriów z rurą, kryteria są łączone w lub warunku, spełnione, gdy którykolwiek z nich jest prawdziwy:

df[((df.A==1) == True) | ((df.D==6) == True)]
10
sharon 25 marzec 2015, 04:00

Moja odpowiedź jest podobna do innych. Jeśli nie chcesz utworzyć nowej funkcji, możesz użyć, jakie pandas już się zdefiniował. Użyj metody rur.

df.pipe(lambda d: d[d['column'] == value])
7
Stewbaca 27 maj 2016, 19:00

Jeśli chcesz zastosować wszystkie wspólne maski boolowskie, a także maskę ogólnej przeznaczenia, możesz uchwycić następujące informacje w pliku, a następnie po prostu przypisać je wszystkie następujące:

pd.DataFrame = apply_masks()

Stosowanie:

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

To trochę hacky, ale może sprawić, że rzeczy nieco czyszczenia, jeśli nie stale cięcia i zmieniając zestawy danych zgodnie z filtrami. Istnieje również filtr ogólnego przeznaczenia przystosowany z Daniela Velkova powyżej w funkcji Gen_maszki, które można używać z funkcjami Lambda lub w przeciwnym razie w razie potrzeby.

Plik, który ma zostać zapisany (używam maseks.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
4
dantes_419 18 kwiecień 2013, 04:44

Po prostu chcę dodać demonstrację za pomocą loc, aby filtrować nie tylko wierszami, ale także kolumnami i pewnymi zasługami na działanie przycisków.

Poniższy kod może przefiltrować wiersze według wartości.

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

Modyfikując go trochę, możesz również filtrować kolumny.

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

Dlaczego więc chcemy metodę przykuwaną? Odpowiedź jest to, że jest proste do czytania, jeśli masz wiele operacji. Na przykład,

res =  df\
    .loc[df['station']=='USA', ['TEMP', 'RF']]\
    .groupby('year')\
    .agg(np.nanmean)
3
Ken T 29 styczeń 2018, 06:18

Jest to nieaktualne, ponieważ wymaga przypisania df do zmiennej przed możliwością filtrowania jego wartości.

df[df["column_name"] != 5].groupby("other_column_name")

Wydaje się, że działa: możesz również zagnieżdżać operatora []. Może go dodali, ponieważ zadałeś pytanie.

3
serv-inc 4 czerwiec 2019, 14:33

Możesz także wykorzystać bibliotekę numpy dla operacji logicznych. Jest dość szybki.

df[np.logical_and(df['A'] == 1 ,df['B'] == 6)]
2
Akash Basudevan 25 styczeń 2018, 07:22

Jeśli ustawisz kolumny do wyszukiwania jako indeksów, możesz użyć DataFrame.xs(), aby przejść przekrój. Nie jest tak wszechstronne jak odpowiedzi query, ale może być przydatne w niektórych sytuacjach.

import pandas as pd
import numpy as np

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

df
# Out[55]: 
#    A  B  C  D  E
# 0  0  2  2  2  2
# 1  1  1  2  0  2
# 2  0  2  0  0  2
# 3  0  2  2  0  1
# 4  0  1  1  2  0
# 5  0  0  0  1  2
# 6  1  0  1  1  1
# 7  0  0  2  0  2
# 8  2  2  2  2  2
# 9  1  2  0  2  1

df.set_index(['A', 'D']).xs([0, 2]).reset_index()
# Out[57]: 
#    A  D  B  C  E
# 0  0  2  2  2  2
# 1  0  2  1  1  0
1
naught101 26 lipiec 2017, 03:35