0

0

Pandas DataFrame多列堆叠与重塑技巧

聖光之護

聖光之護

发布时间:2025-11-18 14:18:07

|

633人浏览过

|

来源于php中文网

原创

Pandas DataFrame多列堆叠与重塑技巧

本文将深入探讨在pandas dataframe中将多对相关列(如`right_count`, `right_sum`, `left_count`, `left_sum`)高效重塑为更紧凑长格式(如`side`, `count`, `sum`)的多种方法。我们将介绍基于multiindex和`stack`的自定义重塑、结合`melt`和`pivot`的经典方案,以及利用`janitor`库中`pivot_longer`函数的简洁实现,旨在提供清晰、专业的教程,帮助读者根据具体场景选择最合适的重塑策略。

在数据分析和处理中,我们经常需要将宽格式(wide format)的DataFrame转换为长格式(long format),以便于后续的聚合分析或可视化。特别是当多组相关数据分散在多个列中时,例如本例中的right_count, right_sum和left_count, left_sum,将其重塑为包含“侧边”(side)、“计数”(count)和“总和”(sum)等新列的长格式,能显著提高数据的可读性和可用性。

示例数据准备

首先,我们定义一个初始的Pandas 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)

我们的目标是将right_count, right_sum, left_count, left_sum这四列重塑为side、count和sum三列,同时保留date和other_col作为标识符。

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

这种方法通过巧妙地创建多级列索引(MultiIndex),然后使用stack操作将特定级别的索引转换为新的行,从而实现数据的重塑。

# 方法一:利用MultiIndex和stack进行自定义重塑
out_multiindex = (df
                  .set_index(['date', 'other_col']) # 将不变的列设为索引
                  # 将列名 'side_value' (如 'right_count') 拆分为多级索引 ('side', 'value')
                  .pipe(lambda x: x.set_axis(x.columns.str.split('_', expand=True), axis=1))
                  .rename_axis(columns=['side', None]) # 命名多级索引的级别,'side' 为第一个级别,第二个级别不命名
                  .stack('side') # 堆叠 'side' 级别的索引,将其转换为行
                  .reset_index() # 将所有索引(包括新生成的 'side')转换回普通列
                 )

print("\n方法一结果 (MultiIndex + stack):")
print(out_multiindex)

解析:

  1. set_index(['date', 'other_col']): 将date和other_col设置为DataFrame的索引,这些列在重塑过程中将保持不变。
  2. pipe(lambda x: x.set_axis(x.columns.str.split('_', expand=True), axis=1)): 这是一个关键步骤。它将原始的列名(如right_count)通过下划线_分割,并使用expand=True创建一个新的MultiIndex作为列索引。例如,right_count会变成('right', 'count')。
  3. rename_axis(columns=['side', None]): 命名新创建的多级列索引的级别。第一个级别被命名为'side',第二个级别(如count或sum)保持匿名(None)。
  4. stack('side'): 这是重塑的核心。它将名为'side'的列索引级别从列堆叠到行中,从而将宽格式数据转换为长格式。
  5. reset_index(): 将所有索引(包括原始的date, other_col以及新生成的side)转换回普通的列,并清除可能由stack操作产生的额外索引名称。

方法二:结合melt和pivot实现重塑

这种方法是Pandas中处理宽长格式转换的经典组合,通过melt操作将多列“融化”为两列(变量名和值),然后通过字符串处理提取信息,最后使用pivot进行重塑。

# 方法二:结合melt和pivot实现重塑
tmp = df.melt(['date', 'other_col'], var_name='temp_col') # 先融化所有需要重塑的列
# 从新的列名 'temp_col' 中拆分出 'side' 和 'col' (如 'count' 或 'sum')
tmp[['side', 'col']] = tmp['temp_col'].str.split('_', n=1, expand=True)

out_melt_pivot = (tmp.pivot(index=['date', 'other_col', 'side'], # 设置新的行索引
                            columns='col', values='value') # 根据 'col' 进行透视,将 'value' 填充
                  .reset_index() # 将索引转换回列
                  .rename_axis(columns=None) # 清除透视产生的列名索引(默认为 'col')
                 )

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

