Чтобы отфильтровать фрейм данных (df) по одному столбцу, если мы рассмотрим данные с мужчинами и женщинами, мы могли бы:
males = df[df[Gender]=='Male']
Вопрос 1. Но что, если данные охватывают несколько лет, и я хотел бы видеть только мужчин за 2014 год?
На других языках я мог бы сделать что-нибудь вроде:
if A = "Male" and if B = "2014" then
(за исключением того, что я хочу сделать это и получить подмножество исходного фрейма данных в новом объекте фрейма данных)
Вопрос 2. Как сделать это в цикле и создать объект фрейма данных для каждого уникального набора года и пола (т.е. df для: 2013-Мужской, 2013-Женский, 2014-Мужской и 2014-Женский
for y in year:
for g in gender:
df = .....
groupby
.Ответы:
Используя
&
оператор, не забудьте заключить подвыражения в()
:males = df[(df[Gender]=='Male') & (df[Year]==2014)]
Чтобы сохранить фреймы данных в
dict
цикле 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
РЕДАКТИРОВАТЬ:
Демо для вашего
getDF
:def getDF(dic, gender, year): return dic[gender][year] print genDF(dic, 'male', 2014)
источник
key
как в вашейgetDF
? один параметр или набор ключей? будьте конкретны плз;)Gender
иYear
оба должны быть строками, т.е.'Gender'
и'Year'
.Для более общих логических функций, которые вы хотели бы использовать в качестве фильтра и которые зависят от более чем одного столбца, вы можете использовать:
df = df[df[['col_1','col_2']].apply(lambda x: f(*x), axis=1)]
где f - это функция, которая применяется к каждой паре элементов (x1, x2) из col_1 и col_2 и возвращает True или False в зависимости от любого условия, которое вы хотите (x1, x2).
источник
Начните с панды 0.13 , это наиболее эффективный способ.
df.query('Gender=="Male" & Year=="2014" ')
источник
Если кому-то интересно, какой способ фильтрации более быстрый (принятый ответ или ответ от @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)]
Результаты для 100 000 строк:
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)
Результаты для 10 000 000 строк:
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)
Так что результаты зависят от размера и данных. На моем ноутбуке
query()
становится быстрее после 500 тыс. Строк. Кроме того, поиск по строкеYear=="2014"
имеет ненужные накладные расходы (Year==2014
быстрее).источник
query
синтаксис более аккуратный и близок к SQL, что с тех пор делает его удобным для данных. Самое приятное в том, что он быстрее с множеством строк :)Вы можете создать свою собственную функцию фильтра, используя
query
inpandas
. Здесь есть фильтрацияdf
результатов по всемkwargs
параметрам. Не забудьте добавить несколько валидаторов (kwargs
фильтрацию), чтобы получить функцию фильтрации для себя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)
источник
Вы можете фильтровать по нескольким столбцам (более двух), используя
np.logical_and
оператор для замены&
(илиnp.logical_or
для замены|
)Вот пример функции, которая выполняет свою работу, если вы указываете целевые значения для нескольких полей. Вы можете адаптировать его для разных типов фильтрации и еще много чего:
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() ]) ]
Применение:
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [1, 2, 3, 4]}) filter_df(df, { 'a': [1, 2, 3], 'b': [1, 2, 4] })
источник