Aby przefiltrować ramkę danych (df) według pojedynczej kolumny, jeśli weźmiemy pod uwagę dane dotyczące mężczyzn i kobiet, możemy:
males = df[df[Gender]=='Male']
Pytanie 1 - Ale co, jeśli dane obejmują wiele lat i chciałbym zobaczyć tylko mężczyzn w 2014 roku?
W innych językach mógłbym zrobić coś takiego:
if A = "Male" and if B = "2014" then
(poza tym, że chcę to zrobić i uzyskać podzbiór oryginalnej ramki danych w nowym obiekcie dataframe)
Pytanie 2. Jak to zrobić w pętli i utworzyć obiekt Dataframe dla każdego unikalnego zestawu roku i płci (np. Df dla: 2013-Mężczyzna, 2013-Kobieta, 2014-Mężczyzna i 2014-Kobieta
for y in year:
for g in gender:
df = .....
groupby
.Odpowiedzi:
Używając
&
operatora, nie zapomnij otoczyć instrukcji podrzędnych()
:males = df[(df[Gender]=='Male') & (df[Year]==2014)]
Aby przechowywać ramki danych w
dict
pętli for:from collections import defaultdict dic={} for g in ['male', 'female']: dic[g]=defaultdict(dict) for y in [2013, 2014]: dic[g][y]=df[(df[Gender]==g) & (df[Year]==y)] #store the DataFrames to a dict of dict
EDYTOWAĆ:
Demo dla
getDF
:def getDF(dic, gender, year): return dic[gender][year] print genDF(dic, 'male', 2014)
źródło
key
twojegetDF
? pojedynczy parametr czy krotka kluczy? be specific plz;)Gender
iYear
powinny być zarówno ciągi, czyli'Gender'
i'Year'
.Aby uzyskać bardziej ogólne funkcje logiczne, których chciałbyś użyć jako filtru i które zależą od więcej niż jednej kolumny, możesz użyć:
df = df[df[['col_1','col_2']].apply(lambda x: f(*x), axis=1)]
gdzie f jest funkcją, która jest stosowana do każdej pary elementów (x1, x2) z col_1 i col_2 i zwraca True lub False w zależności od dowolnego warunku (x1, x2).
źródło
Zacznij od pandy 0.13 , jest to najbardziej efektywny sposób.
df.query('Gender=="Male" & Year=="2014" ')
źródło
W przypadku gdyby ktoś się zastanawiał, jaki jest szybszy sposób filtrowania (odpowiedź zaakceptowana lub ta z @redreamality):
import pandas as pd import numpy as np length = 100_000 df = pd.DataFrame() df['Year'] = np.random.randint(1950, 2019, size=length) df['Gender'] = np.random.choice(['Male', 'Female'], length) %timeit df.query('Gender=="Male" & Year=="2014" ') %timeit df[(df['Gender']=='Male') & (df['Year']==2014)]
Wyniki dla 100 000 wierszy:
6.67 ms ± 557 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 5.54 ms ± 536 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Wyniki dla 10 000 000 wierszy:
326 ms ± 6.52 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 472 ms ± 25.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Zatem wyniki zależą od rozmiaru i danych. Na moim laptopie
query()
przyspiesza po 500 tys. Rzędów. Co więcej, wyszukiwanie ciągówYear=="2014"
ma niepotrzebny narzut (Year==2014
jest szybsze).źródło
query
składnia jest schludniejsza i zbliżona do SQL, co sprawia, że od tego czasu jest przyjemna dla danych. Smutne na torcie jest to, że jest szybszy z wieloma rzędami :)Możesz stworzyć własną funkcję filtrującą za pomocą
query
inpandas
. Tutaj masz filtrowaniedf
wyników według wszystkichkwargs
parametrów. Nie zapomniałem dodać niektórych walidatorów (kwargs
filtrowania), aby uzyskać własną funkcję filtrującądf
.def filter(df, **kwargs): query_list = [] for key in kwargs.keys(): query_list.append(f'{key}=="{kwargs[key]}"') query = ' & '.join(query_list) return df.query(query)
źródło
Możesz filtrować według wielu kolumn (więcej niż dwóch), używając
np.logical_and
operatora do zamiany&
(lubnp.logical_or
zamiany|
)Oto przykładowa funkcja, która wykonuje swoje zadanie, jeśli podasz wartości docelowe dla wielu pól. Możesz go dostosować do różnych typów filtrowania i nie tylko:
def filter_df(df, filter_values): """Filter df by matching targets for multiple columns. Args: df (pd.DataFrame): dataframe filter_values (None or dict): Dictionary of the form: `{<field>: <target_values_list>}` used to filter columns data. """ import numpy as np if filter_values is None or not filter_values: return df return df[ np.logical_and.reduce([ df[column].isin(target_values) for column, target_values in filter_values.items() ]) ]
Stosowanie:
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [1, 2, 3, 4]}) filter_df(df, { 'a': [1, 2, 3], 'b': [1, 2, 4] })
źródło