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

如何在Python中将列值转为新列?DataFrame数据重塑求助

问题:DataFrame 重塑与列移位实现需求

我有如下格式的DataFrame数据:

import pandas as pd

data = {
    'accident_type': [1,1,1,2,2,2,3,3,3],
    'office A': [0,0,0,0,0,0,0,0,0],
    'office B': [0,2,0,0,0,0,0,1,0],
    'office C': [0,2,0,1,1,0,0,1,0],
    'information': ['number','fatality','frequency','number','fatality','frequency','number','fatality','frequency']
}
df = pd.DataFrame(data)

原始数据预览:

accident_typeoffice Aoffice Boffice Cinformation
1000number
1022fatality
1000frequency
2001number
2001fatality
2000frequency
3000number
3011fatality
3000frequency

我希望实现两个核心操作:

  1. 新增列将事故信息值纵向移位,得到office列(对应office A/office B/office C循环)
  2. 删除原有的office A/office B/office C列,将这三列的值转换为number/fatality/frequency列,最终得到如下结果:
accident_typeinformationofficenumberfatalityfrequency
1numberoffice A000
1fatalityoffice B020
1frequencyoffice C020
2numberoffice A000
2fatalityoffice B000
2frequencyoffice C110
3numberoffice A000
3fatalityoffice B010
3frequencyoffice C010

我尝试使用df.melt但未得到预期结果,请问如何用Python实现该需求?


解决方案

这个需求的核心是给每个事故类型分组内的行分配对应office,再将原office列的值按信息类别重新映射,可以通过以下步骤实现:

步骤1:为每行分配对应的office列

观察到每个accident_type下固定有3行,正好对应office A/office B/office C,我们可以按事故类型分组后,给每组的行循环分配这三个值:

# 定义要循环的office列表
office_list = ['office A', 'office B', 'office C']
# 按accident_type分组,给每组的行按顺序分配office值
df['office'] = df.groupby('accident_type').cumcount().map(lambda x: office_list[x])

步骤2:构建office与信息值的映射表

我们需要把原数据中每个(事故类型, office)对应的number/fatality/frequency值提取出来,这里用pivot_table结合多层索引转置来实现:

# 先按事故类型和信息类型做透视,再转置索引得到office对应的各信息值
map_df = df.pivot_table(
    index=['accident_type', 'information'],
    values=['office A', 'office B', 'office C'],
    aggfunc='first'
).unstack('information').stack(0).reset_index()
# 调整列名到我们需要的格式
map_df.columns = ['accident_type', 'office', 'number', 'fatality', 'frequency']

步骤3:合并得到最终结果

最后把原始数据的information列和映射表合并,调整列顺序就得到目标格式:

# 保留原始数据的核心列
df_base = df[['accident_type', 'information', 'office']]
# 合并核心列和映射表
final_df = df_base.merge(map_df, on=['accident_type', 'office'])
# 调整列顺序和目标一致
final_df = final_df[['accident_type', 'information', 'office', 'number', 'fatality', 'frequency']]

完整简化版代码

把上面的逻辑整合起来,直接运行就能得到结果:

import pandas as pd

data = {
    'accident_type': [1,1,1,2,2,2,3,3,3],
    'office A': [0,0,0,0,0,0,0,0,0],
    'office B': [0,2,0,0,0,0,0,1,0],
    'office C': [0,2,0,1,1,0,0,1,0],
    'information': ['number','fatality','frequency','number','fatality','frequency','number','fatality','frequency']
}
df = pd.DataFrame(data)

# 1. 添加office列
office_list = ['office A', 'office B', 'office C']
df['office'] = df.groupby('accident_type').cumcount().map(dict(enumerate(office_list)))

# 2. 构建映射表
map_df = df.pivot_table(
    index=['accident_type', 'information'],
    values=['office A', 'office B', 'office C'],
    aggfunc='first'
).unstack('information').stack(0).reset_index()
map_df.columns = ['accident_type', 'office', 'number', 'fatality', 'frequency']

# 3. 合并得到最终结果
final_df = df[['accident_type', 'information', 'office']].merge(map_df, on=['accident_type', 'office'])
final_df = final_df[['accident_type', 'information', 'office', 'number', 'fatality', 'frequency']]

print(final_df)

这段代码的优势是利用pandas的内置函数处理索引和数据转置,避免了手动循环,效率更高也更易维护。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:42:34