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

使用Pandas按Class对表格进行部分逆透视的技术实现请求

使用Pandas实现部分逆透视(Partially Unpivot)操作

先明确下需求:我们需要把原始表格中按Class字段拆分的年份数据(2017、2018),合并到同一ID的行中,生成带Class后缀的年份列(比如2017A、2018B),同时保留ID、Class和Type字段。

原始数据表格

IDClassType20172018
12AANet17
12BAGrossNaN8
12ABNet39
12BBGross410
13AANet511
13CBNet65

期望结果表格

IDClassType2017A2018A2017B2018B
12AANet1739
12BAGrossNaN8410
13AANet511NaNNaN
13CBNetNaNNaN65

具体实现步骤(Pandas代码)

我把整个过程拆成了几个清晰的步骤,方便理解和调试:

1. 加载原始数据

首先我们把原始数据转换成Pandas的DataFrame:

import pandas as pd
import numpy as np

# 构造原始数据
raw_data = {
    'ID': ['12A', '12B', '12A', '12B', '13A', '13C'],
    'Class': ['A', 'A', 'B', 'B', 'A', 'B'],
    'Type': ['Net', 'Gross', 'Net', 'Gross', 'Net', 'Net'],
    '2017': [1, np.nan, 3, 4, 5, 6],
    '2018': [7, 8, 9, 10, 11, 5]
}
df = pd.DataFrame(raw_data)

2. 转换成长格式(Melt)

我们先把固定的年份列(2017、2018)转成长格式,这样方便后续和Class字段组合:

# 将年份列转为长格式,保留ID和Class作为标识
melted_df = df.melt(
    id_vars=['ID', 'Class'],
    value_vars=['2017', '2018'],
    var_name='Year',
    value_name='Value'
)

3. 生成新的年份- Class列名

把年份和Class拼接成目标中的新列名(比如2017A、2018B):

# 组合年份和Class,生成新的列名前缀
melted_df['Year_Class'] = melted_df['Year'] + melted_df['Class']

4. 透视回宽格式(Pivot)

现在把长格式的数据透视回宽格式,每个ID对应一行,新的年份- Class作为列:

# 透视成宽格式,ID作为唯一标识
pivoted_df = melted_df.pivot(
    index='ID',
    columns='Year_Class',
    values='Value'
).reset_index()

5. 合并元数据(Class、Type)

因为同一个ID的Type是唯一的,Class我们取该ID首次出现的值(和目标表格一致),把这些元数据合并到透视后的结果中:

# 获取每个ID对应的Class和Type(保留第一条记录的值)
id_metadata = df.drop_duplicates(subset='ID')[['ID', 'Class', 'Type']]

# 合并元数据和透视后的年份数据
final_df = pd.merge(id_metadata, pivoted_df, on='ID', how='left')

6. 调整列顺序

最后调整列的顺序,和期望结果完全匹配:

# 按目标表格的列顺序重新排列
final_df = final_df[['ID', 'Class', 'Type', '2017A', '2018A', '2017B', '2018B']]

# 查看结果
print(final_df)

运行这段代码后,你就能得到和期望完全一致的表格了。


内容的提问来源于stack exchange,提问作者S.Gu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:00:30