Как реализовать логический поиск с несколькими столбцами в пандах
У меня есть pandas df, и я хотел бы сделать что-то вроде этого (в терминах SQL):
SELECT * FROM df WHERE column1 = 'a' OR column2 = 'b' OR column3 = 'c' etc.
Теперь это работает для одной пары столбец/значение:
foo = df.loc[df['column']==value]
Однако я не уверен, как расширить это до нескольких пар столбец/значение.
- Чтобы было понятно, каждый столбец соответствует разному значению.
Ответы
Ответ 1
Вам нужно заключить несколько условий в фигурные скобки из-за приоритета оператора и использовать побитовые и (&
) и или (|
) операторы:
foo = df.ix[(df['column1']==value) | (df['columns2'] == 'b') | (df['column3'] == 'c')]
Если вы используете and
или or
, то pandas, скорее всего, будет стонать, что сравнение неоднозначно. В этом случае неясно, сравниваем ли мы каждое значение в ряду в условии, и что это означает, если только 1 или все, кроме 1, соответствуют условию. Вот почему вы должны использовать побитовые операторы или numpy np.all
или np.any
, чтобы указать критерии соответствия.
Существует также метод запроса: http://pandas.pydata.org/pandas-docs/dev/generated/pandas.DataFrame.query.html
но есть некоторые ограничения, в основном связанные с проблемами, где может быть неоднозначность между именами столбцов и значениями индекса.
Ответ 2
Более сжатый, но не обязательно более быстрый способ заключается в использовании DataFrame.isin()
и DataFrame.any()
In [27]: n = 10
In [28]: df = DataFrame(randint(4, size=(n, 2)), columns=list('ab'))
In [29]: df
Out[29]:
a b
0 0 0
1 1 1
2 1 1
3 2 3
4 2 3
5 0 2
6 1 2
7 3 0
8 1 1
9 2 2
[10 rows x 2 columns]
In [30]: df.isin([1, 2])
Out[30]:
a b
0 False False
1 True True
2 True True
3 True False
4 True False
5 False True
6 True True
7 False False
8 True True
9 True True
[10 rows x 2 columns]
In [31]: df.isin([1, 2]).any(1)
Out[31]:
0 False
1 True
2 True
3 True
4 True
5 True
6 True
7 False
8 True
9 True
dtype: bool
In [32]: df.loc[df.isin([1, 2]).any(1)]
Out[32]:
a b
1 1 1
2 1 1
3 2 3
4 2 3
5 0 2
6 1 2
8 1 1
9 2 2
[8 rows x 2 columns]
Ответ 3
Все соображения, сделанные @EdChum в 2014 году, остаются в силе, но метод pandas.Dataframe.ix
устарел по сравнению с версией 0.0.20 для панд. Непосредственно из документов:
Предупреждение: Начиная с версии 0.20.0, индексатор .ix устарел, в пользу из более строгих индексаторов .iloc и .loc.
В последующих версиях pandas этот метод был заменен новыми индексными методами pandas.Dataframe.loc и pandas.Dataframe.iloc.
Если вы хотите узнать больше, в этом посте вы можете найти сравнения между методами, упомянутыми выше.
В конечном счете, на сегодняшний день (и, похоже, с этой точки зрения нет изменений в будущих версиях панд), ответ на этот вопрос следующий:
foo = df.loc[(df['column1']==value) | (df['columns2'] == 'b') | (df['column3'] == 'c')]
Ответ 4
Самый простой способ сделать это
students = [ ('jack1', 'Apples1' , 341) ,
('Riti1', 'Mangos1' , 311) ,
('Aadi1', 'Grapes1' , 301) ,
('Sonia1', 'Apples1', 321) ,
('Lucy1', 'Mangos1' , 331) ,
('Mike1', 'Apples1' , 351),
('Mik', 'Apples1' , np.nan)
]
#Create a DataFrame object
df = pd.DataFrame(students, columns = ['Name1' , 'Product1', 'Sale1'])
print(df)
Name1 Product1 Sale1
0 jack1 Apples1 341
1 Riti1 Mangos1 311
2 Aadi1 Grapes1 301
3 Sonia1 Apples1 321
4 Lucy1 Mangos1 331
5 Mike1 Apples1 351
6 Mik Apples1 NaN
# Select rows in above DataFrame for which ‘Product column contains the value ‘Apples,
subset = df[df['Product1'] == 'Apples1']
print(subset)
Name1 Product1 Sale1
0 jack1 Apples1 341
3 Sonia1 Apples1 321
5 Mike1 Apples1 351
6 Mik Apples1 NA
# Select rows in above DataFrame for which ‘Product column contains the value ‘Apples, AND notnull value in Sale
subsetx= df[(df['Product1'] == "Apples1") & (df['Sale1'].notnull())]
print(subsetx)
Name1 Product1 Sale1
0 jack1 Apples1 341
3 Sonia1 Apples1 321
5 Mike1 Apples1 351
# Select rows in above DataFrame for which ‘Product column contains the value ‘Apples, AND Sale = 351
subsetx= df[(df['Product1'] == "Apples1") & (df['Sale1'] == 351)]
print(subsetx)
Name1 Product1 Sale1
5 Mike1 Apples1 351
# Another example
subsetData = df[df['Product1'].isin(['Mangos1', 'Grapes1']) ]
print(subsetData)
Name1 Product1 Sale1
1 Riti1 Mangos1 311
2 Aadi1 Grapes1 301
4 Lucy1 Mangos1 331
Вот оригинальная ссылка, я нашел это. Я немного редактирую https://thispointer.com/python-pandas-select-rows-in-dataframe-by-conditions-on-multiple-columns/