0

0

将宽格式DataFrame重塑为垂直结构:Pandas与NumPy的实践指南

碧海醫心

碧海醫心

发布时间:2025-10-25 14:36:01

|

431人浏览过

|

来源于php中文网

原创

将宽格式DataFrame重塑为垂直结构:Pandas与NumPy的实践指南

在数据分析中,我们经常遇到水平宽度过大的dataframe,这不仅降低了可读性,也阻碍了后续的数据处理。本教程将详细介绍如何将这类宽格式dataframe转换为更易于分析的垂直结构,特别是当我们需要将每n列提取并作为行追加到新的dataframe时。我们将探讨两种主要方法:利用numpy的`reshape`功能处理列数为n的倍数的情况,以及使用pandas的`multiindex`和`stack`功能处理更通用的情况。

数据重塑:从宽到长的转换

在处理大规模数据集时,原始数据往往以宽格式呈现,即包含数百甚至数千列。这种格式对于某些数据源是自然的,但对于多数分析任务来说,将其转换为“长”或“垂直”格式更为合适。例如,一个包含多组重复测量数据的DataFrame,每组数据占据6列,我们希望将其转换为每行代表一组完整测量的新DataFrame。

假设我们有一个名为 groups.csv 的CSV文件,加载后得到一个具有606列的Pandas DataFrame。我们的目标是每6列一组,将这些数据转换为一个拥有指定6列(例如'GroupA'到'GroupF')的新DataFrame,每一行代表原始DataFrame中的一组数据。

import pandas as pd
import numpy as np

# 模拟一个宽格式DataFrame
# 实际应用中,你会从CSV文件加载
# df = pd.read_csv("groups.csv")

# 示例数据:3行12列,每6列为一组
np.random.seed(123)
df = pd.DataFrame(np.random.randint(10, size=(3, 12)))
print("原始DataFrame:")
print(df)

输出:

原始DataFrame:
   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

方法一:使用NumPy的reshape功能(适用于列数是N的倍数)

当原始DataFrame的列数恰好是目标组大小(例如6)的倍数时,NumPy的reshape方法提供了一种高效且简洁的解决方案。

原理

  1. 转换为NumPy数组:Pandas DataFrame底层数据通常是NumPy数组,通过.to_numpy()方法可以获取。
  2. 重塑数组:numpy.reshape(new_shape)允许我们改变数组的维度。关键在于new_shape的定义。如果我们将目标列数设为6,而行数未知,可以使用-1让NumPy自动计算。例如,reshape(-1, 6)会将数组重塑为任意行数、6列的二维数组。
  3. 创建新DataFrame:将重塑后的NumPy数组传递给pd.DataFrame,并指定新的列名。

实现步骤

首先,确认原始DataFrame的列数是否是目标组大小的倍数。

# 假设目标是每6列为一组
target_cols_per_group = 6
total_columns = len(df.columns)

print(f"原始DataFrame总列数: {total_columns}")
print(f"总列数 % {target_cols_per_group} = {total_columns % target_cols_per_group}")

if total_columns % target_cols_per_group == 0:
    print("列数是目标组大小的倍数,可以使用NumPy的reshape方法。")
else:
    print("列数不是目标组大小的倍数,需要使用更通用的Pandas方法。")

如果列数是倍数,我们可以直接应用reshape:

Bika.ai
Bika.ai

打造您的AI智能体员工团队

下载
# 定义新DataFrame的列名
new_columns = ['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']

# 将DataFrame转换为NumPy数组,然后重塑
# df.to_numpy().reshape(-1, target_cols_per_group) 会将所有数据展平后按6列重新组织
# 但这里我们希望保持原始行结构,即每行的数据作为一个整体被重新组织
# 正确的做法是先将整个DataFrame展平,再进行重塑
# 错误的理解可能导致:df.to_numpy().reshape(len(df) * (total_columns // target_cols_per_group), target_cols_per_group)
# 实际上,`df.to_numpy()`会返回一个 (rows, cols) 的数组
# 如果我们想把 (3, 12) 变成 (6, 6),我们需要先展平为 (36,),再重塑为 (6, 6)
# 或者更直接地,将整个DataFrame的数据视为一个整体进行重塑
df_target_numpy = pd.DataFrame(df.to_numpy().reshape(-1, target_cols_per_group),
                               columns=new_columns)
print("\n使用NumPy reshape重塑后的DataFrame:")
print(df_target_numpy)

输出:

使用NumPy reshape重塑后的DataFrame:
   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的总列数必须是目标组大小的精确倍数。如果不是,reshape会报错,或者产生非预期的结果。
  • df.to_numpy()会丢弃DataFrame的列名,因此我们需要在创建新DataFrame时手动指定列名。
  • 此方法处理的是DataFrame的,而不是其索引或列名。

方法二:使用Pandas MultiIndex和stack功能(适用于更通用的情况)

