pandas基于参考列表为main_frame列赋值的无for循环实现咨询
无循环等价实现方案
原逻辑核心是按参考组顺序匹配关键词、命中后赋值对应标签,可通过向量化操作完全替代外层遍历参考组的for循环,以下是两种可完全复现原结果的实现方式:
方案1:使用numpy.select批量条件赋值
该方法处理逻辑和原逻辑最接近,仅需提前批量生成所有匹配条件,再一次性完成赋值,无需逐组调用df.loc修改数据:
import pandas as pd import numpy as np watchlist_ref = [['A1','AA2','A3'], ['B1','BC2','B3']] upper_ref = ['A','B'] df = pd.DataFrame ({'tw':['A1','AA2','A3','B1','BC2','B3']}) # 批量生成按原参考组顺序的匹配条件 conditions = [ df['tw'].str.contains('|'.join(ls_str), case=False) for ls_str in watchlist_ref ] # 原循环中后执行的组会覆盖前序匹配结果,因此反转条件和标签顺序,让高优先级组先被判断 conditions = conditions[::-1] values = upper_ref[::-1] df['main_frame'] = np.select(conditions, values, default=np.nan)
注意:若所有参考组的关键词无重叠,不需要反转顺序,输出结果和原逻辑完全一致;若存在重叠匹配,反转后即可1:1复刻原循环的覆盖优先级。
方案2:合并命名正则批量提取标签
将所有参考组的关键词合并为带命名捕获组的单个正则,通过pandas内置的字符串提取功能一次性匹配,无需逐组遍历赋值:
# 预处理生成带命名组的合并正则(仅为字符串拼接操作,无逐行/逐组遍历赋值逻辑) pattern_parts = [f"(?P<{label}>{'|'.join(words)})" for words, label in zip(watchlist_ref, upper_ref)] # 若要匹配原循环后序覆盖的优先级,可将pattern_parts倒序后再拼接 full_pattern = '|'.join(pattern_parts[::-1]) # 批量提取匹配到的组名,直接赋值给main_frame列 df['main_frame'] = df['tw'].str.extract(full_pattern, case=False).bfill(axis=1).iloc[:, 0]
效果验证
对应用户给出的测试用例,两种方案输出结果均与原逻辑完全一致:
tw main_frame 0 A1 A 1 AA2 A 2 A3 A 3 B1 B 4 BC2 B 5 B3 B
两种方案均为pandas层面的向量化操作,执行效率远高于原for循环实现,在数据量较大时优势更明显。
内容的提问来源于stack exchange,提问作者rpb
相关产品推荐
相关产品推荐

