如何将Pandas DataFrame中的4列堆叠为2列?
Pandas DataFrame:将指定列堆叠为目标格式
原始数据
定义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] })
数据预览:
date other_col right_count right_sum left_count left_sum 0 2023-12-01 a 4 2 1 0 1 2023-12-05 b 7 3 8 8 2 2023-12-07 c 9 5 5 4
需求
将right_count、right_sum、left_count、left_sum四列转换为包含side(取值right/left)、count、sum的长表格式,保留date和other_col作为标识列。
解决方案1:使用pd.wide_to_long(最优)
该方法专为带前缀/后缀的宽表转长表设计,代码高效简洁:
result = pd.wide_to_long( df, stubnames=['count', 'sum'], # 列名的后缀部分 i=['date', 'other_col'], # 作为标识的列 j='side', # 前缀对应的新列名 sep='_', # 前缀与后缀的分隔符 suffix='.*' # 后缀的匹配规则 ).reset_index()
输出结果:
date other_col side count sum 0 2023-12-01 a right 4 2 1 2023-12-01 a left 1 0 2 2023-12-05 b right 7 3 3 2023-12-05 b left 8 8 4 2023-12-07 c right 9 5 5 2023-12-07 c left 5 4
如果需要按date排序且right排在left之前,添加排序逻辑:
result = result.sort_values( by=['date', 'side'], ascending=[True, False] ).reset_index(drop=True)
解决方案2:使用melt+split+pivot
若对wide_to_long不熟悉,可通过分步转换实现:
- melt转长表:将目标列转为键值对格式
melted = df.melt( id_vars=['date', 'other_col'], value_vars=['right_count', 'right_sum', 'left_count', 'left_sum'], var_name='side_metric', value_name='value' )
- 拆分列名:从
side_metric中拆分出side和metric
melted[['side', 'metric']] = melted['side_metric'].str.split('_', expand=True)
- pivot转回宽表:将
metric转为列,得到最终格式
result = melted.pivot( index=['date', 'other_col', 'side'], columns='metric', values='value' ).reset_index().rename_axis(None, axis=1)
此方法逻辑直观,同样可得到符合需求的结果。
内容的提问来源于stack exchange,提问作者corianne1234
相关产品推荐
相关产品推荐

