如何使用pandas从含双列表列的DataFrame创建分类为列的新DataFrame
列表型分类-数值列转宽表的pandas实现
方案1:逐行字典映射(小数据量最易理解)
代码逻辑直白,几千行以内的表用起来不需要额外理解复杂API:
import pandas as pd # 构造题目给出的原始输入 df = pd.DataFrame({ "values": [[2, 4, 3, 5], [1, 6, 7], [3, 5]], "categories": [['a', 'c', 'd', 'e'], ['b', 'c', 'e'], ['c', 'f']] }) # 逐行把对齐的分类、数值打包成映射字典 row_mappings = [ dict(zip(cats, vals)) for cats, vals in zip(df["categories"], df["values"]) ] # 生成宽表,空值填0,顺带把因NaN生成的浮点类型转回整数 wide_df = pd.DataFrame(row_mappings).fillna(0, downcast="integer") # 按字母序排序列,和示例输出格式完全匹配 wide_df = wide_df.sort_index(axis=1)
方案2:explode+pivot向量化实现(大数据量性能最优)
当数据量到几万行以上时,逐行循环的耗时会明显上升,用pandas内置的向量化操作速度会快很多:
# 基础输入df的构造和方案1完全一致 # 把两列的列表同时炸开,拆成长表结构:每行对应一个分类-数值对 exploded = df.explode(["categories", "values"]) # 标记原始行ID,避免不同行的同分类值在透视时被合并 exploded = exploded.reset_index(names="raw_row_id") # 透视成宽表,空值填充为0并转回整数类型 wide_df = exploded.pivot( index="raw_row_id", columns="categories", values="values" ).fillna(0, downcast="integer") # 清理多余的元信息 wide_df.columns.name = None wide_df.index = None
常见调整技巧
- 觉得列顺序不符合预期时,可以直接用reindex指定固定列顺序:
wide_df = wide_df.reindex(columns=["a", "b", "c", "d", "e", "f"]) - 如果某行的分类列表里存在重复值导致透视报错,可以给pivot函数加
aggfunc="sum"参数,自动把同分类的重复数值求和后填入对应位置 - 不要省略
downcast="integer"参数,否则pandas会因为存在空值把整列转成float类型,出现2.0这种不符合整数存储预期的结果
内容的提问来源于stack exchange,提问作者frohnatur3
相关产品推荐
相关产品推荐

