Удалить столбцы, содержащие определенные слова (не в виде подстроки)

У меня есть следующий фрейм данных, df:

id     text
1      'a little table'
2      'blue lights'
3      'food and drink'
4      'build an atom'
5      'fast animals' 

и список стоп-слов, то есть:

sw = ['a', 'an', 'and']

Я хочу удалить строки, содержащие хотя бы одно стоп-слово (как сами слова, а не как подстроки). То есть результат, который я хотел бы, это:

id     text
2      'blue lights'
5      'fast animals' 

Я пытался с:

df[~df['text'].str.contains('|'.join(sw), regex=True, na=False)]

но, похоже, это не работает, так как это работает с подстроками таким образом, а a является подстрокой всех текстов (кроме «синих огней»). Как мне изменить строку кода?

Ваш код должен работать!

gtomer 12.10.2022 17:40
1
1
62
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

li = ['a', 'an', 'and']
for i in li:
    for k in df.index:
        if i in df.text[k].split():
            df.drop(k,inplace=True)
            

Если вы хотите использовать str.contains, вы можете попробовать следующее:

import pandas as pd

data = {'id': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}, 
        'text': {0: "'a little table'", 1: "'blue lights'", 
                 2: "'food and drink'", 3: "'build an atom'", 
                 4: "'fast animals'"}}
df = pd.DataFrame(data)

sw = ['a', 'an', 'and']
res = df[~df['text'].str.contains(fr'\b(?:{"|".join(sw)})\b', 
                                  regex=True, na=False)]

print(res)

   id            text
1   2   'blue lights'
4   5  'fast animals'

В шаблоне регулярного выражения \b утверждает позицию на границе слова, а ?: в начале шаблона между (...) создает non-capturing group. Строго говоря, вы могли бы обойтись без ?:, но он подавляет Userwarning: «Этот шаблон ... имеет группы совпадений и т. д.». `

Ответ принят как подходящий

вот один из способов сделать это

# '|'.join(sw)  : creates a string with a |, to form an OR condition
# \\b : adds the word boundary to the capture group
# create a pattern surrounded by the word boundary and then 
# filtered out what is found using loc
df.loc[~df['text'].str.contains('\\b('+ '|'.join(sw) + ')\\b' )]


ИЛИ

df[df['text'].str.extract('\\b('+ '|'.join(sw) + ')\\b' )[0].isna()]
    id  text
1   2   'blue lights'
4   5   'fast animals'

Вы также можете использовать собственный метод apply(),

def string_present(List,string):
    return any(ele+' ' in string for ele in List)

df['status'] = df['text'].apply(lambda row: string_present(sw,row))
df[df['status']==False].drop(columns=['status'],axis=1)

Выход,

   id          text
1   2   blue lights
4   5  fast animals

Другое возможное решение, которое работает следующим образом:

  1. Разделите каждую строку пробелом, создав список слов

  2. Проверьте, не пересекается ли каждый из этих списков слов с sw.

  3. Используйте результат для булевой индексации.

df[df['text'].str.split(' ').map(lambda x: set(x).isdisjoint(sw))]

Вывод:

   id          text
1   2   blue lights
4   5  fast animals
sw = ['a', 'an', 'and']
df1.loc[~df1.text.str.split(' ').map(lambda x:pd.Series(x).isin(sw).any())]

Пожалуйста, не публикуйте только код в качестве ответа, но также объясните, что делает ваш код и как он решает проблему вопроса. Ответы с объяснением, как правило, более полезны и качественны, и с большей вероятностью привлекут положительные голоса.

Mark Rotteveel 28.10.2022 14:40

Другие вопросы по теме