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

如何用Pandas的stack和melt转换指定DataFrame格式?

嘿,这事儿用Pandas处理起来很直接,我给你两种方法,一种拆分合并(直观好懂),另一种用专业函数(简洁高效),都能得到你要的长格式结果。

首先先确认原数据的构造(方便复现):

import pandas as pd

a = {'pk': 1, 'pk_name':'p1', 'c1':1, 'c1_val': 1, 'c1_val2': 1, 'c2':0, 'c2_val': 0, 'c2_val2': 1}
b = {'pk': 2, 'pk_name':'p2', 'c1':0, 'c1_val': 1, 'c1_val2': 1, 'c2':0, 'c2_val': 0, 'c2_val2': 1}
c = {'pk': 3, 'pk_name':'p3', 'c1':0, 'c1_val': 1, 'c1_val2': 1, 'c2':0, 'c2_val': 0, 'c2_val2': 1}
d = {'pk': 4, 'pk_name':'p4', 'c1':1, 'c1_val': 1, 'c1_val2': 1, 'c2':0, 'c2_val': 0, 'c2_val2': 1}
e = {'pk': 5, 'pk_name':'p5', 'c1':1, 'c1_val': 1, 'c1_val2': 1, 'c2':0, 'c2_val': 0, 'c2_val2': 1}
df = pd.DataFrame([a, b, c, d, e])

方法一:拆分后合并(新手友好)

我们可以把原DataFrame拆成c1相关列和c2相关列两部分,分别重命名列名后合并:

# 提取c1组列并重命名
df_c1 = df[['pk', 'pk_name', 'c1', 'c1_val', 'c1_val2']].rename(
    columns={'c1': 'c', 'c1_val': 'val', 'c1_val2': 'val2'}
)

# 提取c2组列并重命名
df_c2 = df[['pk', 'pk_name', 'c2', 'c2_val', 'c2_val2']].rename(
    columns={'c2': 'c', 'c2_val': 'val', 'c2_val2': 'val2'}
)

# 合并两组数据,重置索引得到最终结果
result = pd.concat([df_c1, df_c2], ignore_index=True)

运行后result就是你要的结构:

pk pk_name  c  val  val2
0   1      p1  1    1     1
1   2      p2  0    1     1
2   3      p3  0    1     1
3   4      p4  1    1     1
4   5      p5  1    1     1
5   1      p1  0    0     1
6   2      p2  0    0     1
7   3      p3  0    0     1
8   4      p4  0    0     1
9   5      p5  0    0     1

方法二:使用wide_to_long函数(专业高效)

如果后续有更多类似c3、c4的列,用Pandas自带的wide_to_long更省心,它专门处理这种带前缀的宽格式转长格式:

# 先调整列名格式,让函数能识别分组逻辑
df_renamed = df.rename(columns=lambda x: x.replace('c1', 'c_1').replace('c2', 'c_2'))
df_renamed = df_renamed.rename(columns=lambda x: x.replace('c_1_val', 'val_1').replace('c_2_val', 'val_2'))
df_renamed = df_renamed.rename(columns=lambda x: x.replace('c_1_val2', 'val2_1').replace('c_2_val2', 'val2_2'))

# 执行格式转换
result = pd.wide_to_long(
    df_renamed,
    stubnames=['c', 'val', 'val2'],
    i=['pk', 'pk_name'],
    j='group',
    sep='_'
).reset_index(drop=False)

# 不需要分组标识的话可以删掉该列
result = result.drop('group', axis=1)

这个方法同样能得到完全一致的结果,适合列数量较多的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 07:52:40