0

0

Pandas DataFrame高级重塑:将多级列索引转换为行索引与合并列名

DDD

DDD

发布时间:2025-11-10 11:16:55

|

505人浏览过

|

来源于php中文网

原创

pandas dataframe高级重塑:将多级列索引转换为行索引与合并列名

本文详细介绍了如何使用Pandas库对DataFrame进行高级重塑操作。我们将一个具有多级列索引(如岛屿和年份)以及月份作为行索引的DataFrame,转换成以岛屿名称作为行索引,并以合并后的月份和年份(例如“JAN2022”)作为单级列索引的新结构。核心步骤包括利用stack()进行堆叠、transpose()进行转置,以及Index.map()来扁平化和自定义列名,从而实现数据的灵活布局。

在数据分析和报告生成中,我们经常需要根据特定的分析需求来重塑Pandas DataFrame的结构。本教程将展示一个常见的重塑场景:如何将一个具有多级列索引(MultiIndex columns)和单级行索引的DataFrame,转换为一个以原始DataFrame的某个列级别作为新的行索引,并将其余索引级别合并为新的单级列索引的DataFrame。

初始DataFrame结构

假设我们有一个DataFrame,其结构如下所示。它包含了不同岛屿(St Thomas, St. Croix)在不同年份(2022, 2023)的月度数据,月份作为行索引。

Island St Thomas         St. Croix        
Year        2022    2023      2022    2023
Month                                     
JAN       55,086  60,470    11,550  12,755
FEB       57,929  56,826    12,441  13,289
MAR       72,103  64,249    14,094  15,880
APR       67,469  56,321    12,196  13,092
MAY       60,092  49,534    13,385  16,497
JUN       67,026  56,950    14,009  15,728
JUL       66,353  61,110    13,768  16,879
AUG       50,660  42,745    10,673  12,102
SEP       24,507  25,047     6,826   6,298
OCT       34,025  34,462    10,351   9,398
NOV       44,500     NaN     9,635     NaN
DEC       58,735     NaN    12,661     NaN

我们的目标是将此DataFrame转换为一个具有两行(分别代表“St Thomas”和“St. Croix”)和24列(例如“JAN2022”、“FEB2022”等)的结构。

核心重塑操作

为了实现上述目标,我们将利用Pandas的stack()、transpose()(或其简写.T)以及Index.map()方法。

1. 使用 stack() 堆叠最内层列索引

DataFrame.stack()方法用于将DataFrame的“宽”格式转换为“长”格式。它将DataFrame的列(或指定级别)“堆叠”到行索引上,从而产生一个Series或一个具有MultiIndex行的新DataFrame。

在这个例子中,我们的列索引是('Island', 'Year')的多级索引。默认情况下,stack()会堆叠最内层(即Year)的列索引。执行df.stack()后,Year级别将从列索引移动到行索引,与原有的Month索引形成一个MultiIndex行。

# 假设df是上面描述的初始DataFrame
# df = ... (通过前置代码生成)

# 堆叠最内层列索引 'Year'
stacked_df = df.stack()
print("--- After stack() ---")
print(stacked_df)

此时,stacked_df的结构将是:

Island         St Thomas St. Croix
Month Year                        
JAN   2022        55,086    11,550
      2023        60,470    12,755
FEB   2022        57,929    12,441
      2023        56,826    13,289
...
DEC   2022        58,735    12,661

现在,Month和Year是行索引,而Island是列索引。

2. 使用 transpose() 转置DataFrame

DataFrame.transpose()(或简写.T)方法用于交换DataFrame的行和列。在我们的场景中,我们希望Island成为行索引,而Month和Year的组合成为列索引。

ModelGate
ModelGate

一站式AI模型管理与调用工具

下载

对stacked_df执行转置操作:

transposed_df = stacked_df.T
print("\n--- After transpose() ---")
print(transposed_df)

转置后的transposed_df将具有以下结构:

Month     JAN            FEB            MAR       ... NOV     DEC    
Year     2022    2023   2022    2023   2022    2023 ... 2022    2022   
Island                                            ...                
St Thomas  55,086  60,470  57,929  56,826  72,103  64,249 ...  44,500  58,735
St. Croix  11,550  12,755  12,441  13,289  14,094  15,880 ...   9,635  12,661

现在,Island成为了行索引,而列索引是Month和Year组成的多级索引。这已经非常接近我们的目标了。

