如何用Pandas重排DataFrame:将类别转成行、时间点转成列
通用数据重塑解法(类别转行、时间点转列)
原始数据
data={'P1_1': ['1', '6', '5','8', '4', '7', '5', '7', '1', '7', '3', '2', '1', '4', '7', '5', '7', '1'], 'P1_2':['3', '7', '7','9', '8', '10', '8', '9', '3', '10', '9', '5', '3', '8', '9', '6', '7', '5'], 'P2_1': ['1', '2', '3','4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18'], 'P2_2': ['3', '7', '7','9', '8', '10', '8', '9', '8', '10', '12', '13', '14', '8', '17', '8', '2', '5']} df=pd.DataFrame(data)
原始结构说明:
- 列名格式为
{类别}_{时间点}(如P1_1代表类别P1的时间点1数据) - 每行对应同一样本在不同类别、时间点的取值
目标结构
将数据重构为:
- 行:类别(P1、P2、P3...)
- 列:时间点(1、2...)
- 单元格填充对应类别+时间点的所有原始数据(每个类别下的行是原DataFrame对应列的完整值列表)
通用实现方法
这是典型的宽表转结构化表的问题,下面两种方法都支持任意数量的类别和时间点,无需修改代码即可适配扩展场景:
方法1:melt + pivot(直观易懂)
# 1. 添加样本索引,保证数据顺序一致 df['sample_idx'] = df.index # 2. 转长表,拆分列名为类别和时间点 melted_df = df.melt(id_vars='sample_idx', var_name='cat_time', value_name='data') melted_df[['category', 'time']] = melted_df['cat_time'].str.split('_', expand=True) # 3. 转宽表得到目标结构 result = melted_df.pivot(index='category', columns='time', values='data') # 4. 整理格式(可选) result.columns.name = None result = result.reset_index().rename(columns={'index': 'category'})
方法2:stack + unstack(简洁高效)
利用多层列索引直接重塑:
# 将列名拆分为类别、时间点两层索引 df.columns = df.columns.str.split('_', expand=True) # 重塑数据:交换层级并转置 result = df.stack(level=0).unstack(level=0).T.reset_index() result.columns = ['category'] + list(result.columns[1:]) result.columns.name = None
结果示例
运行后得到的目标结构如下:
| category | 1 | 2 |
|---|---|---|
| P1 | ['1','6','5',...,'1'] | ['3','7','7',...,'5'] |
| P2 | ['1','2','3',...,'18'] | ['3','7','7',...,'5'] |
如果新增类别(如P3_1、P3_2)或时间点(如P1_3),代码会自动识别并纳入结果,完全通用。
内容的提问来源于stack exchange,提问作者Kajette
相关产品推荐
相关产品推荐

