0

0

将Pandas DataFrame中的多列堆叠重塑为规范化格式

心靈之曲

心靈之曲

发布时间:2025-11-24 13:43:27

|

305人浏览过

|

来源于php中文网

原创

将pandas dataframe中的多列堆叠重塑为规范化格式

本文旨在深入探讨如何利用Pandas库对DataFrame进行多列堆叠和重塑操作,以实现从宽格式到长格式的转换。我们将介绍三种主要方法:基于MultiIndex的自定义重塑、结合`melt`和`pivot`函数,以及使用`janitor`库中的`pivot_longer`功能。通过示例代码和详细解释,读者将掌握在处理具有特定命名模式(如`*_count`, `*_sum`)的列时,如何高效地将数据结构化,从而提升数据分析的灵活性和可读性。

在数据分析和处理中,我们经常会遇到需要将DataFrame从“宽”格式转换为“长”格式的场景。这种转换对于数据可视化、统计分析以及与特定工具集成至关重要。特别是当DataFrame中的列名遵循某种模式,例如side_metric(如left_count,right_sum),我们希望将这些模式分解,并将side和metric作为新的列。

考虑以下初始DataFrame,它包含日期、其他标识符以及左右两侧的计数和总和数据:

import pandas as pd

df = pd.DataFrame({
    'date': ['2023-12-01', '2023-12-05', '2023-12-07'],
    'other_col': ['a', 'b', 'c'],
    'right_count': [4, 7, 9],
    'right_sum': [2, 3, 5],
    'left_count': [1, 8, 5],
    'left_sum': [0, 8, 4]
})

print("原始DataFrame:")
print(df)

原始DataFrame结构如下:

         date other_col  right_count  right_sum  left_count  left_sum
0  2023-12-01         a            4          2           1         0
1  2023-12-05         b            7          3           8         8
2  2023-12-07         c            9          5           5         4

我们的目标是将其重塑为以下“长”格式,其中side列表示“left”或“right”,count和sum则作为单独的度量列:

         date other_col   side  count  sum
0  2023-12-01         a  right      4    2
1  2023-12-05         b  right      7    3
2  2023-12-07         c  right      9    5
3  2023-12-01         a   left      1    0
4  2023-12-05         b   left      8    8
5  2023-12-07         c   left      5    4

下面将介绍几种实现此目标的方法。

方法一:利用MultiIndex进行自定义重塑

这种方法通过创建临时的MultiIndex列来实现灵活的数据重塑,步骤相对复杂但非常灵活。

  1. 设置索引: 首先,将不需要堆叠的列(如date, other_col)设置为DataFrame的索引。
  2. 创建MultiIndex列: 使用columns.str.split('_', expand=True)将列名(如right_count)拆分为多级索引(right, count)。
  3. 重命名轴: rename_axis(columns=['side', None])为新的多级列索引的第一级命名为side,第二级保持匿名。
  4. 堆叠: stack('side')将名为side的列索引级别转换为行索引。
  5. 重置索引: reset_index()将所有索引级别转换回普通列。
out_multiindex = (df
    .set_index(['date', 'other_col'])
    .pipe(lambda x: x.set_axis(x.columns.str.split('_', expand=True), axis=1))
    .rename_axis(columns=['side', None])
    .stack('side')
    .reset_index()
)

print("\n方法一:MultiIndex重塑结果")
print(out_multiindex)

输出示例(顺序可能不同):

Jenni AI
Jenni AI

使用最先进的 AI 写作助手为您的写作增光添彩。

下载
         date other_col   side  count  sum
0  2023-12-01         a   left      1    0
1  2023-12-01         a  right      4    2
2  2023-12-05         b   left      8    8
3  2023-12-05         b  right      7    3
4  2023-12-07         c   left      5    4
5  2023-12-07         c  right      9    5

方法二:结合melt和pivot函数

这种方法分两步进行:首先使用melt将宽格式数据“融化”为长格式,然后使用pivot将其重新组织为所需的结构。

  1. melt操作: df.melt(['date', 'other_col'], var_name='side')将除date和other_col之外的所有列转换为两列:side(包含原始列名)和value(包含对应的值)。
  2. 拆分列名: tmp['side'].str.split('_', n=1, expand=True)将side列中的原始列名(如right_count)拆分为side和col两部分。
  3. pivot操作: tmp.pivot(...)根据date, other_col, side作为新索引,col作为新列,value作为对应值进行透视。
  4. 清理: reset_index().rename_axis(columns=None)重置索引并清理透视产生的列名轴。
