商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Pandas 中将列表列按行展开并转换为宽格式的完整教程

Pandas 中将列表列按行展开并转换为宽格式的完整教程

  发布于2026-07-15 阅读(0)

扫一扫,手机访问

在数据处理中,经常会遇到一种情况:某一列里存着长度一致的列表,比如[10, 11]。我们的目标是把它们“行内展开”,变成独立的列,比如col_1col_2,最终得到一个标准宽表。很多人第一反应是explodepivot,但这条路其实绕远了,而且容易踩坑。更简洁、高效的方式,其实就藏在pd.DataFrame()构造器里——直接配合indexcolumns参数一步到位。

✅ 推荐方案:一步构造宽格式 DataFrame

先看一个例子,假设原始数据长这样:

import pandas as pd
data = [[1, [10, 11]], [2, [15, 16]], [3, [20, 24]], [4, [22, 23]]]
df = pd.DataFrame(data, columns=['id', 'val'])

现在要把val列里的每个列表展开成两列,并且用id作为行索引。核心代码其实就一行:

out = pd.DataFrame(
    df['val'].tolist(),           # 展开为二维数组:[[10,11], [15,16], ...]
    index=df['id'],              # 指定行索引为原 id 列
    columns=['col_1', 'col_2']   # 显式命名新列
)

输出结果就是我们想要的宽格式:

    col_1  col_2
id            
1      10     11
2      15     16
3      20     24
4      22     23

⚠️ 注意:这种方法要求df['val']中所有列表长度严格一致。如果存在不等长或缺失值(None/NaN),.tolist()会直接报错,或者填充NaN。所以,数据清洗这一步不能省。

? 动态列名:适用于任意长度列表

如果列表长度是未知的,或者可能会变化,那就需要动态生成列名了。比如,用col_1col_2col_3……这样的命名方式:

# 自动推断列数,并命名
n_cols = len(df['val'].iloc[0]) if not df.empty else 0
out = (pd.DataFrame(df['val'].tolist(), index=df['id'])
         .rename(columns=lambda x: f'col_{x + 1}'))

或者更稳健一些,结合range来处理:

out = (pd.DataFrame(df['val'].tolist(), index=df['id'])
         .rename(columns=lambda i: f'col_{i+1}')
         .reset_index())  # 若需将 id 变回普通列

❌ 为什么不推荐 explode + pivot?

确实,df.explode('val').assign(col_num=df.groupby(level=0).cumcount()+1)也能生成一个带序号的中间表,但后续还需要pivot()来转置。问题在于,这个过程很容易因为索引错位、重复键等问题而失败。相比之下,pd.DataFrame(..., index=...)直接绑定原始的id,天然保证了行对齐。代码更短、性能更高(没有分组和聚合的开销),逻辑也更透明。

✅ 最终建议工作流

  1. 验证列表长度一致性df['val'].str.len().nunique() == 1
  2. 直接构造宽表pd.DataFrame(df['val'].tolist(), index=df['id'])
  3. 重命名列(可选):.rename(columns=lambda x: f'feature_{x+1}')
  4. 重置索引(如需):.reset_index()

这个方法兼具可读性、健壮性和执行效率,可以说是 pandas 处理“列表列转宽表”任务的标准实践了。

本文转载于:https://www.php.cn/faq/2825505.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注