Pandas中如何按两列透视DataFrame聚合产品字段并完成独热编码
实现路径梳理
1. 关于df.pivot的适用性说明
原生df.pivot方法无法直接实现需求的第一步聚合。
这里很容易混淆两个透视类方法的能力边界:
df.pivot:无内置聚合能力,仅支持无重复键值对的宽表转换,当account+opportunity分组下存在多个product值时,会直接抛出索引重复的错误,不支持将同组值拼接为列表df.pivot_table:内置聚合参数aggfunc,可灵活指定聚合规则,只要指定aggfunc=list即可得到同组product聚合为列表的中间表,是可以满足第一步需求的
对应的pivot_table实现代码:
# 用pivot_table实现分组列表聚合 agg_df = df.pivot_table( index=["account", "opportunity"], values="product", aggfunc=list ).reset_index()
注:示例中你写出的
c2 o2对应聚合结果为[p3,p3]属于笔误,基于提供的原始数据,分组聚合后该组的product列表应为[p2,p3],对应的独热编码结果和你给出的最终表完全匹配。
2. 第一步聚合的通用实现方式
不依赖透视接口的分组聚合写法,是这类需求的通用解法,逻辑更直观,和pivot_table的运行结果完全一致:
agg_df = df.groupby( ["account", "opportunity"], as_index=False )["product"].agg(list)
3. 衔接后续独热编码流程
你编写的基于MultiLabelBinarizer(即代码中的mlb)的独热编码逻辑完全可以正常复用,只要在聚合完成后传入聚合列表字段即可:
from sklearn.preprocessing import MultiLabelBinarizer mlb = MultiLabelBinarizer() # 对聚合后的product列表做多标签二值化 onehot_res = pd.DataFrame( mlb.fit_transform(agg_df.pop("product")), columns=mlb.classes_, index=agg_df.index ) # 拼接得到最终表 final_df = agg_df.join(onehot_res)
运行后即可输出符合预期的独热编码结果。
可选优化:跳过中间聚合步骤
如果最终目标就是生成多标签独热表,完全可以省略「先把product聚合成列表」的中间环节,通过pandas内置方法直接从原始长表生成最终结果,减少不必要的中间计算,同时无需依赖第三方机器学习库:
final_df = ( df.drop_duplicates(["account", "opportunity", "product"]) .assign(flag=1) .pivot_table( index=["account", "opportunity"], columns="product", values="flag", fill_value=0 ) .reset_index() )
该方法的运行结果和多步流程完全一致。
内容的提问来源于stack exchange,提问作者Devarshi Goswami
相关产品推荐
相关产品推荐

