发布于2026-07-15 阅读(0)
扫一扫,手机访问
在数据处理中,经常会遇到一种情况:某一列里存着长度一致的列表,比如[10, 11]。我们的目标是把它们“行内展开”,变成独立的列,比如col_1、col_2,最终得到一个标准宽表。很多人第一反应是explode再pivot,但这条路其实绕远了,而且容易踩坑。更简洁、高效的方式,其实就藏在pd.DataFrame()构造器里——直接配合index和columns参数一步到位。
先看一个例子,假设原始数据长这样:
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_1、col_2、col_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 变回普通列
确实,df.explode('val').assign(col_num=df.groupby(level=0).cumcount()+1)也能生成一个带序号的中间表,但后续还需要pivot()来转置。问题在于,这个过程很容易因为索引错位、重复键等问题而失败。相比之下,pd.DataFrame(..., index=...)直接绑定原始的id,天然保证了行对齐。代码更短、性能更高(没有分组和聚合的开销),逻辑也更透明。
df['val'].str.len().nunique() == 1pd.DataFrame(df['val'].tolist(), index=df['id']).rename(columns=lambda x: f'feature_{x+1}').reset_index()这个方法兼具可读性、健壮性和执行效率,可以说是 pandas 处理“列表列转宽表”任务的标准实践了。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8