Pandas如何将宽表DataFrame转为mmm yyyy单索引单列长表
Pandas宽表转指定格式单列长表实现方法
问题说明
现有结构化DataFrame对象df:
- 行索引为年份
- 列名为1-12月的三字母缩写(
Jan至Dec) - 单元格存储对应年月的数值,结构示例如下:
Jan Feb Mar Apr ... Aug Sep Oct Nov Dec 2021 0.852144 0.406946 0.067136 0.686585 ... 0.839023 0.803384 0.506883 0.829171 0.214810 2022 0.442388 0.296960 0.751213 0.690898 ... 0.701342 0.924836 0.534601 0.601725 0.673403
需要将其重构为单列结构:
- 所有数据按年月先后顺序逐行排列
- 每行索引为
mmm yyyy格式(如Jan 2021)
目标效果如下:
0 Jan 2021 0.852144 Feb 2021 0.406945 Mar 2021 0.067136 Apr 2021 0.686585 ... ... Aug 2022 0.701342 Sep 2022 0.924836 Oct 2022 0.534601 Nov 2022 0.601725 Dec 2022 0.673403
原尝试代码:
df = df.unstack().to_frame().T.sort_index(0,1).T
存在两个核心问题:
- 输出为
(月份, 年份)格式的多级索引,同月份下仅首行显示月份名称,其余年份行不重复显示月份 - 排序逻辑为优先按月份分组、同月份下再按年份排序,不符合先按年份、再按月份的时序排列要求
错误输出示例:
0 Jan 2021 0.852144 2022 0.442388 Feb 2021 0.406946 2022 0.296960 ...
正确实现代码
推荐使用stack实现,逻辑更简洁,天然符合年-月的索引顺序:
# 1. 堆叠宽表为二级索引序列,索引层级为(年份, 月份),默认已按年、月顺序排序 stacked_series = df.stack() # 2. 将二级索引拼接为要求的"mmm yyyy"格式字符串,替换原有索引 stacked_series.index = [f"{month} {year}" for year, month in stacked_series.index] # 3. 转换为单列DataFrame即为最终结果 result = stacked_series.to_frame()
如果要基于原unstack逻辑修正,只需调整索引层级顺序后再拼接即可:
stacked_series = df.unstack() # 交换索引层级为(年份, 月份),按时序排序 stacked_series = stacked_series.swaplevel().sort_index() # 拼接索引后转DataFrame stacked_series.index = [f"{month} {year}" for year, month in stacked_series.index] result = stacked_series.to_frame()
运行后输出结果与目标格式完全一致,索引为完整的mmm yyyy字符串,数据按2021年1-12月、2022年1-12月的时序排列。
内容的提问来源于stack exchange,提问作者Stacey
相关产品推荐
相关产品推荐

