Как реализовать «в» и «не в» для панды DataFrame?
Pandas предлагает два метода: Series.isin
и DataFrame.isin
для Series и DataFrames, соответственно.
Фильтр DataFrame на основе одного столбца (также относится к серии)
Наиболее распространенный сценарий - применение isin
условия к определенному столбцу для фильтрации строк в DataFrame.
df = pd.DataFrame({'countries': ['US', 'UK', 'Germany', np.nan, 'China']})
df
countries
0 US
1 UK
2 Germany
3 China
c1 = ['UK', 'China'] # list
c2 = {'Germany'} # set
c3 = pd.Series(['China', 'US']) # Series
c4 = np.array(['US', 'UK']) # array
Series.isin
принимает различные типы в качестве входных данных. Ниже приведены все действительные способы получить то, что вы хотите:
df['countries'].isin(c1)
0 False
1 True
2 False
3 False
4 True
Name: countries, dtype: bool
# `in` operation
df[df['countries'].isin(c1)]
countries
1 UK
4 China
# `not in` operation
df[~df['countries'].isin(c1)]
countries
0 US
2 Germany
3 NaN
# Filter with `set` (tuples work too)
df[df['countries'].isin(c2)]
countries
2 Germany
# Filter with another Series
df[df['countries'].isin(c3)]
countries
0 US
4 China
# Filter with array
df[df['countries'].isin(c4)]
countries
0 US
1 UK
Фильтр по МНОГИМ столбцам
Иногда вы захотите применить проверку членства «in» с некоторыми поисковыми терминами в нескольких столбцах,
df2 = pd.DataFrame({
'A': ['x', 'y', 'z', 'q'], 'B': ['w', 'a', np.nan, 'x'], 'C': np.arange(4)})
df2
A B C
0 x w 0
1 y a 1
2 z NaN 2
3 q x 3
c1 = ['x', 'w', 'p']
Чтобы применить isin
условие к обоим столбцам «A» и «B», используйте DataFrame.isin
:
df2[['A', 'B']].isin(c1)
A B
0 True True
1 False False
2 False False
3 False True
Исходя из этого, чтобы сохранить строки, где находится хотя бы один столбецTrue
, мы можем использовать any
вдоль первой оси:
df2[['A', 'B']].isin(c1).any(axis=1)
0 True
1 False
2 False
3 True
dtype: bool
df2[df2[['A', 'B']].isin(c1).any(axis=1)]
A B C
0 x w 0
3 q x 3
Обратите внимание, что если вы хотите искать каждый столбец, вы просто пропустите шаг выбора столбца и выполните
df2.isin(c1).any(axis=1)
Аналогично, чтобы сохранить строки, в которых находятся ВСЕ столбцыTrue
, используйте all
тот же способ, что и раньше.
df2[df2[['A', 'B']].isin(c1).all(axis=1)]
A B C
0 x w 0
Примечательным Упоминания: numpy.isin
, query
, списочные (строка данных)
В дополнение к методам , описанным выше, вы можете также использовать Numpy эквивалент: numpy.isin
.
# `in` operation
df[np.isin(df['countries'], c1)]
countries
1 UK
4 China
# `not in` operation
df[np.isin(df['countries'], c1, invert=True)]
countries
0 US
2 Germany
3 NaN
Почему стоит задуматься? Функции NumPy обычно немного быстрее, чем их эквиваленты в pandas, из-за меньших накладных расходов. Так как это поэлементная операция, которая не зависит от выравнивания индекса, очень мало ситуаций, когда этот метод не является подходящей заменой для pandas ' isin
.
Процедуры Pandas обычно итеративны при работе со строками, потому что строковые операции трудно векторизовать. Существует много свидетельств того, что составление списков здесь будет быстрее. , Мы прибегаем к in
проверке сейчас.
c1_set = set(c1) # Using `in` with `sets` is a constant time operation...
# This doesn't matter for pandas because the implementation differs.
# `in` operation
df[[x in c1_set for x in df['countries']]]
countries
1 UK
4 China
# `not in` operation
df[[x not in c1_set for x in df['countries']]]
countries
0 US
2 Germany
3 NaN
Однако указывать его намного сложнее, поэтому не используйте его, если не знаете, что делаете.
Наконец, есть также то, DataFrame.query
что было рассмотрено в этом ответе . Numxpr FTW!