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

心靈之曲
发布: 2025-11-24 13:43:27
原创
275人浏览过

将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)
登录后复制

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

         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将其重新组织为所需的结构。

AI TransPDF
AI TransPDF

高效准确地将PDF文档翻译成多种语言的AI智能PDF文档翻译工具

AI TransPDF 231
查看详情 AI TransPDF
  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数据重塑技术,将使您能够更有效地组织和分析数据,为后续的数据探索、建模和可视化奠定坚实基础。

以上就是将Pandas DataFrame中的多列堆叠重塑为规范化格式的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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