在 Pandas 中验证 A 列的子字符串是否与 B 列的子字符串匹配

Verify whether substring of column A matches with substring in column B in Pandas

我有以下数据框,其中包含新闻文本(文本列)和我 运行 从 API 中提取特定新闻文本的查询(查询列)。并非所有新闻文本都与查询相关,因此我试图创建一个新列,如果查询字符串的最后一部分位于文本列中,则 returns 为真。我知道如何检查整个查询字符串是否在文本中,但如您所见,通常是官方公司名称,例如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 )

有什么建议吗?

您可以使用 lambda 实现此目的

以下逻辑可以帮助您实现所需的输出

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)

您写了部分查询字符串在文本列中,但我们应该 对此声明设置一些限制。

例如一个单个字母也是字符串的一部分,但我们应该不看 对于这种情况。

您还应该处理 "better" 个案例,例如来自 Query 的 3 个词已被 在 Text 中匹配,而不是在 单个 单词中匹配。

综合以上,我认为比较合理的做法是:

  • 拆分查询成词,
  • 计算这些词中有多少在 Text 中匹配(多个 出现次数仍应计为一次)-这是结果 当前行,
  • 将上述过程应用于 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.

或者,如果对您来说,找到 任何 匹配项(甚至是一个单词)就足够了,并且 你不关心这种匹配的数量,改变上面的功能 所以它 returns bool 值而不是 int.