
本文探讨了在pandas dataframe中将多列宽格式数据重塑为长格式的多种方法。通过示例,详细介绍了使用pandas原生函数如`melt`与`pivot`、基于multiindex的高级重塑技巧,以及利用`pyjanitor`库中`pivot_longer`函数的便捷操作。旨在帮助用户高效地规整数据,使其更适合分析和可视化。
在数据分析和处理中,我们经常会遇到需要将DataFrame中的“宽格式”数据转换为“长格式”数据的情况。宽格式数据通常表现为,多个相关联的指标被分散在不同的列中,且列名中包含了这些指标的分类信息。例如,原始数据中可能包含 right_count, right_sum, left_count, left_sum 等列,我们希望将其重塑为 side, count, sum 三列,其中 side 列表示“right”或“left”,count 和 sum 列分别包含对应的值。这种转换对于后续的数据聚合、可视化和建模至关重要。
以下是一个典型的宽格式DataFrame示例:
import pandas as pd
df = pd.DataFrame({
'date': ['2023-12-01', '2023-12-05', '2023-12-07'],
'other_col': ['a', 'b', 'c'],
'right_count': [4, 7, 9],
'right_sum': [2, 3, 5],
'left_count': [1, 8, 5],
'left_sum': [0, 8, 4]
})
print("原始DataFrame:")
print(df)期望的输出格式如下:
date other_col side count sum 0 2023-12-01 a right 4 2 1 2023-12-05 b right 7 3 2 2023-12-07 c right 9 5 3 2023-12-01 a left 1 0 4 2023-12-05 b left 8 8 5 2023-12-07 c left 5 4
接下来,我们将介绍几种实现这种数据重塑的有效方法。
pandas.melt 函数用于将DataFrame从宽格式转换为长格式,它会将指定的列“融化”成两列:一列包含原列名(通常命名为variable),另一列包含对应的值(通常命名为value)。之后,我们可以利用 str.split 分割 variable 列,并结合 pivot 函数将数据重新排列成我们需要的长格式。
# 步骤1: 使用 melt 函数将 'right_count', 'right_sum', 'left_count', 'left_sum' 列融化
# id_vars 指定不变的标识列
tmp = df.melt(id_vars=['date', 'other_col'], var_name='original_col_name')
# 步骤2: 从新的 'original_col_name' 列中分割出 'side' 和 'metric_type'
# n=1 表示只分割一次,expand=True 将结果扩展为新的DataFrame列
tmp[['side', 'metric_type']] = tmp['original_col_name'].str.split('_', n=1, expand=True)
# 步骤3: 使用 pivot 函数将 'metric_type' 重新作为列,'value' 作为值
# index 指定新的行索引,columns 指定新的列名,values 指定新的值
out_melt_pivot = (tmp.pivot(index=['date', 'other_col', 'side'],
columns='metric_type',
values='value')
.reset_index() # 将索引重置为列
.rename_axis(columns=None) # 移除列索引的名称
)
print("\n方法一 (melt + pivot) 结果:")
print(out_melt_pivot)优点:
缺点:
这种方法利用Pandas的MultiIndex功能在列级别创建分层索引,然后通过 stack 操作将部分索引级别转换为行数据。这是一种更为紧凑和强大的Pandas原生解决方案。
# 步骤1: 设置 'date' 和 'other_col' 为行索引
# 步骤2: 使用 pipe 函数链式操作,通过 str.split 创建列的MultiIndex
# x.columns.str.split('_', expand=True) 会将 'right_count' 分割为 ('right', 'count')
# 步骤3: 重命名列索引的级别,使其更具可读性
# 步骤4: 对 'side' 级别进行 stack 操作,将其从列转换为行
# 步骤5: 重置索引,将所有索引级别转换为常规列
out_multiindex = (df
.set_index(['date', 'other_col'])
.pipe(lambda x: x.set_axis(x.columns.str.split('_', expand=True), axis=1))
.rename_axis(columns=['side', None]) # 'None' 表示第二个级别没有名称
.stack('side') # 对 'side' 级别进行堆叠
.reset_index()
)
print("\n方法二 (MultiIndex) 结果:")
print(out_multiindex)优点:
缺点:
pyjanitor 是一个为Pandas提供额外数据清理和转换功能的库,其中的 pivot_longer 函数专门用于简化从宽格式到长格式的转换,其灵感来源于R语言的 tidyr::pivot_longer。
首先,如果尚未安装 pyjanitor,请通过pip安装:
pip install pyjanitor
然后,可以使用以下代码进行重塑:
import janitor # 导入 janitor 库
# 使用 pivot_longer 函数
# index: 指定不变的标识列
# names_to: 指定新的列名元组,其中 '.value' 是一个特殊占位符,表示将原始列名的剩余部分作为新列名
# names_pattern: 使用正则表达式来匹配原始列名并捕获要提取的部分
out_janitor = df.pivot_longer(
index=['date', 'other_col'],
names_to=('side', '.value'), # 'side' 是第一个捕获组,'.value' 是第二个捕获组
names_pattern=r'([^_]+)_([^_]+)' # 匹配 'xxx_yyy' 模式,捕获 'xxx' 和 'yyy'
)
print("\n方法三 (pyjanitor.pivot_longer) 结果:")
print(out_janitor)优点:
缺点:
掌握这些数据重塑技巧,将使您在处理Pandas DataFrame时更加高效和灵活,从而更好地准备数据以进行深入分析。
以上就是Pandas DataFrame多列重塑:将宽格式数据转换为长格式的实用技巧的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号