如何实现Pandas分类类型DataFrame的长表转宽表操作
Pandas无聚合需求的分类DataFrame长表转宽表实现方法
我们日常使用Pandas做长表转宽表操作时,常用的pivot、pivot_table、unstack、groupby类方法都需要对重复索引对应的值做聚合计算,仅适用于有可聚合元素的场景,无法直接实现「将同分组下的多行分类值按顺序展开为独立列」的需求。针对示例中的场景,我们可以通过如下方案实现:
完整实现代码
首先导入依赖并构造输入数据:
import pandas as pd import numpy as np # 输入数据 d = {'Fruit':['Apple', 'Apple', 'Apple', 'Kiwi'], 'Color1':['Red', 'Yellow', 'Red', 'Green'], 'Color2':['Red', 'Red', 'Green', 'Brown'], 'Color3':[np.nan,np.nan,'Red',np.nan]} df = pd.DataFrame(d)
写法1:逻辑清晰分步实现
# 1. 给每个Fruit分组内的行添加顺序编号 df['row_num'] = df.groupby('Fruit').cumcount() # 2. 把Color列从宽格式转为长格式 df_melt = df.melt(id_vars=['Fruit', 'row_num'], var_name='color_type', value_name='color_value') # 3. 生成新的列名:分组内第0行用原列名,第n行加`_n`后缀 df_melt['new_col'] = df_melt.apply( lambda x: x['color_type'] if x['row_num'] == 0 else f"{x['color_type']}_{x['row_num']}", axis=1 ) # 4. 转回宽格式得到结果 df_result = df_melt.pivot(index='Fruit', columns='new_col', values='color_value').reset_index() # 可选:调整列顺序和示例输出完全一致 col_order = ['Fruit'] + [f'Color{i}' if j == 0 else f'Color{i}_{j}' for i in range(1,4) for j in range(3)] df_result = df_result[col_order]
写法2:更简洁的groupby+unstack实现
df_result = df.groupby('Fruit', group_keys=False)\ .apply(lambda x: x.drop('Fruit', axis=1).reset_index(drop=True))\ .unstack()\ .reset_index() # 处理列名 df_result.columns = [ col[0] if col[1] == 0 else f"{col[0]}_{col[1]}" for col in df_result.columns ]
结果验证
输出df_result即可得到符合要求的结构:
| Fruit | Color1 | Color1_1 | Color1_2 | Color2 | Color2_1 | Color2_2 | Color3 | Color3_1 | Color3_2 |
|---|---|---|---|---|---|---|---|---|---|
| Apple | Red | Yellow | Red | Red | Red | Green | NaN | NaN | Red |
| Kiwi | Green | NaN | NaN | Brown | NaN | NaN | NaN | NaN | NaN |
内容的提问来源于stack exchange,提问作者delimiter
相关产品推荐
相关产品推荐

