0

0

怎样用Python实现数据堆叠?stack与unstack方法

看不見的法師

看不見的法師

发布时间:2025-07-10 17:09:02

|

524人浏览过

|

来源于php中文网

原创

python中,数据堆叠与解堆叠的核心工具是pandas库的stack()和unstack()方法。1. stack()用于将列“堆叠”到行上,形成新的内层索引,适用于将宽格式数据转换为长格式;2. unstack()则相反,它将索引层级“解堆叠”到列上,常用于还原或转换长格式回宽格式。此外,stack()默认丢弃nan值,但可通过dropna=false保留,而unstack()可用fill_value参数填充缺失值。3. 其他相关工具包括melt()(快速融化多列为两列)、pivot_table()(带聚合功能的透视表)和pivot()(无聚合的简单透视),它们各有适用场景。掌握这些方法有助于灵活重塑数据结构以满足分析需求。

怎样用Python实现数据堆叠?stack与unstack方法

在Python中,实现数据堆叠(或称为数据透视、数据重塑)主要依赖Pandas库中的stack()unstack()方法。简单来说,stack()用于将DataFrame的列“堆叠”到行上,从而创建一个新的内层索引;而unstack()则相反,它将索引的某个层级“解堆叠”到列上。这两个操作在数据分析和准备阶段非常常见,它们能帮助我们灵活地转换数据的“宽”格式(wide format)和“长”格式(long format),以适应不同的分析或可视化需求。

怎样用Python实现数据堆叠?stack与unstack方法

解决方案

要实现数据的堆叠与解堆叠,我们首先需要一个Pandas DataFrame。我通常会先创建一个具有代表性的数据集,这样才能更好地演示这些方法的实际效果。

import pandas as pd
import numpy as np

# 创建一个示例DataFrame
# 模拟一些销售数据,包含地区、年份和不同产品的销售额
data = {
    '地区': ['华北', '华北', '华东', '华东', '华南', '华南'],
    '年份': [2022, 2023, 2022, 2023, 2022, 2023],
    '产品A销售额': [100, 120, 150, 130, 90, 110],
    '产品B销售额': [80, 95, 110, 105, 75, 88],
    '产品C销售额': [50, 60, 70, 65, 45, 55]
}
df = pd.DataFrame(data)

# 通常,为了使用stack/unstack,我们会先设置索引
# 比如,我们想按地区和年份来分析不同产品的销售额
df_indexed = df.set_index(['地区', '年份'])
print("原始DataFrame(已设置索引):")
print(df_indexed)

# --- 使用 stack() 方法 ---
# stack() 将DataFrame的列(这里是产品销售额)转换为行,
# 并在索引中创建一个新的内层级别。
# 默认情况下,它会堆叠所有非索引的列。
df_stacked = df_indexed.stack()
print("\n使用 stack() 后的DataFrame:")
print(df_stacked)
print(f"堆叠后数据的类型:{type(df_stacked)}") # 注意:堆叠后通常会变成Series,如果只剩一列数据的话

# 如果想保留DataFrame结构,或者有多个值列,可以这样操作
df_indexed_multi_cols = df.set_index(['地区', '年份'])
df_stacked_df = df_indexed_multi_cols.stack().to_frame(name='销售额')
print("\n使用 stack() 并转为DataFrame(多列):")
print(df_stacked_df)

# stack() 默认会丢弃NaN值。如果想保留NaN,可以使用 dropna=False
df_nan_test = pd.DataFrame({
    'A': [1, 2], 'B': [3, np.nan], 'C': [5, 6]
}, index=['X', 'Y'])
df_nan_test_stacked_default = df_nan_test.stack()
df_nan_test_stacked_keep_nan = df_nan_test.stack(dropna=False)
print("\nstack() 处理NaN (默认丢弃):")
print(df_nan_test_stacked_default)
print("\nstack() 处理NaN (保留NaN):")
print(df_nan_test_stacked_keep_nan)


# --- 使用 unstack() 方法 ---
# unstack() 是 stack() 的逆操作,它将索引的某个级别转换为列。
# 默认情况下,它会解堆叠最内层的索引。
df_unstacked = df_stacked.unstack()
print("\n使用 unstack() 后的DataFrame (还原到原始列结构):")
print(df_unstacked)

