如何用Pandas将每组含多观测的DataFrame转换为单观测行
解决Pandas分组多行转单行的问题
嘿,这个需求很常见,我来给你一步步演示怎么实现。首先我得确认下核心需求:你想把每个分组(看起来你这里是按type列分组,每个type对应多条观测)的多行数据,摊平成一行,每个字段带上序号区分不同的观测,对吧?
先从创建示例数据开始,和你给的原始数据一致:
import pandas as pd # 原始数据 df = pd.DataFrame({ 'type': ['A', 'A', 'B', 'B'], 'value': [1, 2, 3, 1], 'group': [0.3, 0.1, 0.2, 0.1] })
步骤1:给每个分组内的观测添加序号
我们需要给同一type下的每一行分配一个唯一的序号,这样后续才能把它们转成不同的列。用groupby.cumcount()就能轻松做到,我习惯从1开始编号,这样列名更直观:
df['obs_num'] = df.groupby('type').cumcount() + 1
这时候数据会变成这样:
| type | value | group | obs_num |
|---|---|---|---|
| A | 1 | 0.3 | 1 |
| A | 2 | 0.1 | 2 |
| B | 3 | 0.2 | 1 |
| B | 1 | 0.1 | 2 |
步骤2:重塑数据为单行格式
接下来用pivot函数把行转成列,以type为索引,obs_num作为列的层级,把value和group都转成对应序号的列:
pivoted_df = df.pivot(index='type', columns='obs_num')
这时候会得到一个多层列索引的DataFrame,我们需要把多层列名合并成更友好的格式,比如value1、group1:
# 合并列名 pivoted_df.columns = [f'{col_name}{obs_num}' for col_name, obs_num in pivoted_df.columns] # 把type从索引变回普通列 final_df = pivoted_df.reset_index()
最终结果
运行完上面的代码,你会得到这样的DataFrame(我猜你给的示例里列名可能有点笔误,这个格式更符合逻辑):
| type | value1 | group1 | value2 | group2 |
|---|---|---|---|---|
| A | 1 | 0.3 | 2 | 0.1 |
| B | 3 | 0.2 | 1 | 0.1 |
适配可变数量的观测
如果你的分组里观测数量不固定(比如有的组3条,有的组2条),这个方法也完全适用——多余的列会自动生成,没有值的位置会填充NaN,你可以根据需求用fillna()处理这些空值。
另外,如果你实际的分组依据不是type而是其他列(比如group列),只需要把groupby的参数改成对应的列名就行,逻辑完全一致。
内容的提问来源于stack exchange,提问作者pfuhlert
相关产品推荐
相关产品推荐

