0

0

Pandas DataFrame宽表重塑:按固定列数分组并堆叠为长表

聖光之護

聖光之護

发布时间:2025-10-25 10:09:12

|

678人浏览过

|

来源于php中文网

原创

Pandas DataFrame宽表重塑:按固定列数分组并堆叠为长表

本文详细介绍了如何将宽格式的pandas dataframe重塑为更易读的垂直长表,特别是当需要每n列作为一个逻辑组进行处理时。文章提供了两种核心方法:当总列数是n的倍数时,可高效利用`numpy.reshape`进行批量转换;而对于总列数不是n的倍数的情况,则通过pandas的`multiindex`和`stack`功能实现灵活重塑,并处理可能出现的缺失值。

在数据分析和处理中,我们经常会遇到宽格式的数据集,其中包含大量水平排列的列。为了便于分析或满足特定需求(例如,将每N列视为一个逻辑单元并将其堆叠成新的行),我们需要将这种宽表结构重塑为更垂直、更规范的长表。本文将详细介绍两种在Pandas中实现这一目标的方法。

场景描述

假设我们有一个非常宽的CSV文件,例如包含606列,我们已将其导入到Pandas DataFrame中。我们的目标是将原始DataFrame中每6列提取出来,作为一个新的逻辑组,并将其堆叠到目标DataFrame的行中。目标DataFrame应具有预定义的列名,例如['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']。

方法一:使用 numpy.reshape(适用于总列数是N的倍数)

当原始DataFrame的总列数是目标组列数(N)的整数倍时,numpy.reshape提供了一种非常高效且简洁的解决方案。这种方法将整个DataFrame的数据扁平化为一个一维数组,然后按照新的行数和列数进行重塑。

核心原理

  1. 将Pandas DataFrame转换为NumPy数组:df.to_numpy()。
  2. 使用reshape(-1, N)进行重塑:
    • -1 表示NumPy会自动计算新的行数。
    • N (例如,6) 表示新的DataFrame将有N列。
    • 这个操作实际上是将原始DataFrame的所有数据(所有行和所有列)按行优先的顺序展平,然后重新排列成N列的新结构。
  3. 将重塑后的NumPy数组转换回Pandas DataFrame,并指定新的列名。

示例代码

假设我们有一个3行12列的DataFrame,需要将其重塑为每6列一组。

import pandas as pd
import numpy as np

# 模拟一个宽格式的DataFrame
np.random.seed(123)
df_wide = pd.DataFrame(np.random.randint(10, size=(3, 12)))
print("原始宽格式DataFrame:")
print(df_wide)
# 输出:
#    0  1  2  3  4  5  6  7  8  9  10  11
# 0  2  2  6  1  3  9  6  1  0  1   9   0
# 1  0  9  3  4  0  0  4  1  7  3   2   4
# 2  7  2  4  8  0  7  9  3  4  6   1   5

# 检查列数是否是目标列数N的倍数
N = 6
if len(df_wide.columns) % N != 0:
    print(f"警告:原始列数 {len(df_wide.columns)} 不是 {N} 的整数倍,此方法可能不适用或需调整。")
else:
    print(f"\n原始DataFrame列数: {len(df_wide.columns)}")
    print(f"列数 {len(df_wide.columns)} 是 {N} 的整数倍: {len(df_wide.columns) % N == 0}")

    # 定义目标DataFrame的列名
    target_columns = ['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']

    # 使用numpy.reshape进行重塑
    df_target = pd.DataFrame(df_wide.to_numpy().reshape(-1, N),
                             columns=target_columns)

    print("\n重塑后的目标DataFrame:")
    print(df_target)
    # 输出:
    #    GroupA  GroupB  GroupC  GroupD  GroupE  GroupF
    # 0       2       2       6       1       3       9
    # 1       6       1       0       1       9       0
    # 2       0       9       3       4       0       0
    # 3       4       1       7       3       2       4
    # 4       7       2       4       8       0       7
    # 5       9       3       4       6       1       5

注意事项

  • 列数匹配: 此方法要求原始DataFrame的总列数必须是目标组列数N的整数倍。如果不是,reshape操作会失败或产生意想不到的结果。
  • 数据类型: to_numpy()会尝试统一所有列的数据类型。如果原始DataFrame中存在混合数据类型,可能会导致数据类型转换(例如,全部转换为object或float)。
  • 性能: 对于大型DataFrame,numpy.reshape通常非常高效。

方法二:使用 Pandas MultiIndex 和 stack(适用于任意列数)

