导读:本期聚焦于卡拉米创作的《Pandas中怎样实现数据的堆叠与解堆叠?stack与unstack用法详解》,敬请观看详情。数据堆叠就是把宽格式的表格压成长格式,解堆叠则相反,这两个操作是Pandas数据重塑的核心。stack函数会把列标签下压到行索引上,unstack则把行索引展开成新的列,两者互为逆过程。本文详细讲解stack和unstack的参数含义、多级索引下的表现、dropna参数的作用,以及pivot和melt等替代方案的适用场景,还给出透视表转换、缺失值处理等实际案例,帮助掌握灵活变换数据形态的技巧。

在处理表格数据时,我们经常需要在宽格式和长格式之间来回切换。比如一个按月份展开的销售明细表,做统计分析时希望它变成一行一条记录的长表,而画透视图时又希望它变回宽表。Pandas提供的stackunstack这对函数,就是专门解决这类形态转换问题的利器。它们的本质是操作索引层级,理解了这一点,数据重塑就不再是玄学。

Pandas中怎样实现数据的堆叠与解堆叠?stack与unstack用法详解

stack与unstack的基本原理

stack的中文含义是堆叠,它的作用是把列标签转变成最内层的行索引,相当于把横向排列的数据往纵向压。unstack则相反,把最内层的行索引提升为列标签,把纵向的数据摊开。两者互为逆操作,df.stack().unstack()通常能还原回原始结构。

先看一个最简单的例子。假设有这样一个DataFrame,行索引是城市,列是两个季度的销售额:

import pandas as pd

df = pd.DataFrame({
    'Q1': [100, 200, 150],
    'Q2': [120, 180, 170]
}, index=['北京', '上海', '广州'])

print(df)
#        Q1   Q2
# 北京  100  120
# 上海  200  180
# 广州  150  170

# 堆叠:列标签Q1、Q2变成行索引的第二层
stacked = df.stack()
print(stacked)
# 北京  Q1    100
#      Q2    120
# 上海  Q1    200
#      Q2    180
# 广州  Q1    150
#      Q2    170

可以看到,stack之后DataFrame变成了一个带有MultiIndex的Series,原来的列名Q1和Q2现在成了行索引的第二层。这种一行一条数值的形式,就是典型的长格式数据。再执行unstack就能还原:

# 解堆叠:把第二层行索引展开成列
restored = stacked.unstack()
print(restored)
#        Q1   Q2
# 北京  100  120
# 上海  200  180
# 广州  150  170

多级索引下的层级控制

当DataFrame本身带有多级索引时,stack和unstack操作哪一层就需要明确指定了。unstack的level参数默认是-1,也就是操作最内层的索引;stack的level参数默认是-1,操作最内层的列索引。level既可以是整数,也可以是索引的名称。

通过一个两层索引的例子来看层级切换的效果:

index = pd.MultiIndex.from_tuples(
    [('华东', '杭州'), ('华东', '苏州'), ('华北', '天津')],
    names=['大区', '城市']
)
df2 = pd.DataFrame({
    '2023年': [10, 20, 30],
    '2024年': [15, 25, 35]
}, index=index)

# 默认unstack最内层(城市)
print(df2.unstack())
#         2023年        2024年
# 城市     杭州  苏州  天津    杭州  苏州  天津
# 大区
# 华东     10   20  NaN    15   25  NaN
# 华北    NaN  NaN   30   NaN  NaN   35

# unstack外层(大区),传入层名或序号0
print(df2.unstack(level='大区'))
# 城市      2023年       2024年
# 大区     华东  华北      华东  华北
# 杭州     10  NaN      15  NaN
# 苏州     20  NaN      25  NaN
# 天津    NaN   30     NaN   35

注意unstack之后产生的缺失值。因为华东大区没有天津,华北大区没有杭州和苏州,展开后这些交叉位置自然就是NaN。这是unstack非常常见的副作用,实际使用时要考虑是否需要用fillna(0)之类的操作补齐。

dropna参数与缺失值的处理技巧

stack有一个容易被忽略的参数dropna,默认值为True,表示堆叠时自动丢弃全为NaN的数据,避免长格式里出现大量无意义的空行。如果原始DataFrame中本来就有NaN列,stack后这些数据会直接消失,需要特别留意。

df3 = pd.DataFrame({
    'A': [1, 2],
    'B': [3, 4],
    'C': [pd.NA, pd.NA]  # 全空列
}, index=['x', 'y'])

print(df3.stack())
# x  A    1
#    B    3
# y  A    2
#    B    4

# 保留NaN,C列的空值也会出现在结果里
print(df3.stack(dropna=False))
# x  A       1
#    B       3
#    C    <NA>
# y  A       2
#    B       4
#    C    <NA>

反过来,unstack产生的NaN在多数统计场景下没有意义,常见的处理方式是链式调用unstack(fill_value=0),unstack原生支持fill_value参数,比事后fillna效率更高,写法也更简洁。不过要注意,fill_value只能填充一个固定值,如果需要区分处理不同来源的缺失,还是要分步操作。

stack与pivot、melt的关系

Pandas中实现宽转长的函数不止stack一个,meltwide_to_long也能做类似的事情。它们的核心区别在于:stack基于索引层级操作,要求列标签结构规整;melt基于参数指定,灵活性更强,可以指定哪些列保持不动,哪些列被融化成两列。

df4 = pd.DataFrame({
    '城市': ['北京', '上海'],
    'Q1': [100, 200],
    'Q2': [120, 180]
})

# 用melt实现宽转长,城市列作为标识保留
long_df = df4.melt(id_vars=['城市'], var_name='季度', value_name='销售额')
print(long_df)
#   城市 季度  销售额
# 0 北京  Q1   100
# 1 上海  Q1   200
# 2 北京  Q2   120
# 3 上海  Q2   180

# 如果用stack,需要先把城市列先设为索引
long_by_stack = df4.set_index('城市').stack().reset_index()
long_by_stack.columns = ['城市', '季度', '销售额']

选择建议很简单:数据列名有规律、追求链式调用简洁性时用stack;列名不规则、只需要融化部分列时用melt。反向转换中,unstack适合配合MultiIndex使用,而pivot_table适合从普通长表直接重建宽表,并且自带聚合能力,遇到重复索引也不会报错。

掌握stack和unstack之后,配合groupbyagg可以实现很多一气呵成的分析流程。例如先按地区和月份分组求和,再unstack月份做同比对比,几行代码就能得到一张清晰的透视对比表,这也是它们在数据分析实战中最常见的用法。

Pandas stackunstack数据重塑修改时间:2026-09-03 12:16:57

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260903/49553.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。