当原始DataFrame的列数不是目标组大小的精确倍数时,或者需要更灵活地处理列名时,Pandas的MultiIndex和stack组合提供了强大的功能。这种方法可以优雅地处理列数不匹配的情况,并自动填充NaN值。

原理

  1. 创建多级索引:利用整数除法//和取模运算%,为原始列创建两级索引。
    • a // 6:确定每个组的索引(例如,0-5列属于第0组,6-11列属于第1组)。
    • a % 6:确定组内元素的索引(0到5)。
  2. 设置新轴:使用df.set_axis([level0_index, level1_index], axis=1)将这些多级索引应用到列轴。
  3. 堆叠数据:stack()方法会将DataFrame的列“堆叠”到行上,将最内层的列索引转换为行索引的一部分。这正是我们将宽数据转换为长数据所需的关键步骤。
  4. 重命名列:堆叠后,列名会丢失,需要重新指定。
  5. 重置索引:reset_index(drop=True)清理新生成的索引。

实现步骤

# 示例数据:3行10列,每6列为一组,但10不是6的倍数
np.random.seed(123)
df_uneven = pd.DataFrame(np.random.randint(10, size=(3, 10)))
print("\n原始DataFrame (列数非倍数):")
print(df_uneven)

total_columns_uneven = len(df_uneven.columns)
print(f"原始DataFrame总列数: {total_columns_uneven}")
print(f"总列数 % {target_cols_per_group} = {total_columns_uneven % target_cols_per_group}")

# 为列创建多级索引
# level0_index: 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 (表示第几组)
# level1_index: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3 (表示组内第几列)
a = np.arange(total_columns_uneven)
multi_index_level0 = a // target_cols_per_group # 组索引
multi_index_level1 = a % target_cols_per_group  # 组内列索引

# 设置多级列索引
df_multi_indexed = df_uneven.set_axis([multi_index_level1, multi_index_level0], axis=1)
print("\n设置多级索引后的DataFrame:")
print(df_multi_indexed)

# 堆叠数据
# stack()默认会堆叠最内层的列索引(即multi_index_level1)
df_stacked = df_multi_indexed.stack()
print("\n堆叠后的DataFrame:")
print(df_stacked)

# 重命名列并重置索引
df_target_pandas = df_stacked.set_axis(new_columns, axis=1).reset_index(drop=True)
print("\n使用Pandas MultiIndex和stack重塑后的DataFrame:")
print(df_target_pandas)

输出:

原始DataFrame (列数非倍数):
   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

设置多级索引后的DataFrame:
   0  1  2  3  4  5  0  1  2  3
   0  0  0  0  0  0  1  1  1  1
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

堆叠后的DataFrame:
      0  1  2  3  4  5
0 0   2  2  6  1  3  9
  1   6  1  0  1  9  0
1 0   0  9  3  4  0  0
  1   4  1  7  3  2  4
2 0   7  3  2  4  7  2
  1   4  8  0  7  NaN  NaN

使用Pandas MultiIndex和stack重塑后的DataFrame:
   GroupA  GroupB  GroupC  GroupD  GroupE  GroupF
0       2       2       6       1     3.0     9.0
1       6       1       0       1     9.0     0.0
2       0       9       3       4     0.0     0.0
3       4       1       7       3     2.0     4.0
4       7       3       2       4     7.0     2.0
5       4       8       0       7     NaN     NaN

注意事项

  • 当原始列数不是目标组大小的倍数时,stack()操作会在不足的列位置自动填充NaN。这通常是期望的行为,但需要注意后续处理中对NaN值的处理。
  • 这种方法比NumPy reshape更灵活,因为它利用了Pandas的索引和重塑功能,能够更好地处理非规则数据。
  • 性能上,对于非常大的数据集,numpy.reshape可能略快,但Pandas方法在处理复杂情况时提供了更高的鲁棒性和可读性。

总结与选择

将宽格式DataFrame重塑为垂直结构是数据清理和准备的关键步骤。本教程介绍了两种有效的方法:

  1. NumPy reshape:适用于原始DataFrame列数是目标组大小的精确倍数的情况。它简洁高效,但对输入数据结构有严格要求。
  2. Pandas MultiIndex和stack:适用于更通用的场景,包括列数不是目标组大小倍数的情况。它通过引入NaN值来处理不完整的数据组,提供了更大的灵活性和鲁棒性。

在实际应用中,应根据你的数据特点和具体需求选择最合适的方法。如果数据总是规整的,reshape是一个不错的选择;如果数据可能不规整,或者需要更细致的控制,Pandas的MultiIndex和stack组合将是更强大的工具。无论选择哪种方法,目标都是为了获得一个结构清晰、易于分析的DataFrame。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

58

2025.12.04

treenode的用法
treenode的用法

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

538

2023.12.01

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

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

17

2025.12.22

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

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

27

2026.01.06

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

396

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

24

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

7

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

28

2026.01.28

热门下载

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

精品课程

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

共58课时 | 4.3万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.0万人学习

ASP 教程
ASP 教程

共34课时 | 4.2万人学习

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

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