如何将宽格式DataFrame按固定列数重塑为长格式

心靈之曲
发布: 2025-10-25 09:17:37
原创
242人浏览过

如何将宽格式dataframe按固定列数重塑为长格式

本教程详细介绍了如何将一个具有大量列的宽格式Pandas DataFrame重塑为更易读的垂直长格式。文章提供了两种核心方法:当总列数是目标列数的完美倍数时,可以使用NumPy的`reshape`功能高效处理;当总列数不是目标列数的完美倍数时,则采用Pandas的`MultiIndex`和`stack`操作灵活应对。通过具体代码示例和注意事项,帮助读者掌握数据重塑技巧,提升数据处理效率和可读性。

数据重塑:将宽格式DataFrame转换为长格式

在数据分析和处理中,我们经常会遇到包含大量列的“宽格式”DataFrame。这种格式在某些情况下可能难以阅读和分析,例如,当逻辑上相关的列被水平地分散在整个数据集中时。本教程将指导您如何将这类宽格式DataFrame,按照每N列一组的方式,重塑为一个更紧凑、更易于理解的“长格式”DataFrame。我们将探讨两种主要场景:当总列数是目标分组列数的完美倍数时,以及当它不是完美倍数时。

场景一:总列数是目标分组列数的完美倍数

当原始DataFrame的总列数能够被目标分组列数(例如,每6列一组)整除时,使用NumPy的reshape功能是最高效且简洁的方法。

1.1 方法概述

这种方法的核心是将DataFrame转换为NumPy数组,然后利用numpy.reshape()将其重塑为新的维度。由于我们希望最终的DataFrame有固定数量的列(例如6列),我们可以指定目标列数为6,并让NumPy自动推断行数。

1.2 示例代码

假设我们有一个包含606列的DataFrame,并且我们希望每6列为一组,将其转换为一个具有6列的新DataFrame。

import pandas as pd
import numpy as np

# 模拟一个宽格式DataFrame
# 实际应用中,这里会是 df = pd.read_csv("groups.csv")
np.random.seed(123)
# 假设原始DataFrame有3行12列,每6列一组,目标DataFrame有6列
df = pd.DataFrame(np.random.randint(10, size=(3, 12)))
print("原始DataFrame:")
print(df)
# 预期输出列名
target_columns = ['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']

# 检查总列数是否为目标分组列数的倍数
print(f"\n原始DataFrame列数: {len(df.columns)}")
print(f"列数 % 6: {len(df.columns) % 6}")

if len(df.columns) % 6 == 0:
    # 将DataFrame转换为NumPy数组,然后重塑
    # -1 表示让NumPy自动计算行数,6 表示目标DataFrame的列数
    df_target = pd.DataFrame(df.to_numpy().reshape(-1, 6),
                             columns=target_columns)
    print("\n重塑后的DataFrame (使用 numpy.reshape):")
    print(df_target)
else:
    print("\n原始DataFrame的列数不是6的倍数,此方法不适用。")
登录后复制

代码解析:

  1. df.to_numpy(): 将Pandas DataFrame转换为底层的NumPy数组。这会移除列名,只保留数据值。
  2. .reshape(-1, 6): 这是关键步骤。它将NumPy数组重塑为一个新的形状。
    • -1: 告诉NumPy根据数组中的元素总数和指定的其他维度(这里是6列)自动计算新的行数。
    • 6: 指定新DataFrame的列数。
  3. pd.DataFrame(..., columns=target_columns): 将重塑后的NumPy数组转换回Pandas DataFrame,并指定新的列名。

输出示例:

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

原始DataFrame列数: 12
列数 % 6: 0

重塑后的DataFrame (使用 numpy.reshape):
   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的所有数据类型都是兼容的,因为NumPy数组通常是同构的。如果DataFrame包含混合数据类型,to_numpy()可能会将其转换为object类型。
  • 此方法不保留原始的行索引信息,如果需要,需在重塑前进行保存或后续处理。

场景二:总列数不是目标分组列数的完美倍数

当原始DataFrame的总列数不能被目标分组列数整除时(例如,有5252列,但我们仍想每6列一组),numpy.reshape将无法直接使用。此时,我们可以利用Pandas的MultiIndex和stack操作来灵活处理。

比格设计
比格设计

比格设计是135编辑器旗下一款一站式、多场景、智能化的在线图片编辑器

