Python Pandas:重塑宽格式DataFrame为长格式的策略与实践

花韻仙語
发布: 2025-10-25 12:34:01
原创
356人浏览过

Python Pandas:重塑宽格式DataFrame为长格式的策略与实践

本教程探讨如何将水平宽度过大的pandas dataframe重塑为更易读的垂直长格式。针对列数能被目标组数整除和不能整除的两种情况,文章详细介绍了使用numpy `reshape`方法进行高效转换,以及利用pandas `multiindex`结合`stack`操作处理复杂场景的专业技巧,旨在帮助用户优化数据结构,提升数据分析效率。

在数据处理和分析中,我们经常会遇到数据以“宽”格式存储的情况,即一个实体的信息横向铺开,占据了大量的列。例如,一个CSV文件可能有数百甚至数千列,这使得数据难以直观阅读和分析。为了更好地进行数据操作和可视化,通常需要将这种宽格式数据转换为“长”格式,使其更符合关系型数据库或某些数据分析工具的要求。本文将详细介绍两种在Pandas中实现这种数据重塑的专业方法:利用NumPy的reshape功能以及结合Pandas MultiIndex和stack操作。

方法一:使用NumPy reshape进行高效重塑

当原始DataFrame的列数能够被目标组的列数整除时,NumPy的reshape方法提供了一种非常高效且简洁的解决方案。这种方法直接作用于底层NumPy数组,避免了Pandas层面的一些开销。

适用场景

  • 原始DataFrame的列数是目标每组列数的整数倍。
  • 数据类型一致,可以直接转换为NumPy数组。
  • 需要将每N列作为一个新的行组。

实现步骤与代码

  1. 将DataFrame转换为NumPy数组。
  2. 使用reshape方法将数组重塑为新的形状。其中,-1表示该维度的大小将由NumPy自动计算,以确保总元素数量不变;另一个参数则指定目标每组的列数。
  3. 将重塑后的NumPy数组转换回Pandas DataFrame,并指定新的列名。

以下是一个具体的示例:

import pandas as pd
import numpy as np

# 假设我们有一个宽格式的DataFrame
# 模拟一个3行12列的DataFrame,列数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

# 目标列名
target_columns = ['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']
group_size = len(target_columns) # 每组6列

# 检查列数是否可被整除
print(f"\n原始DataFrame列数: {len(df.columns)}")
print(f"列数 % {group_size} = {len(df.columns) % group_size}")

if len(df.columns) % group_size == 0:
    # 使用NumPy的reshape方法
    df_target = pd.DataFrame(df.to_numpy().reshape(-1, group_size),
                             columns=target_columns)
    print("\n重塑后的DataFrame:")
    print(df_target)
else:
    print("\n列数不能被目标组大小整除,请考虑使用Pandas MultiIndex和stack方法。")

# 重塑后的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操作将失败,并抛出ValueError: cannot reshape array of size X into shape (Y, Z)错误。
  • reshape(-1, group_size)中的-1表示NumPy会自动计算行数,以确保总元素数量不变。
  • 这种方法会丢失原始列名信息,因此需要重新指定新的列名。

方法二:利用Pandas MultiIndex和stack处理复杂场景

当原始DataFrame的列数不能被目标组的列数整除时,或者需要更灵活地处理列分组时,结合使用Pandas的MultiIndex和stack操作是一个强大的解决方案。这种方法能够优雅地处理不规则的列分组,并在必要时引入NaN值。

比格设计
比格设计

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

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

立即学习Python免费学习笔记(深入)”;

适用场景

  • 原始DataFrame的列数不能被目标每组列数整除。
  • 需要更灵活的列分组逻辑。
  • 可以接受在数据不完整时自动填充NaN。

实现步骤与代码

  1. 创建两个索引数组:一个用于标识每组内的位置(a % group_size),另一个用于标识组的序号(a // group_size)。
  2. 使用set_axis将这两个索引数组作为DataFrame的列MultiIndex。
  3. 使用stack()方法将最内层(即每组内的位置)的列堆叠为行,从而将宽格式转换为长格式。
  4. 再次使用set_axis重命名转换后的列。
  5. 使用reset_index(drop=True)清理索引,使其成为默认的整数索引。

以下是一个具体的示例:

import pandas as pd
import numpy as np

# 模拟一个3行10列的DataFrame,列数10不能被6整除
np.random.seed(123)
df = pd.DataFrame(np.random.randint(10, size=(3, 10)))
print("原始DataFrame:")
print(df)
# 原始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

# 目标列名
target_columns = ['GroupA', 'GroupB', 'GroupC', 'GroupD', 'GroupE', 'GroupF']
group_size = len(target_columns) # 每组6列

print(f"\n原始DataFrame列数: {len(df.columns)}")
print(f"列数 % {group_size} = {len(df.columns) % group_size}") # 结果为2,不能整除

# 创建用于MultiIndex的索引数组
# a % group_size: [0, 1, 2, 3, 4, 5, 0, 1, 2, 3] (表示在组内的位置)
# a // group_size: [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] (表示组的序号)
a = np.arange(len(df.columns))

# 设置MultiIndex,然后stack
df_target_multiindex = (df.set_axis([a % group_size, a // group_size], axis=1)
                          .stack() # 堆叠最内层索引 (即a % group_size)
                          .set_axis(target_columns, axis=1) # 重命名列
                          .reset_index(drop=True)) # 重置索引

print("\n重塑后的DataFrame (使用MultiIndex和stack):")
print(df_target_multiindex)

# 重塑后的DataFrame (使用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
登录后复制

注意事项

  • 当原始列数不能被目标组大小整除时,stack操作会自动用NaN填充缺失的值。例如,上述示例中,原始DataFrame有10列,每组6列,那么第一组有6列,第二组有4列。在重塑后,第二组的最后两列(GroupE, GroupF)将填充NaN。
  • set_axis用于设置或修改DataFrame的轴标签。在这里,它用于创建列的MultiIndex。
  • stack()操作默认会堆叠最内层的列索引。
  • 由于stack()操作可能导致数据类型从整数变为浮点数(因为引入了NaN),如果需要,可能需要后续进行数据类型转换。

选择合适的重塑策略

  • 优先考虑NumPy reshape: 如果你的数据列数总是目标组大小的精确倍数,并且性能是关键因素,那么NumPy的reshape方法是最佳选择,因为它直接操作底层数组,效率最高。
  • 灵活选择Pandas MultiIndex和stack: 如果你的数据列数不总是精确倍数,或者你需要更灵活地处理列分组,那么Pandas的MultiIndex结合stack方法是更健壮的选择。它能够优雅地处理不完整的数据组,并通过NaN值进行标记。

总结

将宽格式的DataFrame重塑为长格式是数据预处理中的常见任务。本文介绍了两种核心策略:当列数完美匹配时,利用NumPy的reshape方法可以实现高效的转换;而当列数不规则时,结合Pandas的MultiIndex和stack操作则提供了更灵活和鲁棒的解决方案。掌握这些技巧将极大地提升你在处理复杂数据结构时的效率和能力,使你的数据分析工作更加顺畅。在实际应用中,根据数据的特性和具体需求选择最适合的方法至关重要。

以上就是Python Pandas:重塑宽格式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号