解析:

  1. df.melt(['date', 'other_col'], var_name='temp_col'): melt函数用于将DataFrame从宽格式转换为长格式。id_vars参数指定了不进行重塑的标识符列。所有其他列将被“融化”:它们的列名将放入var_name指定的新列(此处为temp_col),而它们的值将放入value列。
  2. tmp[['side', 'col']] = tmp['temp_col'].str.split('_', n=1, expand=True): melt操作后,temp_col列包含了原始的列名(如right_count)。我们利用字符串的split('_', n=1, expand=True)方法,将其拆分为两部分:side(如right或left)和col(如count或sum)。
  3. tmp.pivot(index=['date', 'other_col', 'side'], columns='col', values='value'): pivot函数用于将长格式数据重新透视回宽格式,但这次是按照我们新的需求。index指定了新的行索引,columns指定了将作为新列的列,values指定了填充新列的值。
  4. reset_index().rename_axis(columns=None): reset_index将透视操作产生的索引转换回列。rename_axis(columns=None)则用于清除pivot操作可能在列索引上留下的名称(例如,col)。

方法三:使用janitor库的pivot_longer简化操作

janitor是一个提供简洁、易用数据清理和转换函数的Python库。它的pivot_longer函数专门用于处理这种将多列重塑为长格式的场景,尤其当列名具有特定模式时,它能极大地简化代码。

PageOn
PageOn

AI驱动的PPT演示文稿创作工具

下载
# 方法三:使用janitor库的pivot_longer简化操作
# 如果尚未安装,请先执行:pip install pyjanitor
import janitor

out_janitor = df.pivot_longer(index=['date', 'other_col'],
                              names_to=('side', '.value'), # 指定新的列名,.value 是一个特殊关键字
                              names_pattern=r'([^_]+)_([^_]+)') # 正则表达式匹配 'side_value' 模式

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

解析:

  1. import janitor: 导入janitor库。
  2. df.pivot_longer(index=['date', 'other_col'], ...): pivot_longer是janitor提供的函数,index参数与melt类似,指定了不进行重塑的标识符列。
  3. names_to=('side', '.value'): 这是一个关键参数。它告诉pivot_longer如何命名新生成的列。'side'将作为新列的名称,而.value是一个特殊占位符,表示从原始列名中提取的值将作为新的列(例如count和sum)。
  4. names_pattern=r'([^_]+)_([^_]+)': 这是一个正则表达式,用于从原始列名中捕获模式。([^_]+)匹配一个或多个非下划线字符。第一个捕获组将对应names_to中的第一个元素(side),第二个捕获组将对应.value所代表的列(count和sum)。

总结与注意事项

以上三种方法都能实现将多列堆叠重塑为新列的目标,但它们各有特点和适用场景:

  • 方法一(MultiIndex + stack)

    • 优点:高度灵活,能够处理复杂的层级重塑,是Pandas底层机制的体现。
    • 缺点:代码相对复杂,需要对Pandas的MultiIndex有较深入的理解。
    • 适用场景:当你需要对列进行多级分组,并根据这些级别进行堆叠时。
  • 方法二(melt + pivot)

    • 优点:使用Pandas内置函数,不引入额外依赖;逻辑清晰,分步执行,易于理解和调试。
    • 缺点:相比pivot_longer,步骤稍多。
    • 适用场景:不想引入第三方库,且对Pandas的melt和pivot操作熟悉,或当列名模式不完全规整,需要更多中间处理时。
  • 方法三(janitor.pivot_longer)

    • 优点:代码最简洁、直观,特别适合列名有清晰模式(如prefix_suffix)的场景,大大提高了开发效率。
    • 缺点:需要安装并引入第三方库janitor。
    • 适用场景:追求代码简洁性、可读性,且列名模式规整时,是首选方案。

在选择具体方法时,应综合考虑项目的依赖管理、团队成员的熟悉程度以及重塑任务的复杂性。对于日常的数据清洗和转换,janitor.pivot_longer无疑是一个非常强大的工具。如果项目不允许额外依赖,或者需要更精细的控制,melt与pivot的组合是稳健的选择。而基于MultiIndex的stack方法,则为处理更底层、更复杂的DataFrame结构提供了最大的灵活性。

相关专题

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

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

769

2023.06.15

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

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

661

2023.07.20

python能做什么
python能做什么

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

764

2023.07.25

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

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

639

2023.07.31

python教程
python教程

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

1305

2023.08.03

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

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

549

2023.08.04

python eval
python eval

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

579

2023.08.04

scratch和python区别
scratch和python区别

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

709

2023.08.11

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

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

精品课程

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

共4课时 | 9万人学习

Django 教程
Django 教程

共28课时 | 3.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

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

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