比格设计 124
查看详情 比格设计

2.1 方法概述

这种方法通过创建一个多级列索引来逻辑地分组原始列,然后使用stack()方法将这些分组转换为行。对于不完整的最后一组,stack()会自动填充NaN。

2.2 示例代码

假设我们有一个包含10列的DataFrame,但我们仍然希望每6列为一组进行重塑。

import pandas as pd
import numpy as np

# 模拟一个宽格式DataFrame
np.random.seed(123)
# 假设原始DataFrame有3行10列,每6列一组,目标DataFrame有6列
df_imperfect = pd.DataFrame(np.random.randint(10, size=(3, 10)))
print("原始DataFrame (列数非6的倍数):")
print(df_imperfect)

# 预期输出列名
target_columns = ['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']
group_size = 6

print(f"\n原始DataFrame列数: {len(df_imperfect.columns)}")
print(f"列数 % {group_size}: {len(df_imperfect.columns) % group_size}")

# 创建一个用于生成MultiIndex的数组
a = np.arange(len(df_imperfect.columns))

# 使用 set_axis 和 MultiIndex 进行重塑
# a % group_size: 生成第一级索引,表示组内位置 (0到5)
# a // group_size: 生成第二级索引,表示是第几组 (0, 1, ...)
df_target_imperfect = (df_imperfect.set_axis([a % group_size, a // group_size], axis=1)
                                   .stack(level=0) # 将第一级索引(组内位置)堆叠为行
                                   .set_axis(target_columns, axis=1) # 设置新的列名
                                   .reset_index(drop=True)) # 重置索引,移除MultiIndex的层级
print("\n重塑后的DataFrame (使用 Pandas MultiIndex 和 stack):")
print(df_target_imperfect)
登录后复制

代码解析:

  1. a = np.arange(len(df_imperfect.columns)): 创建一个与列数等长的整数序列,用于生成索引。
  2. df_imperfect.set_axis([a % group_size, a // group_size], axis=1):
    • a % group_size: 计算每个原始列在目标组中的位置(0, 1, 2, 3, 4, 5, 0, 1, ...)。这将成为MultiIndex的第一层。
    • a // group_size: 计算每个原始列属于哪一个目标组(0, 0, 0, 0, 0, 0, 1, 1, ...)。这将成为MultiIndex的第二层。
    • set_axis(..., axis=1): 将生成的这两个数组作为新的列索引,创建多级列索引。
  3. .stack(level=0): 这是核心的重塑操作。它将MultiIndex的第一层(即组内位置)从列级别堆叠到行级别。这意味着每个原始行的数据,将根据其在组中的位置,被转换为多行。
  4. .set_axis(target_columns, axis=1): 堆叠后,列名会变成默认的数字索引,我们将其重新设置为目标列名。
  5. .reset_index(drop=True): stack()操作会引入新的索引层级。reset_index(drop=True)用于将这些层级移除,并生成一个干净的默认整数索引。

输出示例:

原始DataFrame (列数非6的倍数):
   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列数: 10
列数 % 6: 4

重塑后的DataFrame (使用 Pandas MultiIndex 和 stack):
   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
登录后复制

注意事项:

  • 当最后一组的列数不足group_size时,stack()会自动填充NaN值。您可能需要根据具体需求处理这些NaN值(例如,使用fillna()或dropna())。
  • 此方法比numpy.reshape更灵活,但对于非常大的数据集,性能可能会略低于纯NumPy方法。
  • 同样,原始行索引信息不会直接保留。

总结

本教程介绍了两种将宽格式DataFrame重塑为长格式的有效方法:

  1. numpy.reshape(-1, N): 适用于原始列数是目标分组列数N的完美倍数的情况。它直接操作底层NumPy数组,效率高,代码简洁。
  2. Pandas MultiIndex + stack(): 适用于原始列数不是目标分组列数N的完美倍数的情况。它利用Pandas强大的索引和重塑功能,能够灵活处理不完整的分组,并自动填充NaN。

选择哪种方法取决于您的具体数据特性和需求。在实际应用中,了解这两种方法可以帮助您更高效、更灵活地处理各种数据重塑任务。始终记住在重塑后检查数据类型和NaN值,以确保数据质量符合后续分析要求。

以上就是如何将宽格式DataFrame按固定列数重塑为长格式的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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