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

如何按唯一ID转置DataFrame行?Python Pandas数据重构求助

Pandas DataFrame重构问题解决方案

首先先还原你的原始DataFrame(方便后续测试):

import pandas as pd

df = pd.DataFrame({
    'Name': ['John', 'John', 'John', 'Amanda', 'Amanda', 'Amanda'],
    'ID': ['BE2', 'BE1', 'DE1', 'BE2', 'BE1', 'DE1'],
    'Birth_date': ['18/05/2011 06:45', '18/05/2011 06:55', '18/05/2011 03:11',
                   '18/05/2011 04:44', '18/05/2011 06:08', '18/05/2011 12:08'],
    'Age': [22, 21, 42, 35, 25, 36]
})

你想要的目标格式是把每个用户的生日和年龄分别占一行,ID作为列。之前用set_index('ID').T的方法会把所有字段都转置,所以才会出现重复的ID列,显然不是我们要的效果。

这里给你两种简单高效的实现方法:

方法一:拆分+合并法

这种方法逻辑很直观,先分别处理生日和年龄的宽表,再把它们堆叠起来:

# 1. 分别生成生日和年龄的宽表(ID转成列)
birth_df = df.pivot(index='Name', columns='ID', values='Birth_date').reset_index()
age_df = df.pivot(index='Name', columns='ID', values='Age').reset_index()

# 2. 给两个表添加标识,区分是用户行还是年龄行
birth_df['row_label'] = birth_df['Name']
age_df['row_label'] = 'Age'

# 3. 合并两个表,调整列顺序和索引
result = pd.concat([birth_df, age_df], ignore_index=True)
# 重新设置列名和索引
result = result.set_index('row_label').rename_axis(None).reset_index()
result.columns = ['Name'] + list(birth_df.columns[1:-1])

print(result)

运行后就能得到你想要的结果:

Name         BE2         BE1         DE1
0    John  18/05/2011 06:45  18/05/2011 06:55  18/05/2011 03:11
1     Age                22                21                42
2  Amanda  18/05/2011 04:44  18/05/2011 06:08  18/05/2011 12:08
3     Age                35                25                36

方法二:长表转宽表法

如果数据更复杂,这种用melt+pivot_table的组合会更灵活:

# 1. 把原始数据转成"长格式",将Birth_date和Age合并成一个字段
df_melted = df.melt(id_vars=['Name', 'ID'], var_name='data_type', value_name='value')

# 2. 转成宽格式,用Name和data_type作为行索引,ID作为列
pivot_result = df_melted.pivot_table(
    index=['Name', 'data_type'],
    columns='ID',
    values='value',
    aggfunc='first'
).reset_index()

# 3. 调整第一列的显示,把Birth_date对应的行显示用户名,Age对应的行显示'Age'
pivot_result['Name'] = pivot_result.apply(
    lambda x: x['Name'] if x['data_type'] == 'Birth_date' else 'Age',
    axis=1
)
# 去掉多余的data_type列,重置索引
final_result = pivot_result.drop('data_type', axis=1).reset_index(drop=True)

print(final_result)

这个方法同样能得到和目标一致的输出,而且如果后续有更多类似Birth_date、Age的字段,只需要调整melt的参数就能轻松扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:14:49