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

拆分DataFrame为多列:代码缺失列问题排查与优化方案

问题描述

我的数据集结构类似下图(行数更多):
原始数据

目标是得到如下结构:
目标结构

我尝试的代码如下:

# Identify names that are in the dataset
names = df['name'].unique().tolist()

# Define dataframe with first name
df1 = pd.DataFrame()
df1 = df[(df == names[0]).any(axis=1)]
df1 = df1.drop(['name'], axis=1)
df1 = df1.rename({'color':'color_'+str(names[0]), 'number':'number_'+str(names[0])}, axis=1)

# Make dataframes with other names and their corresponding color and number, add them to df1
df_merged = pd.DataFrame()
for i in range(1, len(names)):
    df2 = pd.DataFrame()
    df2 = df[(df == names[i]).any(axis=1)]
    df2 = df2.drop(['name'], axis=1)
    df2 = df2.rename({'color':'color_'+str(names[i]), 'number':'number_'+str(names[i])}, axis=1)
    df_merged = df1.join(df2, lsuffix="_left", rsuffix="_right", how='left')

最终得到的df_merged结果如下:
结果

可见color_Donald和number_Donald列缺失,循环似乎跳过或覆盖了Donald相关内容,求问原因及代码优化方法。


问题原因与优化方案

原因分析

  1. 循环覆盖问题:你每次循环都用初始的df1和当前df2做join,然后把结果赋值给df_merged,这导致只有最后一次循环的结果会保留,之前的列全被覆盖。比如如果names是['Mickey', 'Donald', 'Goofy'],循环到Goofy时,df_merged就变成了df1+Goofy的列,Donald的列自然丢失。
  2. 筛选逻辑隐患:用(df == names[i]).any(axis=1)筛选行,可能会误匹配到其他列(比如color/number)值和name相同的行,正确的筛选应该直接指定name列:df[df['name'] == names[i]]。

优化代码

方法一:用pivot一步到位(推荐)

pandas的pivot是处理这类宽表转换的标准方法,代码简洁高效:

# 给每个人的行添加序号,确保行对应(假设每个人的行数一致)
df['row_id'] = df.groupby('name').cumcount()

# 执行透视转换
result = df.pivot(index='row_id', columns='name', values=['color', 'number'])

# 合并多层列名为目标格式
result.columns = [f'{col[0]}_{col[1]}' for col in result.columns]

# 可选:移除row_id索引
result = result.reset_index(drop=True)

方法二:修复循环逻辑

如果一定要用循环,需要每次把新列合并到上一次的结果中,而不是每次都用初始的df1:

names = df['name'].unique().tolist()

# 初始化结果为第一个name的数据
result = df[df['name'] == names[0]].drop('name', axis=1)
result = result.rename(columns={'color': f'color_{names[0]}', 'number': f'number_{names[0]}'})

# 循环合并剩余name的数据
for name in names[1:]:
    temp_df = df[df['name'] == name].drop('name', axis=1)
    temp_df = temp_df.rename(columns={'color': f'color_{name}', 'number': f'number_{name}'})
    # 合并到结果中,保证行索引对应
    result = result.join(temp_df, how='left')

两种方法都能得到目标结构,优先用pivot方法,性能和可读性都更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:25:21