8

Как фильтровать DataFrame Pandas с помощью 'in' и 'not in', как в SQL

11

Как мне добиться эквивалентов SQL-запросов IN и NOT IN в Pandas?

У меня есть список с необходимыми значениями. Вот сценарий:

df = pd.DataFrame({'country': ['US', 'UK', 'Germany', 'China']})
countries_to_keep = ['UK', 'China']

псевдокод:

df[df['country'] not in countries_to_keep]

Мой текущий способ выполнения этого выглядит следующим образом:

df = pd.DataFrame({'country': ['US', 'UK', 'Germany', 'China']})
df2 = pd.DataFrame({'country': ['UK', 'China'], 'matched': True})

IN

df.merge(df2, how='inner', on='country')

NOT IN

not_in = df.merge(df2, how='left', on='country') not_in = not_in[pd.isnull(not_in['matched'])]

Но это кажется ужасным обходным решением. Можете ли вы предложить улучшение?

5 ответ(ов)

0

Вам нужно фильтровать строки в DataFrame, используя условие, при котором значение в столбце 'countries' отсутствует в перечисленных странах. Ваш код уже почти правильный, однако можно немного улучшить его для более понятного выполнения. Вы можете использовать метод .isin() для этого, чтобы сделать код более лаконичным. Вот как это можно реализовать:

not_in = df[~df['countries'].isin(countries)]

Здесь ~ - это оператор логического отрицания, который будет исключать строки, где значения в столбце 'countries' присутствуют в списке countries. Таким образом, вы получите DataFrame not_in, который будет содержать только те строки, где значение 'countries' не входит в указанный список.

0

Для решения задачи по фильтрации данных в pandas:

Для фильтрации с использованием IN:

df[df['A'].isin([3, 6])]

Для фильтрации с использованием NOT IN можно использовать несколько подходов:

  1. Использовать отрицание с помощью минуса:

    df[-df["A"].isin([3, 6])]
    
  2. Использовать оператор ~ (логическое отрицание):

    df[~df["A"].isin([3, 6])]
    
  3. Использовать сравнение с False:

    df[df["A"].isin([3, 6]) == False]
    
  4. Использовать функцию np.logical_not из библиотеки NumPy:

    df[np.logical_not(df["A"].isin([3, 6]))]
    

Эти методы позволят вам эффективно отфильтровать данные в вашем DataFrame в зависимости от необходимости включения или исключения определенных значений.

0

На вопрос о том, почему никто не обсуждает производительность различных методов фильтрации данных, следует отметить, что эта тема действительно часто поднимается на форумах, включая StackOverflow. Я провел собственные тесты производительности на большом наборе данных, и результаты получились довольно интересными и познавательными.

Я создал DataFrame с 10 миллионами записей, где один столбец содержит животных, а другой — случайно сгенерированные числа. Ниже приведены результаты тестов производительности для различных методов фильтрации по одному столбцу:

  1. Метод .isin():

    %%timeit
    conditions = ['cat', 'dog']
    df[df.animals.isin(conditions)]
    
    367 ms ± 2.34 ms на цикл (среднее ± стандартное отклонение из 7 запусков)
    
  2. Метод .query():

    %%timeit
    conditions = ['cat', 'dog']
    df.query('animals in @conditions')
    
    395 ms ± 3.9 ms на цикл
    
  3. Метод .loc[]:

    %%timeit
    df.loc[(df.animals=='cat')|(df.animals=='dog')]
    
    987 ms ± 5.17 ms на цикл
    
  4. Метод с использованием apply():

    %%timeit
    df[df.apply(lambda x: x['animals'] in ['cat', 'dog'], axis=1)]
    
    41.9 s ± 490 ms на цикл
    
  5. Создание индекса и фильтрация:

    %%timeit
    new_df = df.set_index('animals')
    new_df.loc[['cat', 'dog'], :]
    
    3.64 s ± 62.5 ms на цикл
    
  6. Индекс и метод .isin():

    %%timeit
    new_df = df.set_index('animals')
    new_df[new_df.index.isin(['cat', 'dog'])]
    
    469 ms ± 8.98 ms на цикл
    
  7. Слияние через merge():

    %%timeit
    s = pd.Series(['cat', 'dog'], name='animals')
    df.merge(s, on='animals', how='inner')
    
    796 ms ± 30.9 ms на цикл
    

Таким образом, метод isin оказался самым быстрым, тогда как использование apply() продемонстрировало наименьшую производительность, что не вызывает удивления. Эти результаты подчеркивают важность выбора правильного метода в зависимости от задач и объема данных, что может существенно повлиять на производительность вашей работы с DataFrame.

0

Чтобы отфильтровать строки в DataFrame dfbc, у которых значение столбца BUSINESS_ID также присутствует в столбце BUSINESS_ID DataFrame dfProfilesBusIds, вы можете использовать метод isin() в сочетании с отрицательной индексацией. Ваш код выглядит верно:

dfbc = dfbc[~dfbc['BUSINESS_ID'].isin(dfProfilesBusIds['BUSINESS_ID'])]

Таким образом, ~ (логическое "НЕ") используется для исключения всех строк из dfbc, где BUSINESS_ID также содержится в dfProfilesBusIds. Это позволит вам оставить только те строки, которые не имеют соответствующих идентификаторов в другом DataFrame. Если у вас возникнут дополнительные вопросы или понадобится помощь с другим кодом, не стесняйтесь спрашивать!

0

Для того чтобы отфильтровать строки в DataFrame, которые содержат только определённые страны, вы можете использовать метод isin(). В представленном вами коде, например, вы можете извлечь строки для стран, входящих в список countries:

import pandas as pd

df = pd.DataFrame({'countries': ['US', 'UK', 'Germany', 'China']})
countries = ['UK', 'China']

# Фильтр для стран, входящих в список
result_in = df[df.countries.isin(countries)]
print(result_in)

Это вернёт строки с 'UK' и 'China'.

Чтобы отфильтровать все строки, которые содержат страны, не указанные в списке countries, вы можете использовать следующий код. Он создает новый список стран, не входящих в countries, а затем применяет фильтр:

import numpy as np

# Фильтр для стран, которые не входят в список
result_not_in = df[df.countries.isin([x for x in np.unique(df.countries) if x not in countries])]
print(result_not_in)

Этот код вернёт строки с 'US' и 'Germany'.

Таким образом, вы можете легко использовать isin() для фильтрации значений в DataFrame как для включения, так и для исключения определенных значений.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь