You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在DataFrame文本列匹配多字符串并累加对应分数的高效实现方法

高效实现Pandas子串匹配并累加分数

当然有更简洁高效的实现方式!你当前用的双重iterrows()循环在数据量较大时会非常慢,因为它是逐行的Python级别迭代。我们可以利用Pandas的向量化操作来大幅提升效率,下面提供两种实用方案:

方案1:使用apply结合布尔索引(简洁易读)

这种方法代码直观,适合中小规模数据集:

import pandas as pd

# 初始化示例数据
df1 = pd.DataFrame({
    'ID':[1,2,3,4,5,6],
    'Texts':['this is a string', 'here we have another string', 'this one is completly different', 'one more', 'this is one more', 'and the last one'],
    'c':['C','C','C','C','C','C'],
    'd':['D','D','D','D','NaN','NaN']
})

df2 = pd.DataFrame({
    'SubString':['This', 'one', 'this is', 'is one'],
    'Score':[0.5, 0.2, 0.75, -0.5]
})

# 为df1添加Score列
df1['Score'] = df1['Texts'].apply(
    lambda txt: df2[df2['SubString'].apply(lambda s: s in txt)]['Score'].sum()
)

print(df1)

这段代码对df1的每个文本,筛选出df2中满足“子串存在于文本”的行,然后累加对应的分数。

方案2:广播+矩阵运算(性能最优)

如果你的数据集很大,推荐这种方法——利用NumPy的向量化计算,完全避免Python层面的循环,速度提升非常明显:

# 创建布尔匹配矩阵:每行对应df1的文本,每列对应df2的子串,值为子串是否在文本中
matches = df1['Texts'].apply(lambda x: df2['SubString'].apply(lambda y: y in x)).values

# 通过矩阵乘法直接计算每个文本的总分
df1['Score'] = matches @ df2['Score'].values

print(df1)

扩展:忽略大小写匹配

如果需要不区分大小写的匹配,可以将文本和子串统一转为小写:

# 方案2的大小写不敏感版本
matches = df1['Texts'].str.lower().apply(
    lambda x: df2['SubString'].str.lower().apply(lambda y: y in x)
).values
df1['Score'] = matches @ df2['Score'].values

为什么这两种方法更好?

  • 避免了iterrows()的低效逐行迭代:iterrows()会把每一行转为Python对象,速度远低于Pandas/NumPy的向量化操作。
  • 代码更简洁:去掉了嵌套循环,逻辑一目了然。
  • 性能差距显著:当df1有1000行、df2有100行时,向量化方法的速度会比双重循环快几十倍甚至上百倍。

内容的提问来源于stack exchange,提问作者Fernando S. Peregrino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:04:15