Проверьте, совпадает ли подстрока столбца A с подстрокой в ​​столбце B в Pandas - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть следующий фрейм данных с текстом новостей (столбец Text) и запросом (столбец Query), который я запускаю, чтобы извлечь этот c текст новости из API. Не все новостные тексты имеют отношение к запросу, поэтому я пытаюсь создать новый столбец, который возвращает True, если последняя часть строки запроса находится внутри столбца Text. Я знаю, как проверить, находится ли вся строка запроса в тексте, но, как вы видите, часто официальное название компании, например, Nike Ltd., не соответствует тому, как сообщается в тексте новостей (они могут использовать более неформальные сокращения).

Это нечеткое совпадение, и я не совсем понял, как его решить.

news = {'Text':['Nike invests in shoes', 'Adidas invests in t-shirts', 'dog drank water before eating the meal'], 'Source':['NYT', 'WP', 'Guardian'], 'Query' :['Nike Ltd.', "LV", 'dog central']}
news_df = pd.DataFrame(news)

Желаемый результат:

desired = {'Text':['Nike invests in shoes', 'Adidas invests in t-shirts', 'dog drank water before eating the meal'], 'Source':['NYT', 'WP', 'Guardian'], 'Query' :['Nike Ltd.', "LV", 'dog central'], 'Outcome':[True, False, True]}
desired _df = pd.DataFrame(desired )

есть предложения?

Ответы [ 2 ]

0 голосов
/ 28 апреля 2020

Вы написали часть строки запроса находится в столбце Текст , но мы должны установить некоторые ограничения для этого утверждения.

Например, одна буква также часть строки, но мы не должны искать такие случаи.

Вам также следует относиться к «лучшим» случаям, когда, например, 3 слова из Query были сопоставлены в Text чем совпадение для одного слова.

С учетом вышесказанного, я думаю, более разумным подходом является:

  • split Запрос в слова,
  • подсчитайте, сколько из этих слов имеют совпадения в Текст (несколько вхождений все равно должны учитываться как одно) - это результат для текущей строки,
  • применить вышеописанную процедуру к каждой строке в news_df .

Код для этого может быть следующим:

import re

def hasMatch(t1, t2):
    cnt = 0
    for wrd in filter(lambda tt: len(tt) > 0, re.split(r'[^a-z]', t2, re.I)):
        if re.search(wrd, t1):
            cnt += 1
    return cnt

desired_df = news_df.copy()
desired_df['Outcome'] = desired_df.apply(lambda row: hasMatch(row.Text, row.Query), axis=1)

В этом случае столбец Outcome имеет тип int (не bool ), но я думаю, что он лучше, чем bool .

Или, если для вас достаточно найти любое совпадение (даже одно слово), и вам не важно количество таких совпадений, измените вышеуказанная функция, так что она возвращает bool значений вместо int .

0 голосов
/ 28 апреля 2020

Этого можно добиться, используя лямбду

Приведенный ниже лог c может помочь вам достичь требуемого результата

news = {'Text':['Nike invests in shoes', 'Adidas invests in t-shirts', 'dog drank water before eating the meal'], 'Source':['NYT', 'WP', 'Guardian'], 'Query' :['Nike Ltd.', "LV", 'dog central']}
news_df = pd.DataFrame(news)
news_df['Outcome'] = news_df.apply(lambda row: bool(len(set(row['Query'].lower().split(' '))) != len(set(row['Query'].lower().split(' ')) - set(row['Text'].lower().split(' ')))),axis=1)
...