3. 使用 Index.map() 扁平化和自定义列名

最后一步是将多级列索引('Month', 'Year')扁平化为单个字符串,例如“JAN2022”。我们可以通过Index.map()方法,结合一个lambda函数来实现这一点。

Index.map()允许我们对索引中的每个元素应用一个函数,并返回一个新的索引。对于一个MultiIndex,每个元素是一个元组(例如 ('JAN', '2022'))。

# 扁平化列索引
transposed_df.columns = transposed_df.columns.map(lambda x: f'{x[0]}{x[1]}')

# 或者使用更简洁的方式
# transposed_df.columns = map(''.join, transposed_df.columns)

out = transposed_df
print("\n--- Final Output ---")
print(out)

最终输出的DataFrame out 将符合我们的要求:

          JAN2022 JAN2023 FEB2022 FEB2023 MAR2022 MAR2023 APR2022 APR2023 MAY2022 MAY2023 JUN2022 JUN2023 JUL2022 JUL2023 AUG2022 AUG2023 SEP2022 SEP2023 OCT2022 OCT2023 NOV2022 DEC2022
Island                                                                                                                                                                                   
St Thomas  55,086  60,470  57,929  56,826  72,103  64,249  67,469  56,321  60,092  49,534  67,026  56,950  66,353  61,110  50,660  42,745  24,507  25,047  34,025  34,462  44,500  58,735
St. Croix  11,550  12,755  12,441  13,289  14,094  15,880  12,196  13,092  13,385  16,497  14,009  15,728  13,768  16,879  10,673  12,102   6,826   6,298  10,351   9,398   9,635  12,661

完整代码示例

为了演示的完整性,下面提供了生成初始DataFrame并执行重塑操作的完整代码:

import pandas as pd
import tabula

# --- 原始DataFrame的生成代码 (来自问题描述) ---
page_number = "1"
pdf_url = "https://usviber.org/wp-content/uploads/2023/12/A23-OCT.pdf"

tables = tabula.read_pdf(pdf_url, pages=page_number)
df = tables[1]

numeric_columns = df.select_dtypes(include=["number"])
df = df.drop(numeric_columns.columns[(numeric_columns < 0).any()], axis=1)
df = df.loc[2:13, :].iloc[:, :5]

df.set_index(df.columns[0], inplace=True)

df.columns = pd.MultiIndex.from_product(
    [["St Thomas", "St. Croix"], ["2022", "2023"]], names=["Island", "Year"]
)

df.index = df.index.map(lambda x: str(x).upper()[:3])
df.index.set_names("Month", inplace=True)

print("--- Initial DataFrame ---")
print(df)

# --- 重塑操作 ---
# 1. 堆叠最内层列索引 'Year'
stacked_df = df.stack()

# 2. 转置DataFrame,使'Island'成为行索引
transposed_df = stacked_df.T

# 3. 扁平化多级列索引,合并'Month'和'Year'
transposed_df.columns = transposed_df.columns.map(lambda x: f'{x[0]}{x[1]}')

# 最终结果
out = transposed_df
print("\n--- Final Reshaped DataFrame ---")
print(out)

注意事项与总结

  • stack() 的层级控制:stack() 默认会堆叠最内层的列索引。如果需要堆叠特定层级的列索引,可以使用 stack(level=...) 参数。
  • unstack() 的反向操作:unstack() 是 stack() 的逆操作,它将行索引的某个级别转换为列索引。
  • 处理 NaN 值:在重塑过程中,如果原始数据包含 NaN 值,这些 NaN 值会保留在重塑后的DataFrame中。在某些情况下,你可能需要在重塑前后进行缺失值处理(例如填充、删除)。
  • 索引命名:在整个过程中,保持索引和列的良好命名习惯(通过 set_names())有助于代码的可读性和可维护性。
  • 灵活性:stack(), transpose(), unstack(), pivot_table(), melt() 等Pandas函数提供了强大的数据重塑能力,理解它们的工作原理对于高效处理复杂数据结构至关重要。

通过结合使用 stack()、transpose() 和 Index.map(),我们可以灵活地将复杂的MultiIndex DataFrame重塑为满足特定分析和展示需求的结构。这种方法在处理时间序列数据、交叉表格数据或需要改变数据透视角度时尤其有用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

80

2025.12.04

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

33

2026.01.31

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1568

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1204

2024.04.29

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.6万人学习

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

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