# unstack() 也可以指定要解堆叠的索引级别。
# 索引级别可以通过整数位置(从0开始)或名称来指定。
# 比如,将“年份”从索引解堆叠到列
df_unstacked_year = df_indexed.unstack(level='年份')
print("\n使用 unstack(level='年份') 后的DataFrame:")
print(df_unstacked_year)

# 甚至可以解堆叠多个级别,但结果会形成MultiIndex的列
df_unstacked_multi = df_stacked_df.unstack(level=['地区', '年份'])
print("\n使用 unstack(level=['地区', '年份']) 后的DataFrame:")
print(df_unstacked_multi)

# unstack() 处理NaN时,会用NaN填充。可以使用 fill_value 参数指定填充值
df_nan_test_unstacked_fill = df_nan_test_stacked_keep_nan.unstack(fill_value=0)
print("\nunstack() 处理NaN (使用 fill_value=0):")
print(df_nan_test_unstacked_fill)

为什么我们需要数据堆叠?理解其在数据分析中的核心价值

我经常发现,在处理真实世界的数据时,原始数据格式很少能直接满足所有分析或可视化需求。这就是stackunstack这类数据重塑工具显得如此重要的原因。它们的核心价值在于提供了一种灵活的方式来改变数据的“视角”或“粒度”。

立即学习Python免费学习笔记(深入)”;

怎样用Python实现数据堆叠?stack与unstack方法

想象一下,你有一份销售数据,每行代表一个地区和年份,而每列则代表不同产品的销售额(就像我们上面的df_indexed)。这种“宽”格式在录入数据时可能很方便,但在进行某些分析时却不那么直观。比如,你想比较所有产品在不同地区和年份的销售额趋势,或者想用Seaborn绘制一个条形图,其中每个条形代表一个产品的销售额,并按地区和年份分组。这时,数据就需要变成“长”格式,即每一行代表一个具体的销售事件(地区、年份、产品名称、销售额)。stack()就是实现这种转换的关键。它把“产品A销售额”、“产品B销售额”等列名变成了索引的一部分,而它们对应的值则统一归入一列,这大大简化了后续的聚合、过滤和绘图操作。

反过来,unstack()则用于将长格式数据恢复或转换为宽格式。比如,你可能从数据库中查询到的是长格式数据,但你希望将其转换为一个便于人类阅读的交叉表,或者为某些需要特定宽格式输入的模型准备数据。这时候,unstack()就能派上用场,它能将索引中的某个类别重新“摊开”到列上。我个人觉得,理解这两种操作,就是理解如何在数据“维度”之间灵活切换,这对于任何深入的数据分析工作都是基石。它不仅仅是语法上的操作,更是一种数据思维模式的体现。

怎样用Python实现数据堆叠?stack与unstack方法

stack与unstack的实战技巧:处理多级索引与缺失值

在实际应用中,stackunstack的强大之处往往体现在它们与Pandas的多级索引(MultiIndex)的结合上。很多时候,我们的数据本身就带有层级结构,或者在预处理后形成了多级索引。

stack()默认会操作DataFrame最外层的列名,将其转换为最内层的行索引。但如果你有一个多级列索引,或者想选择性地堆叠某些列,就需要更精细的控制。例如,如果我们有像('产品', 'A')这样的多级列名,stack()会把'产品'这一级堆叠起来。

聚蜂消防BeesFPD
聚蜂消防BeesFPD

关注消防领域的智慧云平台

下载

unstack()则默认操作最内层的行索引,将其转换为列。但通过level参数,你可以指定任何一个索引级别进行解堆叠,无论是通过其整数位置(从0开始)还是通过其名称。这在处理复杂的多级索引数据时尤其重要。比如,你可能有一个按['地区', '年份', '产品']三级索引的数据,你可能想把'产品'解堆叠到列上,或者把'年份'解堆叠到列上,这完全取决于你的分析目的。

# 示例:更复杂的多级索引处理
# 假设我们已经有了堆叠后的数据,并想进行不同方式的解堆叠
df_stacked_example = df_indexed.stack().to_frame(name='销售额')
print("\n用于演示多级索引解堆叠的DataFrame:")
print(df_stacked_example)

