You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas基于已有DataFrame高效创建含二进制列的新DataFrame

高效实现DataFrame的二进制编码(替代循环方法)

嘿,我完全懂你遇到的痛点——嵌套循环处理大型数据集时,那种慢到让人抓狂的感觉真的不好受!其实Pandas和Scikit-learn有专门的矢量化/批量处理工具,能帮你以快得多的速度完成这个二进制编码需求,而且代码更简洁。

先明确你的需求:把原DataFrame每行的每个元素,对应到新DataFrame的列(比如prod_xxx),出现过的标记为1,没出现的为0。下面分两种常见场景给你最优方案:

场景1:原DataFrame是宽格式(每行对应一个样本,每列是单个产品项)

比如你的products是这样的结构(每行是一个用户,每列是他购买的一个产品):

import pandas as pd

products = pd.DataFrame({
    'item1': ['A', 'B', 'C'],
    'item2': ['B', 'D', None],
    'item3': ['A', 'C', 'D']
})

最优实现代码

用stack() + get_dummies() + groupby().sum()的组合,全程矢量化操作,比循环快几个数量级:

# 1. 把所有元素堆叠成Series,保留原行索引
stacked_products = products.stack()

# 2. 生成二值化编码,再按原索引分组求和(同一行的多个产品合并为1)
products_coded = pd.get_dummies(stacked_products, prefix='prod').groupby(level=0).sum()

这样得到的products_coded就是每行对应原DataFrame的行,每列是prod_A、prod_B这类,值为1或0的结果。

场景2:原DataFrame是长格式(每行是一个样本,单元格是产品列表)

如果你的products是每行存一个产品列表的结构:

products = pd.DataFrame({
    'user_products': [['A', 'B'], ['B', 'D'], ['A', 'C', 'D']]
})

最优实现代码

用Scikit-learn的MultiLabelBinarizer,专门处理多标签的二值化:

from sklearn.preprocessing import MultiLabelBinarizer

# 初始化二值化器
mlb = MultiLabelBinarizer()

# 生成编码结果,转成DataFrame并加上前缀
products_coded = pd.DataFrame(
    mlb.fit_transform(products['user_products']),
    columns=[f'prod_{item}' for item in mlb.classes_],
    index=products.index
)

为什么你的循环方法慢?

你之前用的嵌套循环+ix赋值(注意ix已经被Pandas弃用,推荐用loc/iloc),本质是逐元素修改DataFrame——每次赋值都会触发DataFrame的内存重新分配和索引更新,大数据集下这种操作的开销会被无限放大。而上面的方法都是批量处理,底层用C语言实现,跳过了Python循环的额外开销,速度提升非常明显。

额外小技巧

  • 如果原数据有缺失值,stack()会自动忽略,get_dummies()和MultiLabelBinarizer也会自动处理,没出现的产品列默认是0;
  • 可以通过get_dummies(prefix='prod')直接给列加前缀,不用手动拼接字符串;
  • 如果需要把结果填充0(比如原行没有的产品列),可以用fillna(0)确保所有值都是0或1。

内容的提问来源于stack exchange,提问作者Subhanandh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:09:40