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

如何在Pandas DataFrame中实现字符串部分匹配并跨表赋值?

解决Pandas DataFrame字符串部分匹配赋值问题

看起来你在处理两个DataFrame的字符串匹配赋值时遇到了两个关键问题:生成的数组长度不符合预期,而且匹配逻辑也有偏差,再加上双重循环在大数据集下效率极低。我来帮你拆解问题并给出合适的解决方案。

你的代码问题在哪里?

  1. 数组长度错误:你用了双重循环,每遍历一次A的行就往clus_tx里追加一个值,最终数组长度是len(B)*len(A),远超过B的行数,这就导致赋值给B的Group列时肯定出错。
  2. 匹配逻辑失效:就算找到了匹配的A行,后续不匹配的A行还会把clus重新设为999,最后只能保留最后一次遍历的结果,根本留不住正确的匹配值。
  3. 效率低下:双重循环的时间复杂度是O(n*m),大数据集下会慢到无法接受。

正确实现方案

优先推荐向量化匹配方案,这是处理大规模数据的最优解;如果想先理清循环逻辑,也可以看修正后的循环方案。

方案1:向量化匹配(高效适配大数据集)

我们先把A中ID的核心部分提取出来(比如从DF-PI-xx提取PI-xx),然后用映射字典结合Pandas的向量化操作快速匹配,避免循环:

import numpy as np
import pandas as pd
import random

# 构造原始数据
A_list = ['DF-PI-05', 'DF-PI-09', 'DF-PI-10', 'DF-PI-15', 'DF-PI-16', 'DF-PI-19', 'DF-PI-89', 'DF-PI-92', 'DF-PI-93', 'DF-PI-94', 'DF-PI-95', 'DF-PI-96', 'DF-PI-25', 'DF-PI-29', 'DF-PI-30', 'DF-PI-34', 'DF-PI-84']
B_list = ['PI-05', 'PI-10', 'PI-89', 'PI-90', 'PI-93', 'PI-94', 'PI-95', 'PI-96', 'PI-09', 'PI-15', 'PI-16', 'PI-19', 'PI-91A', 'PI-91b', 'PI-92', 'PI-25-CU', 'PI-29', 'PI-30', 'PI-34', 'PI-84-CU-S1', 'PI-84-CU-S2']

sample_size = len(A_list)
Group = [random.randint(0,1) for _ in range(sample_size)]
A = pd.DataFrame(list(zip(A_list, Group)), columns=['ID', 'Group'])
B = pd.DataFrame(B_list, columns=['Name'])

# 提取A中ID的核心标识(去掉前缀DF-)
A['core_id'] = A['ID'].str.replace('DF-', '')

# 构建核心ID到Group值的映射字典
id_group_map = A.set_index('core_id')['Group'].to_dict()

# 用np.select实现向量化匹配,速度极快
conditions = [B['Name'].str.contains(core_id) for core_id in id_group_map.keys()]
choices = list(id_group_map.values())
B['Group'] = np.select(conditions, choices, default=999)

这种方式的时间复杂度接近O(n+m),完全适配大规模数据集,因为Pandas的向量化操作是基于C语言实现的,比Python循环快几个数量级。

方案2:修正后的循环方案(逻辑清晰,适合小数据集)

如果一定要用循环,得调整逻辑:对B的每一行先默认设为999,找到匹配后立即跳出A的循环,避免被后续不匹配值覆盖:

import numpy as np
import pandas as pd
import random

# 构造数据部分和上面一致
A_list = ['DF-PI-05', 'DF-PI-09', 'DF-PI-10', 'DF-PI-15', 'DF-PI-16', 'DF-PI-19', 'DF-PI-89', 'DF-PI-92', 'DF-PI-93', 'DF-PI-94', 'DF-PI-95', 'DF-PI-96', 'DF-PI-25', 'DF-PI-29', 'DF-PI-30', 'DF-PI-34', 'DF-PI-84']
B_list = ['PI-05', 'PI-10', 'PI-89', 'PI-90', 'PI-93', 'PI-94', 'PI-95', 'PI-96', 'PI-09', 'PI-15', 'PI-16', 'PI-19', 'PI-91A', 'PI-91b', 'PI-92', 'PI-25-CU', 'PI-29', 'PI-30', 'PI-34', 'PI-84-CU-S1', 'PI-84-CU-S2']

sample_size = len(A_list)
Group = [random.randint(0,1) for _ in range(sample_size)]
A = pd.DataFrame(list(zip(A_list, Group)), columns=['ID', 'Group'])
B = pd.DataFrame(B_list, columns=['Name'])

clus_tx = []
for _, row in B.iterrows():
    clus = 999  # 默认值设为999
    for _, row2 in A.iterrows():
        # 检查B的Name是否包含A的核心ID
        if row2['ID'].replace('DF-', '') in row['Name']:
            clus = row2['Group']
            break  # 找到匹配后立即停止遍历A,避免被覆盖
    clus_tx.append(clus)

B['Group'] = clus_tx

这里修正了三个关键点:

  • 每处理B的一行,先初始化clus为999
  • 找到匹配后立刻break,不再遍历后续的A行
  • 每处理完B的一行才往clus_tx加一个值,确保数组长度和B一致

验证结果

运行上述代码后,B的Group列会正确赋值:

  • 像PI-05会匹配DF-PI-05,得到对应的Group值
  • PI-90没有匹配项,赋值999
  • PI-84-CU-S1包含PI-84,会匹配DF-PI-84的Group值

内容的提问来源于stack exchange,提问作者JCV

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 21:57:31