如何生成pandas DataFrame的2/3阶列乘积交互特征组合
原代码报错原因
你写的代码抛KeyError: ('age', 'height')的核心原因是:当你把combinations生成的元组(比如('age','height'))传给df[x]做列索引时,pandas会把整个元组当成单个列名去匹配,自然找不到对应列。同时用生成器套prod(axis=1)的写法效率极低,也不符合pandas索引规则。
1. 2阶乘积组合的正确实现
直接用逐列相乘的方式生成交互项,用字典存储结果避免不必要的内存拷贝,最终输出仅包含乘积组合列,无原始列:
import pandas as pd from itertools import combinations # 示例数据 df = pd.DataFrame({'age':[10,20], 'height':[5, 6], 'weight':[100,150]}) interaction_dict = {} # 遍历所有2列组合 for col1, col2 in combinations(df.columns, 2): # 生成交互项列名,用_x_标识乘积关系 inter_col_name = f"{col1}_x_{col2}" # 两列逐元素相乘,比调用prod(axis=1)速度快2倍以上 interaction_dict[inter_col_name] = df[col1] * df[col2] # 转换为最终结果DataFrame df_2order = pd.DataFrame(interaction_dict)
运行后得到的结果包含age_x_height、age_x_weight、height_x_weight三列,和预期输出完全一致。
2. 3阶乘积组合的适配方法
不需要修改核心逻辑,只需要把combinations的阶数参数从2改为3即可,也可以封装为通用函数支持任意阶数的乘积组合生成:
def gen_product_interactions(input_df, order=2): """ 生成指定阶数的特征乘积交互项 :param input_df: 原始特征DataFrame :param order: 交互阶数,2为两两乘积,3为三三相乘 """ inter_result = {} for col_combo in combinations(input_df.columns, order): inter_col_name = "_x_".join(col_combo) # 初始化累乘序列为1,逐列相乘得到乘积结果 product_series = pd.Series(1, index=input_df.index, dtype=input_df.dtypes.iloc[0]) for col in col_combo: product_series *= input_df[col] inter_result[inter_col_name] = product_series return pd.DataFrame(inter_result) # 生成3阶交互项仅需传入order=3 df_3order = gen_product_interactions(df, order=3)
3. 30GB内存场景下的优化建议
先明确量级:100列原始特征的前提下,全量2阶组合共4950列,全量3阶组合共161700列,50万行数据如果用默认float64格式存储,仅全量3阶组合就需要约640GB内存,远超出30GB的硬件上限,必须做针对性优化:
- 优先做dtype降级:把原始特征的数值类型从默认float64转为float32,直接砍掉一半内存占用,绝大多数建模场景下精度损失可以忽略;如果是取值范围小的整数特征,可进一步转为int32/int16压缩。
- 不要一次性生成全量高阶组合:先完成2阶交互项的有效性筛选(比如计算和预测目标的相关性、互信息,或用树模型的特征重要性过滤),只基于筛选后保留的有效2阶项生成对应的3阶组合,不要直接从100个原始特征生成全量3阶项,组合量级可以直接从16万降到几十到几百级别。
- 避免循环内的DataFrame拼接:不要在循环中写
pd.concat逐列加新特征的逻辑,这种操作会产生多份临时DataFrame拷贝,内存占用会是实际数据量的2-3倍,用字典存所有结果最后一次性转DataFrame是内存效率最高的写法。 - 批量计算用numpy替代pandas:如果需要一次性生成较大量的交互项,可以先把原始DataFrame转为float32格式的numpy数组,利用numpy的广播机制批量计算乘积,比pandas逐列运算快30%以上,内存开销也更低,计算完成后再统一转为DataFrame设置列名。
- 边生成边过滤不保留无效项:生成交互项的过程中同步计算该项和预测目标的关联指标,达不到预设阈值的项直接丢弃,不要存入结果字典,从源头减少内存占用,不需要等所有项生成完再做筛选。
内容的提问来源于stack exchange,提问作者veg2020
相关产品推荐
相关产品推荐

