Проверьте, содержит ли строка все слова во фразе из списка в Python

У меня есть список фраз, и мне нужно определить, содержит ли каждая строка набора данных все слова из любой фразы в моем списке. Возьмем мой пример проблемы ниже.

У меня есть набор данных, в котором столбец «Поиск» содержит некоторые поисковые запросы в браузере. У меня также есть список «фразы», ​​содержащий фразы, которые я пытаюсь найти в столбце «Поиск».

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

Я нашел много решений для случаев, когда список «фраз» состоит из отдельных слов (например, здесь , здесь и здесь), но я изо всех сил пытаюсь найти решение, в котором я необходимо сопоставить полные фразы.

Я также пытался реализовать это решение, но не смог заставить его работать с набором данных.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Вам придется перебирать всю фразу, пока не найдете совпадение. Эффективным вариантом было бы использование наборов (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

Это коротко и просто.

user24714692 05.06.2024 19:25

@mozway Это отлично сработало с моим реальным набором данных, спасибо !!

Maria 05.06.2024 20:22

Вы можете использовать set() и определить функцию _match:

def _match(x, sets):
    s = set(x.lower().split())
    for ps in sets:
        if ps.issubset(s):
            return True
    return False

Для эффективности предварительно вычислите наборы (см. комментарии @mozway ниже).

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(). Его легко поддерживать.

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

mozway 05.06.2024 19:01

Нет, здесь вы пересчитываете set(phrase.lower().split()) для каждой строки. Итак, с точки зрения этой части вычислений, сложность равна O(N*M) времени по сравнению с O(M), если вы предварительно вычисляете наборы. В действительности вычисление происходит иначе: O(N*M) (N — количество строк, а M — количество фраз).

mozway 05.06.2024 19:16

Я протестировал оба подхода для ~ 10 тысяч строк и 300 фраз, предварительные вычисления (как и в моем подходе) выполняются за 3,5 секунды, пересчет наборов в функции выполняется за 6 секунд.

mozway 05.06.2024 19:19

@mozway Моя вина! Обновлено. Спасибо. Вы абсолютно правы.

user24714692 05.06.2024 19:24

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