Поиск слов в текстовом документе и удаление соответствующих строк в фрейме данных - python
У меня есть таблица с 87 миллионов строк и 5 столбцов. У меня тоже есть отдельный файл, около 3500 слов. Я хочу проверить слова в файле.txt и проверить это слово в 4 столбцах таблицы для каждой строки. Если это слово присутствует в любом из столбцов, я хочу удалить эти строки. Это помогло бы мне значительно уменьшить количество строк здесь. Ниже приведен код, который я использую,
bad_words = pd.read_csv('badwords.txt')
bad_words.dtypes
words object
dtype: object
bad_words
words
0 word1
1 word3
2 word5
3 word13
4 word16
data
s.no column1 column2 column3 column4
1 aaaword1b aaaword2b aaaword3b aaaword4b
2 aaaword5b aaaword6b aaaword7b aaaword8b
3 aaaword9b aaaword10b aaaword11b aaaword12b
4 aaaword13b aaaword14b aaaword15b aaaword16b
5 aaaword17b aaaword18b aaaword19b aaaword20b
Я хочу удалить строки, содержащие слова, из документа с плохим словом. Выход этого должен быть,
data
s.no column1 column2 column3 column4
3 aaaword9b aaaword10b aaaword11b aaaword12b
5 aaaword17b aaaword18b aaaword19b aaaword20b
Я пытаюсь сделать что-то вроде,
data[(data['column1'].str.contains("word1|word3|word5|word13|word16")==False)|
(data['column2'].str.contains("word1|word3|word5|word13|word16")==False)|
(data['column3'].str.contains("word1|word3|word5|word13|word16")==False)]
Но я не уверен, сможем ли мы сделать это за все 3500 слов. Также не уверен, что это эффективный способ сделать для 87 миллионов строк.
Обновлен вопрос с шаблонами строк, а не с прямыми словами. Извините за плохое требование ранее.
Кто-нибудь может предложить мне лучший способ сделать это?
Спасибо
2 ответа
Ты можешь использовать apply
метод проверки по строке и создания вектора, указывающего, содержит ли строка что-либо в bad_words
с использованием isin
метод, а затем установить исходный фрейм данных на основе возвращенного логического вектора:
data[~data.apply(lambda row: row.isin(bad_words.words).any(), axis = 1)]
#s.no column1 column2 column3 column4
#2 3 word9 word10 word11 word12
#4 5 word17 word18 word19 word20
Для обновленного вопроса, вот вариант, который может работать в зависимости от ваших фактических данных:
data[~data.apply(lambda row: bad_words.words.apply(lambda w: row.str.contains(w + "(?=\D)").any()).any(), axis = 1)]
# sno column1 column2 column3 column4
#2 3 aaaword9b aaaword10b aaaword11b aaaword12b
#4 5 aaaword17b aaaword18b aaaword19b aaaword20b
Я изменил ваш пример, потому что word1
технически в word11
а также word12
и я не думаю, что ты это имел ввиду.
Настроить
from StringIO import StringIO
import pandas as pd
text_bad_words = """ words
0 _word1_
1 _word3_
2 _word5_
3 _word13_
4 _word16_"""
text_data = """s.no column1 column2 column3 column4
1 aaa_word1_b aaa_word2_b aaa_word3_b aaa_word4_b
2 aaa_word5_b aaa_word6_b aaa_word7_b aaa_word8_b
3 aaa_word9_b aaa_word10_b aaa_word11_b aaa_word12_b
4 aaa_word13_b aaa_word14_b aaa_word15_b aaa_word16_b
5 aaa_word17_b aaa_word18_b aaa_word19_b aaa_word20_b"""
bad_words = pd.read_csv(
StringIO(text_bad_words), squeeze=True, index_col=0, delim_whitespace=True)
data = pd.read_csv(
StringIO(text_data), squeeze=True, index_col=0, delim_whitespace=True)
Решение
Я буду использовать regex
а также contains
regex = r'|'.join(bad_words)
regex
'_word1_|_word3_|_word5_|_word13_|_word16_'
Создать булеву маску
mask = data.stack().str.contains(regex).unstack().any(1)
mask
s.no
1 True
2 True
3 False
4 True
5 False
dtype: bool
data.loc[~mask]