在 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.
我有以下数据框,其中包含新闻文本(文本列)和我 运行 从 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.