如何高效处理Pandas含重复值列的非向量化转换?
优化Pandas重复值的非向量化转换效率
假设我们有一个包含列A的Pandas DataFrame df,以及如下非向量化转换函数:
def transform_a_to_b(a): ... return b
常规做法是通过df['B'] = df['A'].apply(lambda x: transform_a_to_b(x))生成列B,但这个转换函数耗时较长,且A列存在大量重复值,重复值的转换结果完全一致。同时原DataFrame还有其他列,需要将转换结果映射回原表每一行。
已经实现了一种基于merge的解法(仅对3个唯一值执行3次转换),但希望找到更简洁的方案,允许使用缓存但不能修改原转换函数。
测试代码及现有解法
transform_counts = 0 def transform_a_to_b(a): global transform_counts # 统计函数调用次数 transform_counts += 1 return 2 * a # 包含大量重复值的测试DataFrame df = pd.DataFrame({ 'A': [1, 3, 2, 2, 3, 3, 2, 3, 1, 1, 1], }) # 现有merge解法:仅对3个唯一A值执行转换,保留原表顺序 df = df.merge( df['A'].drop_duplicates().apply(lambda a: pd.Series( data=[a, transform_a_to_b(a)], index=['A', 'B'], )), on='A', how='left', )
执行后transform_counts为3,结果DataFrame如下:
A B 0 1 2 1 3 6 2 2 4 3 2 4 4 3 6 5 3 6 6 2 4 7 3 6 8 1 2 9 1 2 10 1 2
更简洁的替代方案
方案1:用functools.lru_cache给原函数加缓存
无需修改原函数,通过装饰器包装实现自动缓存,直接用map调用即可:
from functools import lru_cache # 包装原函数,添加缓存功能 cached_transform = lru_cache(maxsize=None)(transform_a_to_b) # 映射生成B列 df['B'] = df['A'].map(cached_transform)
执行后transform_counts同样为3,代码更简洁,缓存会自动处理重复值,无需手动提取唯一值。
方案2:先生成唯一值映射字典,再用map
手动提取唯一值生成转换后的映射关系,再映射回原表:
# 提取唯一值并生成映射字典 unique_a = df['A'].unique() a_to_b = {a: transform_a_to_b(a) for a in unique_a} # 映射生成B列 df['B'] = df['A'].map(a_to_b)
这种方式手动控制唯一值的转换,避免了merge的繁琐语法,同样只调用3次转换函数。
方案3:用replace方法
本质和方案2类似,利用字典替换生成新列:
unique_a = df['A'].unique() a_to_b = {a: transform_a_to_b(a) for a in unique_a} df['B'] = df['A'].replace(a_to_b)
内容的提问来源于stack exchange,提问作者Logan Pageler
相关产品推荐
相关产品推荐