当原始DataFrame的列数不是目标组列数N的整数倍时,或者当我们需要更灵活地处理列名和分组逻辑时,Pandas的MultiIndex结合stack方法提供了更通用的解决方案。这种方法通过创建多级列索引来标记每个列所属的组和其在组内的位置,然后利用stack将这些组堆叠起来。

Playground AI
Playground AI

AI图片生成和修图

下载

核心原理

  1. 创建列索引数组: 生成一个与原始DataFrame列数相同的序列,例如[0, 1, ..., total_columns - 1]。
  2. 构建多级列索引:
    • 第一级索引 (a % N):表示当前列在每个N列组中的位置(0到N-1)。
    • 第二级索引 (a // N):表示当前列所属的组编号。
    • 通过df.set_axis([a % N, a // N], axis=1)将这两级索引应用于DataFrame的列。
  3. 堆叠数据: 使用df.stack()默认会堆叠最内层(即第二级)的列索引,将其转换为行索引的一部分。这会将每个组的数据垂直堆叠起来。
  4. 重命名列: 堆叠后,原始的第一级索引(a % N)会成为新的列名(0到N-1)。通过set_axis(target_columns, axis=1)将其重命名为目标列名。
  5. 清理索引: reset_index(drop=True)用于清除新生成的行索引,使其变为默认的整数索引。

示例代码

假设我们有一个3行10列的DataFrame,需要将其重塑为每6列一组。由于10不是6的倍数,部分行将包含NaN。

import pandas as pd
import numpy as np

# 模拟一个宽格式的DataFrame,列数不是6的倍数
np.random.seed(123)
df_wide_uneven = pd.DataFrame(np.random.randint(10, size=(3, 10)))
print("原始宽格式DataFrame (列数非倍数):")
print(df_wide_uneven)
# 输出:
#    0  1  2  3  4  5  6  7  8  9
# 0  2  2  6  1  3  9  6  1  0  1
# 1  9  0  0  9  3  4  0  0  4  1
# 2  7  3  2  4  7  2  4  8  0  7

N = 6
print(f"\n原始DataFrame列数: {len(df_wide_uneven.columns)}")
print(f"列数 {len(df_wide_uneven.columns)} 是 {N} 的整数倍: {len(df_wide_uneven.columns) % N == 0}")

# 定义目标DataFrame的列名
target_columns = ['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']

# 创建列索引数组
a = np.arange(len(df_wide_uneven.columns))

# 构建MultiIndex并堆叠
df_target_uneven = (df_wide_uneven.set_axis([a % N, a // N], axis=1) # 创建MultiIndex: (列内序号, 组号)
                                  .stack()                             # 堆叠最内层索引 (组号)
                                  .set_axis(target_columns, axis=1)  # 重命名列
                                  .reset_index(drop=True))           # 重置索引

print("\n重塑后的目标DataFrame (处理非倍数列数):")
print(df_target_uneven)
# 输出:
#    GroupA  GroupB  GroupC  GroupD  GroupE  GroupF
# 0       2       2       6       1     3.0     9.0
# 1       6       1       0       1     NaN     NaN
# 2       9       0       0       9     3.0     4.0
# 3       0       0       4       1     NaN     NaN
# 4       7       3       2       4     7.0     2.0
# 5       4       8       0       7     NaN     NaN

注意事项

  • 缺失值处理: 当原始列数不是N的倍数时,最后一组(或多组)可能不完整。stack操作会自动用NaN填充缺失的单元格,以确保每行都有N列。因此,结果DataFrame的数据类型可能会变为浮点型(如果原始数据是整数)。
  • 索引清理: reset_index(drop=True)是必要的,因为它会移除stack操作生成的额外索引层,使DataFrame的索引干净。
  • 灵活性: 这种方法在处理复杂分组逻辑或需要保留更多原始列信息时更具优势。

总结

将宽格式的Pandas DataFrame重塑为按固定列数分组的长表是数据清洗和预处理的常见任务。

  • 对于列数是目标组列数N的整数倍的情况,推荐使用df.to_numpy().reshape(-1, N),它简洁高效。
  • 对于列数不是N的整数倍的情况,或者需要更灵活地处理列名和缺失值时,应采用Pandas MultiIndex结合stack的方法。

选择哪种方法取决于你的具体数据结构和对效率、灵活性以及缺失值处理的需求。理解这两种方法的原理和适用场景,能够帮助你更有效地处理各种数据重塑任务。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

52

2025.12.04

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

306

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

567

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

99

2025.10.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

535

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

21

2026.01.06

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

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

19

2026.01.20

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.5万人学习

Django 教程
Django 教程

共28课时 | 3.3万人学习

Excel 教程
Excel 教程

共162课时 | 12.6万人学习

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

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