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

如何将按年份分多列的Pandas DataFrame转换为含年份列与值列的单列结构?

最优方法转换宽格式DataFrame为长格式

看起来你可能在表述期望输出时有点小混淆——重复的列名(a、b、c、d重复两次)在Pandas DataFrame里是不推荐的,而且结合你提到的年份列和值列的需求,你真正想要的应该是一个长格式的DataFrame,每行对应一个「类别(a/b/c/d)-年份」的组合,包含年份、类别、值三个列。

先明确你的输入DataFrame结构,应该是这样的:

import pandas as pd

# 输入的宽格式DataFrame
df_wide = pd.DataFrame({
    '年份': [2015, 2016],
    'a': [1, 5],
    'b': [2, 6],
    'c': [3, 7],
    'd': [4, 8]
})

下面两种方法都是比for循环高效得多的矢量化操作,完全满足你的需求:

方法1:用melt函数(直观易读)

melt是Pandas专门为宽转长设计的函数,只需要指定作为标识符的列(这里是年份),然后把其他列转成「变量-值」对:

df_long = df_wide.melt(
    id_vars='年份',       # 保留作为标识符的列
    var_name='类别',     # 原列名(a/b/c/d)对应的新列名
    value_name='值'      # 原列值对应的新列名
)

# 按年份排序,匹配你要的输出顺序(2015的a-d在前,2016在后)
df_long = df_long.sort_values('年份').reset_index(drop=True)

最终输出的df_long就是:

年份类别值
02015a1
12015b2
22015c3
32015d4
42016a5
52016b6
62016c7
72016d8

方法2:用stack方法(性能更优)

如果把年份设为索引,stack可以快速把列转成行,适合处理大数据集:

# 先将年份设为索引
df_indexed = df_wide.set_index('年份')
# stack转长格式,然后重置索引并命名列
df_long = df_indexed.stack().reset_index()
df_long.columns = ['年份', '类别', '值']

# 同样按年份排序
df_long = df_long.sort_values('年份').reset_index(drop=True)

为什么这两种方法比for循环好?

  • 性能更高:Pandas的melt和stack都是底层用C实现的矢量化操作,避免了Python层面的循环开销,数据量越大,优势越明显。
  • 代码更简洁:一行/几行代码就能完成转换,可读性和可维护性远高于for循环。
  • 更符合Pandas idiom:这是Pandas处理宽转长场景的标准做法,团队里其他熟悉Pandas的开发者一眼就能看懂。

如果你之前用melt没得到预期结果,大概率是没正确设置参数或者没做排序调整,按上面的代码应该就能解决问题。


内容的提问来源于stack exchange,提问作者Enrique Ortiz de Zárate

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 19:32:31