如何高效为DataFrame多分类列的指定代码子集生成哑变量列?
优化Pandas百万级数据的哑变量生成与分组聚合方案
问题背景
现有如下Pandas DataFrame:
d = {"account_number": [1234, 5678, 9012, 1234, 5678, 9012, 1234, 5678, 9012, 1234, 5678, 9012], "c1": ["V89", "M54", "T14", "V89", "M54", "S13", "V89", "M62", "T14", "V43", "M54", None], "c2": ["V43", "M54", None, "T14", "M54", None, "G89", None, "T14", "S59", None, None], "c3": [None, None, None, "LML", None, None, "G89", None, None, "V29", None, None]} df = pd.DataFrame(data=d)
该DataFrame包含c1、c2、c3三列三位字符代码,列中存在超11000种代码,但仅关注其中15种:
codes = ["V89", "M54", "V49", "R07", "V43", "S16", "R51", "S52", "S59", "M99", "T14", "S13", "S61", "V29", "V87"]
原方案通过apply生成初始哑变量,再用iterrows遍历更新c2、c3对应的指示列,最后按account_number分组取max聚合。但iterrows在百万级数据、多代码列场景下性能极差,需要更高效的优化方案。
优化方案
步骤1:将多列代码数据重塑为长格式
把c1/c2/c3列转换为长表结构,保留account_number关联信息,统一处理所有代码列:
# 重塑数据,保留account_number和所有代码列的有效代码 long_df = df.melt(id_vars="account_number", value_vars=["c1", "c2", "c3"], value_name="code") # 过滤掉None和不在目标codes中的代码 long_df = long_df.dropna(subset=["code"]) long_df = long_df[long_df["code"].isin(codes)]
步骤2:生成哑变量并按账户聚合
利用pivot_table直接按account_number分组,对每个目标代码标记是否存在:
# 给每条有效代码记录标记为1 long_df["flag"] = 1 # 透视表生成哑变量,缺失值填充为0 result = long_df.pivot_table(index="account_number", columns="code", values="flag", aggfunc="max", fill_value=0).reset_index() # 补全所有目标codes中未出现的列,确保结果包含全部15个代码列 for code in codes: if code not in result.columns: result[code] = 0 # 调整列顺序,将account_number放在首位,其余按codes顺序排列 result = result[["account_number"] + codes]
性能优势说明
- 原方案的
iterrows是逐行操作,时间复杂度为O(n*m)(n为行数,m为代码列数),百万级数据下会非常缓慢。 - 优化方案采用矢量化重塑+透视聚合,所有操作都是Pandas内部优化的C级运算,时间复杂度大幅降低,内存占用也更可控,在百万级数据上速度可提升数十倍。
内容的提问来源于stack exchange,提问作者marv722
相关产品推荐
相关产品推荐

