新闻中心

Pandas DataFrame多列堆叠与重塑技巧

2025-11-18
浏览次数:
返回列表

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

Whimsical Whimsical

Whimsical推出的AI思维导图工具

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

以上就是Pandas DataFrame多列堆叠与重塑技巧的详细内容,更多请关注其它相关文章!


# 多个  # 面试seo岗位注意事项  # 优化排名seo效果好吗  # 为什么网站会优化失败啊  # 北京营销技术推广平台  # 搜索引擎seo软件  # 黑龙江百度营销推广排名  # 洪梅服装网站制作推广  # 网站优化推荐是什么意思  # 汕尾网站建设报价方案  # 松岗怎么样进行网站推广  # 下划线  # python  # 自定义  # 第二个  # 这是一个  # 将其  # 是一个  # 转换为  # 第一个  # 数据清洗  # 工具  # 正则表达式 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: J*a递归快速排序中静态变量导致数据累积的陷阱与解决方案  一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法  Python实时数据流中的动态最值查找策略  win11如何卸载Windows更新补丁 Win11解决更新导致系统不稳定的问题【修复】  QQ邮箱官网登录入口 QQ邮箱网页版邮箱快速登录  漫蛙漫画网页端入口 漫蛙2官方正版漫画站点  谷歌浏览器怎么给标签页静音_Chrome标签静音快捷操作  解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南  AngularJS $http POST请求数据传递与Go后端接收实践  一加 14R 快充无反应_一加 14R 充电优化  Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量  Python大型XML文件高效流式解析教程  随机参数递归函数的基准调用次数与时间复杂度探究  如何为你的Composer包编写自动化测试_集成PHPUnit到Composer的scripts工作流  c++如何使用TBB库进行任务并行_c++ Intel线程构建模块  Windows电脑怎么截图最方便_系统自带截图工具的5种神仙用法【技巧】  qq音乐在线播放入口_qq音乐电脑版登录链接  格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施  C++如何实现一个装饰器模式_C++设计模式之动态地给对象添加额外职责  React Router 嵌套组件中 URL 重定向问题的解决方案  AO3网页版最新入口合集 Archive of Our Own在线访问指南  Typer应用中灵活处理命令行参数的令牌化与解析  Python字典中优雅地迭代剩余元素的方法  mysql备份恢复性能优化_mysql备份恢复性能优化方法  Eclipse怎么运行工程_Eclipse工程运行配置说明  写好的html代码怎么运行出来_运行写好的html代码方法【教程】  腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程  J*aScript中在Map循环中检测并处理空数组元素  Bing引擎入口最新2025 Bing搜索免费官方登录  ACG动漫手机版官网入口 手机ACG动漫APP在线观看正版  vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧  Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖  c++ 获取系统当前时间 c++时间戳获取方法  Composer的 "licenses" 命令如何帮助你遵守开源协议_检查项目依赖的许可证合规性  汽水音乐车机版横屏版7.1 汽水音乐车机版横屏版下载入口  Win11如何使用Windows Sandbox Win11沙盒功能开启与使用教程【详解】  微博网页版主页入口 微博官方网站免登录访问  漫蛙manwa官网登录界面_漫蛙漫画网页版主站入口  J*a应用程序首次运行自动创建文件与目录的最佳实践  漫蛙漫画官方主页入口 漫蛙MANWA网页直达访问链接  Archive of Our Own官网直达 AO3最新可用地址一览  J*aScript中高效管理与清空动态列表:避免循环陷阱  c++如何使用折叠表达式(Fold Expressions)_c++17可变参数模板新技巧  纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析  微信网页版登录教程_微信网页版登录入口在哪  微信网页版官方入口教程 微信网页版网页版快速登录步骤  深入理解Go语言中Map值与方法接收器的交互:为什么需要临时变量  如何在低配置电脑上搭建轻量级J*a环境_占用更小的环境选择技巧  如何在Promise链中优雅地中断后续then执行  在哪找SublimeJ远程工具_SFTP插件配置教程 

搜索