У меня есть список фраз, и мне нужно определить, содержит ли каждая строка набора данных все слова из любой фразы в моем списке. Возьмем мой пример проблемы ниже.
У меня есть набор данных, в котором столбец «Поиск» содержит некоторые поисковые запросы в браузере. У меня также есть список «фразы», содержащий фразы, которые я пытаюсь найти в столбце «Поиск».
import pandas as pd
import numpy as np
text = [('how to screenshot on mac', 0),
('how to take screenshot?', 0),
('how to take screenshot on windows', 0),
('when is christmas', 0),
('how many days until christmas', 0),
('how many weeks until christmas', 0),
('how much is the new google pixel 8', 0),
('which google pixel versions are available', 0),
('how do I do google search on my pixel phone 7a', 0)]
labels = ['Search','Random_Column']
df = pd.DataFrame.from_records(text, columns=labels)
phrases = ['mac screenshot', 'days until christmas', 'google pixel 7a']
Меня не волнует порядок слов внутри «фраз», и до, внутри и после фразы могут быть другие слова, но мне нужно убедиться, что только те строки df, которые содержат все слова в любом из фразы обозначены. Таким образом, ожидаемый результат будет таким:
Search Random_Column Match
0 how to screenshot on mac 0 True
1 how to take screenshot? 0 False
2 how to take screenshot on windows 0 False
3 when is christmas 0 False
4 how many days until christmas 0 True
5 how many weeks until christmas 0 False
6 how much is the new google pixel 8 0 False
7 which google pixel versions are available 0 False
8 how do I do google search on my pixel phone 7a 0 True
Я нашел много решений для случаев, когда список «фраз» состоит из отдельных слов (например, здесь , здесь и здесь), но я изо всех сил пытаюсь найти решение, в котором я необходимо сопоставить полные фразы.
Я также пытался реализовать это решение, но не смог заставить его работать с набором данных.






Вам придется перебирать всю фразу, пока не найдете совпадение. Эффективным вариантом было бы использование наборов (set.issubset ) в сочетании с Any:
# convert the phrases to set
sets = [set(s.split()) for s in phrases]
# [{'screenshot', 'mac'}, {'until', 'christmas', 'days'},
# {'google', 'pixel', '7a'}]
# for each string, check if one of the sets is a subset
# if a match is found, return True immediately
df['Match'] = [any(S.issubset(lst) for S in sets)
for lst in map(str.split, df['Search'])]
Выход:
Search Random_Column Match
0 how to screenshot on mac 0 True
1 how to take screenshot? 0 False
2 how to take screenshot on windows 0 False
3 when is christmas 0 False
4 how many days until christmas 0 True
5 how many weeks until christmas 0 False
6 how much is the new google pixel 8 0 False
7 which google pixel versions are available 0 False
8 how do I do google search on my pixel phone 7a 0 True
@mozway Это отлично сработало с моим реальным набором данных, спасибо !!
Вы можете использовать set() и определить функцию _match:
def _match(x, sets):
s = set(x.lower().split())
for ps in sets:
if ps.issubset(s):
return True
return False
sets = [set(phrase.lower().split()) for phrase in phrases]
Затем apply() метод _match в виде лямбды:
df['Match'] = df['Search'].apply(lambda x: _match(x, sets))
import pandas as pd
import numpy as np
def _match(x, sets):
s = set(x.lower().split())
for ps in sets:
if ps.issubset(s):
return True
return False
text = [('how to screenshot on mac', 0),
('how to take screenshot?', 0),
('how to take screenshot on windows', 0),
('when is christmas', 0),
('how many days until christmas', 0),
('how many weeks until christmas', 0),
('how much is the new google pixel 8', 0),
('which google pixel versions are available', 0),
('how do I do google search on my pixel phone 7a', 0)]
labels = ['Search', 'Random_Column']
df = pd.DataFrame.from_records(text, columns=labels)
phrases = ['mac screenshot', 'days until christmas', 'google pixel 7a']
sets = [set(phrase.lower().split()) for phrase in phrases]
df['Match'] = df['Search'].apply(lambda x: _match(x, sets))
print(df)
Search Random_Column Match
0 how to screenshot on mac 0 True
1 how to take screenshot? 0 False
2 how to take screenshot on windows 0 False
3 when is christmas 0 False
4 how many days until christmas 0 True
5 how many weeks until christmas 0 False
6 how much is the new google pixel 8 0 False
7 which google pixel versions are available 0 False
8 how do I do google search on my pixel phone 7a 0 True
Если вы хотите внести какие-либо изменения, вы можете просто изменить _match(). Его легко поддерживать.
Недостаток использования функции (здесь) заключается в том, что она пересчитывает разделение/набор для каждой строки, что неэффективно. Лучшим подходом было бы использовать фабрику функций или класс.
Нет, здесь вы пересчитываете set(phrase.lower().split()) для каждой строки. Итак, с точки зрения этой части вычислений, сложность равна O(N*M) времени по сравнению с O(M), если вы предварительно вычисляете наборы. В действительности вычисление происходит иначе: O(N*M) (N — количество строк, а M — количество фраз).
Я протестировал оба подхода для ~ 10 тысяч строк и 300 фраз, предварительные вычисления (как и в моем подходе) выполняются за 3,5 секунды, пересчет наборов в функции выполняется за 6 секунд.
@mozway Моя вина! Обновлено. Спасибо. Вы абсолютно правы.
Это коротко и просто.