# 解堆叠最内层索引(默认行为,这里是产品名称,因为它在stack后成了最内层)
df_unstacked_default = df_stacked_example.unstack()
print("\n解堆叠最内层索引(产品名称):")
print(df_unstacked_default)

# 解堆叠 '年份' 级别
df_unstacked_year_level = df_stacked_example.unstack(level='年份')
print("\n解堆叠 '年份' 级别:")
print(df_unstacked_year_level)

# 解堆叠 '地区' 级别
df_unstacked_region_level = df_stacked_example.unstack(level='地区')
print("\n解堆叠 '地区' 级别:")
print(df_unstacked_region_level)

至于缺失值,这是一个非常实际的问题。stack()的默认行为是丢弃任何包含NaN的行(如果这些NaN是在被堆叠的列中)。这通常是合理的,因为你可能不希望堆叠“空”的数据点。但如果你的分析需要保留这些缺失信息,那么dropna=False参数就显得非常重要了。而unstack()在遇到缺失值时,会用NaN填充。这也很合理,因为当某个组合在原始数据中不存在时,解堆叠后自然会形成一个空洞。此时,fill_value参数就提供了灵活性,你可以用0、空字符串或其他任何值来替代这些NaN,这对于后续的数据处理或可视化可能很有用。我常常会根据下游任务来决定是否保留NaN或如何填充它们。

除了stack和unstack,还有哪些数据重塑工具?它们与堆叠操作有何异同?

Pandas提供了不止stackunstack来重塑数据,还有meltpivot_tablepivot等。理解它们之间的异同,能帮助你在不同的场景下选择最合适的工具。

  • melt(): 这个方法通常用于将“宽”格式数据转换为“长”格式,与stack()有相似之处,但侧重点不同。melt()更适合当你有一组“标识符变量”(id_vars)和一组“值变量”(value_vars)时,你想把所有“值变量”列聚合到一个新的“变量”列和一个新的“值”列中。它不需要你预先设置MultiIndex。

    • 异同: melt()更像是stack()的简化版,尤其适用于那些没有多级索引,只是想把几列数据“融化”成两列(变量名和变量值)的场景。stack()则更专注于将现有的列名转化为索引的一部分,它更擅长处理已经有或将要形成MultiIndex的数据。我个人觉得,如果数据结构比较简单,melt往往比stack更直观。
  • pivot_table(): 这是一个非常强大的工具,用于创建电子表格风格的透视表。它不仅能重塑数据(将某些列作为索引,某些列作为列,某个列作为值),还能同时进行数据聚合(如求和、平均值、计数等)。

    • 异同: pivot_table()unstack()功能更丰富,因为它集成了聚合功能。unstack()仅仅是改变索引和列的结构,不进行任何聚合。如果你需要对数据进行汇总并同时重塑,pivot_table()是首选。如果仅仅是想改变数据的“形状”而不涉及聚合,那么stack/unstackpivot可能更直接。
  • pivot(): pivot()类似于pivot_table(),但它更简单,不具备聚合功能。它要求你指定一个索引列、一个列名列和一个值列。如果存在重复的索引-列组合,pivot()会报错,因为它无法处理重复值(不像pivot_table会默认聚合)。

    • 异同: pivot()可以看作是unstack()的特定场景替代品,特别是当你不想预先设置索引,而是直接通过列名来指定新的索引和列时。但它的限制在于,如果目标透视表中出现重复的索引-列组合,它就无法工作。而unstack()则是在已有的MultiIndex上进行操作,它能更好地处理这些情况。

总结来说,这些工具各有侧重。stackunstack是处理多级索引和在宽/长格式之间精确转换的利器;melt是快速将多列“融化”为两列的便捷方式;而pivot_tablepivot则更侧重于创建交叉表,其中pivot_table还提供了强大的聚合功能。在实际工作中,我发现自己经常会根据数据的原始形态和最终分析目标,灵活地组合使用这些方法。没有绝对的“最好”,只有“最适合”。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

753

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

636

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

758

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

618

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1262

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

577

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

707

2023.08.11

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

0

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.7万人学习

Django 教程
Django 教程

共28课时 | 3.1万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号