
本文详细介绍了如何使用Pandas库对DataFrame进行高级重塑操作。我们将一个具有多级列索引(如岛屿和年份)以及月份作为行索引的DataFrame,转换成以岛屿名称作为行索引,并以合并后的月份和年份(例如“JAN2022”)作为单级列索引的新结构。核心步骤包括利用stack()进行堆叠、transpose()进行转置,以及Index.map()来扁平化和自定义列名,从而实现数据的灵活布局。
在数据分析和报告生成中,我们经常需要根据特定的分析需求来重塑Pandas DataFrame的结构。本教程将展示一个常见的重塑场景:如何将一个具有多级列索引(MultiIndex columns)和单级行索引的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()方法。
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是列索引。
DataFrame.transpose()(或简写.T)方法用于交换DataFrame的行和列。在我们的场景中,我们希望Island成为行索引,而Month和Year的组合成为列索引。
对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组成的多级索引。这已经非常接近我们的目标了。
最后一步是将多级列索引('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()、transpose() 和 Index.map(),我们可以灵活地将复杂的MultiIndex DataFrame重塑为满足特定分析和展示需求的结构。这种方法在处理时间序列数据、交叉表格数据或需要改变数据透视角度时尤其有用。
以上就是Pandas DataFrame高级重塑:将多级列索引转换为行索引与合并列名的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号