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

将宽格式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 pdimport 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  110  2  2  6  1  3  9  6  1  0  1   9   01  0  9  3  4  0  0  4  1  7  3   2   42  7  2  4  8  0  7  9  3  4  6   1   5

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

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

原理

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

实现步骤

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

# 假设目标是每6列为一组target_cols_per_group = 6total_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:

吉卜力风格图片在线生成 吉卜力风格图片在线生成

将图片转换为吉卜力艺术风格的作品

吉卜力风格图片在线生成 121 查看详情 吉卜力风格图片在线生成

# 定义新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  GroupF0       2       2       6       1       3       91       6       1       0       1       9       02       0       9       3       4       0       03       4       1       7       3       2       44       7       2       4       8       0       75       9       3       4       6       1       5

注意事项

此方法要求原始DataFrame的总列数必须是目标组大小的精确倍数。如果不是,reshape会报错,或者产生非预期的结果。df.to_numpy()会丢弃DataFrame的列名,因此我们需要在创建新DataFrame时手动指定列名。此方法处理的是DataFrame的,而不是其索引或列名。

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

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

原理

创建多级索引:利用整数除法//和取模运算%,为原始列创建两级索引。a // 6:确定每个组的索引(例如,0-5列属于第0组,6-11列属于第1组)。a % 6:确定组内元素的索引(0到5)。设置新轴:使用df.set_axis([level0_index, level1_index], axis=1)将这些多级索引应用到列轴。堆叠数据:stack()方法会将DataFrame的列“堆叠”到行上,将最内层的列索引转换为行索引的一部分。这正是我们将宽数据转换为长数据所需的关键步骤。重命名列:堆叠后,列名会丢失,需要重新指定。重置索引: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  90  2  2  6  1  3  9  6  1  0  11  9  0  0  9  3  4  0  0  4  12  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  10  2  2  6  1  3  9  6  1  0  11  9  0  0  9  3  4  0  0  4  12  7  3  2  4  7  2  4  8  0  7堆叠后的DataFrame:      0  1  2  3  4  50 0   2  2  6  1  3  9  1   6  1  0  1  9  01 0   0  9  3  4  0  0  1   4  1  7  3  2  42 0   7  3  2  4  7  2  1   4  8  0  7  NaN  NaN使用Pandas MultiIndex和stack重塑后的DataFrame:   GroupA  GroupB  GroupC  GroupD  GroupE  GroupF0       2       2       6       1     3.0     9.01       6       1       0       1     9.0     0.02       0       9       3       4     0.0     0.03       4       1       7       3     2.0     4.04       7       3       2       4     7.0     2.05       4       8       0       7     NaN     NaN

注意事项

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

总结与选择

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

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

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

以上就是将宽格式DataFrame重塑为垂直结构:Pandas与NumPy的实践指南的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/583582.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月10日 12:06:06
下一篇 2025年11月10日 12:07:14

相关推荐

发表回复

登录后才能评论
关注微信