tmp = df.melt(['date', 'other_col'], var_name='temp_col_name')
tmp[['side', 'col']] = tmp['temp_col_name'].str.split('_', n=1, expand=True)

out_melt_pivot = (tmp.pivot(index=['date', 'other_col', 'side'],
                            columns='col', values='value')
                     .reset_index()
                     .rename_axis(columns=None)
)

print("\n方法二:melt + pivot重塑结果")
print(out_melt_pivot)

输出示例(顺序可能不同):

         date other_col   side  count  sum
0  2023-12-01         a   left      1    0
1  2023-12-01         a  right      4    2
2  2023-12-05         b   left      8    8
3  2023-12-05         b  right      7    3
4  2023-12-07         c   left      5    4
5  2023-12-07         c  right      9    5

方法三:使用janitor库的pivot_longer

janitor是一个强大的Python库,提供了许多便捷的数据清洗和处理功能,其中包括pivot_longer,它旨在简化类似R语言tidyr包中的pivot_longer操作。这种方法通常更简洁、易读。

首先,确保安装了pyjanitor库:

pip install pyjanitor

然后,导入并使用pivot_longer:

import janitor

out_janitor = df.pivot_longer(
    index=['date', 'other_col'],
    names_to=('side', '.value'),
    names_pattern=r'([^_]+)_([^_]+)'
)

print("\n方法三:janitor.pivot_longer重塑结果")
print(out_janitor)

关键参数解释:

  • index: 指定作为新DataFrame索引的列(不参与堆叠的列)。
  • names_to: 一个元组,用于指定如何将原始列名解析为新的列。
    • 'side':匹配正则表达式捕获组中的第一个部分,并将其命名为side列。
    • '.value':一个特殊关键字,表示匹配正则表达式捕获组中的剩余部分,并将其作为新的列名(如count和sum)。
  • names_pattern: 一个正则表达式,用于从原始列名中提取信息。r'([^_]+)_([^_]+)'表示匹配一个或多个非下划线字符(第一个捕获组),后跟一个下划线,再后跟一个或多个非下划线字符(第二个捕获组)。

输出示例:

         date other_col   side  count  sum
0  2023-12-01         a  right      4    2
1  2023-12-05         b  right      7    3
2  2023-12-07         c  right      9      5
3  2023-12-01         a   left      1    0
4  2023-12-05         b   left      8    8
5  2023-12-07         c   left      5    4

总结与注意事项

  • 选择方法:
    • MultiIndex方法:提供最大的灵活性,适用于列名模式复杂或需要精细控制中间步骤的场景。但代码可读性相对较低。
    • melt + pivot方法:是Pandas内置的经典重塑组合,逻辑清晰,适用于大多数通用场景。理解melt和pivot的工作原理是掌握Pandas数据重塑的关键。
    • janitor.pivot_longer方法:对于有规律的列名模式,此方法最为简洁和直观,大大提高了代码的可读性和编写效率。强烈推荐在日常数据处理中使用。
  • 性能考量: 对于非常大的DataFrame,不同的重塑方法可能在性能上有所差异。通常,Pandas的内置函数经过高度优化,而外部库如janitor也会利用这些优化。在极端性能敏感的场景下,可以进行基准测试。
  • 列名模式: 所有方法都依赖于对原始列名模式的理解和解析。确保正则表达式(在janitor方法中)或str.split(在Pandas内置方法中)能够准确地从列名中提取所需的部分。
  • 数据类型: 重塑操作可能会改变列的数据类型,特别是当melt操作将不同类型的列值合并到value列时。在后续分析前,可能需要进行数据类型转换。

掌握这些Pandas数据重塑技术,将使您能够更有效地组织和分析数据,为后续的数据探索、建模和可视化奠定坚实基础。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

530

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

258

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

765

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

219

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

356

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

244

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

546

2023.12.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

4

2026.03.05

热门下载

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

精品课程

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

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.8万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.8万人学习

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

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