выбор по нескольким столбцам с панд python?
у меня есть фрейм данных df
в панд, которые были построены с использованием pandas.read_table
из файла csv. Dataframe имеет несколько столбцов и индексируется одним из столбцов (который уникален, поскольку каждая строка имеет уникальное значение для этого столбца, используемого для индексирования.)
как я могу выбрать строки моего фрейма данных на основе "сложного" фильтра, применяемого к нескольким столбцам? Я могу легко выбрать фрагмент фрейма данных, где столбец colA
больше чем 10 для пример:
df_greater_than10 = df[df["colA"] > 10]
но что, если бы я хотел фильтр, как: Выберите кусок df
здесь любой из столбцов больше 10?
или где значение colA
больше 10, но значение для colB
меньше 5?
как они реализованы в панд? Спасибо.
3 ответов
Я призываю Вас поставить эти вопросы на рассылки, но в любом случае, это все еще очень низкоуровневое дело, работающее с базовыми массивами NumPy. Например, чтобы выбрать строки, где значение в любом столбце превышает, скажем, 1.5 в этом примере:
In [11]: df
Out[11]:
A B C D
2000-01-03 -0.59885 -0.18141 -0.68828 -0.77572
2000-01-04 0.83935 0.15993 0.95911 -1.12959
2000-01-05 2.80215 -0.10858 -1.62114 -0.20170
2000-01-06 0.71670 -0.26707 1.36029 1.74254
2000-01-07 -0.45749 0.22750 0.46291 -0.58431
2000-01-10 -0.78702 0.44006 -0.36881 -0.13884
2000-01-11 0.79577 -0.09198 0.14119 0.02668
2000-01-12 -0.32297 0.62332 1.93595 0.78024
2000-01-13 1.74683 -1.57738 -0.02134 0.11596
2000-01-14 -0.55613 0.92145 -0.22832 1.56631
2000-01-17 -0.55233 -0.28859 -1.18190 -0.80723
2000-01-18 0.73274 0.24387 0.88146 -0.94490
2000-01-19 0.56644 -0.49321 1.17584 -0.17585
2000-01-20 1.56441 0.62331 -0.26904 0.11952
2000-01-21 0.61834 0.17463 -1.62439 0.99103
2000-01-24 0.86378 -0.68111 -0.15788 -0.16670
2000-01-25 -1.12230 -0.16128 1.20401 1.08945
2000-01-26 -0.63115 0.76077 -0.92795 -2.17118
2000-01-27 1.37620 -1.10618 -0.37411 0.73780
2000-01-28 -1.40276 1.98372 1.47096 -1.38043
2000-01-31 0.54769 0.44100 -0.52775 0.84497
2000-02-01 0.12443 0.32880 -0.71361 1.31778
2000-02-02 -0.28986 -0.63931 0.88333 -2.58943
2000-02-03 0.54408 1.17928 -0.26795 -0.51681
2000-02-04 -0.07068 -1.29168 -0.59877 -1.45639
2000-02-07 -0.65483 -0.29584 -0.02722 0.31270
2000-02-08 -0.18529 -0.18701 -0.59132 -1.15239
2000-02-09 -2.28496 0.36352 1.11596 0.02293
2000-02-10 0.51054 0.97249 1.74501 0.20525
2000-02-11 0.10100 0.27722 0.65843 1.73591
In [12]: df[(df.values > 1.5).any(1)]
Out[12]:
A B C D
2000-01-05 2.8021 -0.1086 -1.62114 -0.2017
2000-01-06 0.7167 -0.2671 1.36029 1.7425
2000-01-12 -0.3230 0.6233 1.93595 0.7802
2000-01-13 1.7468 -1.5774 -0.02134 0.1160
2000-01-14 -0.5561 0.9215 -0.22832 1.5663
2000-01-20 1.5644 0.6233 -0.26904 0.1195
2000-01-28 -1.4028 1.9837 1.47096 -1.3804
2000-02-10 0.5105 0.9725 1.74501 0.2052
2000-02-11 0.1010 0.2772 0.65843 1.7359
несколько условий должны быть объединены с помощью &
или |
(и скобки!):
In [13]: df[(df['A'] > 1) | (df['B'] < -1)]
Out[13]:
A B C D
2000-01-05 2.80215 -0.1086 -1.62114 -0.2017
2000-01-13 1.74683 -1.5774 -0.02134 0.1160
2000-01-20 1.56441 0.6233 -0.26904 0.1195
2000-01-27 1.37620 -1.1062 -0.37411 0.7378
2000-02-04 -0.07068 -1.2917 -0.59877 -1.4564
мне было бы очень интересно иметь какой-то API запросов для такого рода все проще
есть, по крайней мере, несколько подходов к сокращению синтаксиса для этого в Pandas, пока он не получит полный API запросов по дороге (возможно, я попытаюсь присоединиться к проекту github и сделать это время позволяет, и если никто еще не начал).
один метод для сокращения синтаксиса немного приведен ниже:
inds = df.apply(lambda x: x["A"]>10 and x["B"]<5, axis=1)
print df[inds].to_string()
чтобы полностью решить эту проблему, нужно было бы построить что-то вроде SQL select и Where предложения в панд. Это не тривиально, но один удар что я думаю, что может это использовать в Python operator
встроенный модуль. Это позволяет рассматривать вещи как больше-чем как функции вместо символов. Таким образом, вы можете сделать следующее:
def pandas_select(dataframe, select_dict):
inds = dataframe.apply(lambda x: reduce(lambda v1,v2: v1 and v2,
[elem[0](x[key], elem[1])
for key,elem in select_dict.iteritems()]), axis=1)
return dataframe[inds]
тогда тестовый пример, подобный вашему, должен был бы сделать следующее:
import operator
select_dict = {
"A":(operator.gt,10),
"B":(operator.lt,5)
}
print pandas_select(df, select_dict).to_string()
вы можете сократить синтаксис еще больше, либо построив больше аргументов в pandas_select
обрабатывать различные общие логические операторы автоматически, или путем импортировать их в пространство имен с более короткими именами.
отметим, что pandas_select
функция выше работает только с логическими-и цепи ограничения. Вам придется изменить его, чтобы получить другое логическое поведение. Или использовать not
и законы DeMorgan по.
функция запроса была добавлена к панд, так как этот вопрос был задан и ответил. Пример приведен ниже.
учитывая этот образец фрейма данных:
periods = 8
dates = pd.date_range('20170101', periods=periods)
rand_df = pd.DataFrame(np.random.randn(periods,4), index=dates,
columns=list('ABCD'))
синтаксис запроса следующим образом позволит вам использовать несколько фильтров, таких как предложение" WHERE " в инструкции select.
rand_df.query("A < 0 or B < 0")
посмотреть панды документация для получения дополнительной информации.