从DataFrame混合类型列提取值生成新列的高效方案
高效处理Pandas中混合格式price_list列的匹配问题
原逐行apply的方法在大数据集下效率低下,核心原因是重复解析相同的字典字符串、逐行循环的Python级操作性能差。以下是基于批量预处理+矢量化操作的高效解决方案:
核心思路
- 批量处理唯一的
price_list值,避免重复解析字典字符串; - 将字典格式的
price_list展开为shop_id-price映射表,通过merge实现批量匹配; - 用矢量化条件判断处理单个数值、
NaN字符串的情况。
完整代码
import pandas as pd import numpy as np import ast # 原始数据集 df = pd.DataFrame( {'item_id': [1,1,1,2,3,4,4], 'shop_id': ['S1','S2','S3','S2','S3','S1','S2'], 'price_list': [ "{'10':['S1','S2'], '20':['S3'], '30':['S4']}", "{'10':['S1','S2'], '20':['S3'], '30':['S4']}", "{'10':['S1','S2'], '20':['S3'], '30':['S4']}", '50', 'NaN', "{'10':['S1','S2','S3'],'25':['S4']}", "{'10':['S1','S2','S3'],'25':['S4']}" ]} ) # 1. 处理所有字典类型的price_list,生成shop-price映射临时表 unique_dict_pls = df[df['price_list'].str.startswith('{')]['price_list'].unique() temp_dfs = [] for pl in unique_dict_pls: # 用ast.literal_eval替代eval,更安全且性能相当 price_dict = ast.literal_eval(pl) # 把字典展开为(price_list, shop_id, price)的三元组 shop_price_pairs = [] for price, shops in price_dict.items(): shop_price_pairs.extend([(pl, shop, price) for shop in shops]) temp_dfs.append(pd.DataFrame(shop_price_pairs, columns=['price_list', 'shop_id', 'price'])) # 合并临时表 temp_merge_df = pd.concat(temp_dfs, ignore_index=True) # 2. 关联原表和临时表,批量匹配字典类型的价格 df = df.merge(temp_merge_df, on=['price_list', 'shop_id'], how='left') # 3. 处理非字典类型的情况:单个数值、NaN字符串 df['price'] = np.where( df['price_list'] == 'NaN', np.nan, np.where( ~df['price_list'].str.startswith('{'), df['price_list'], df['price'] ) ) # 可选:将price列转为数值类型 df['price'] = pd.to_numeric(df['price'], errors='coerce') # 输出目标结果 print(df[['item_id', 'shop_id', 'price']])
效率提升原因
- 减少重复计算:只对唯一的
price_list解析一次,避免原apply中重复解析相同字典字符串的冗余操作; - 矢量化操作替代循环:
merge和np.where都是Pandas底层优化的矢量化操作,比Python级逐行循环快数倍至数十倍; - 安全解析字典:用
ast.literal_eval替代eval,避免恶意代码执行风险,同时保持解析效率。
内容的提问来源于stack exchange,提问作者charlie_boy
相关产品推荐
相关产品推荐

