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)

解析:

Okaaaay
Okaaaay

适用于所有人的AI文本和内容生成器

下载
  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函数专门用于处理这种将多列重塑为长格式的场景,尤其当列名具有特定模式时,它能极大地简化代码。

# 方法三:使用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结构提供了最大的灵活性。

热门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正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

766

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中文网欢迎大家前来学习。

547

2023.12.06

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

23

2026.03.06

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新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号