Pandas:将多行数据合并为单行的实现方案
问题描述
我有如下DataFrame:
ID TYPE SN Notes 0 01 Lorem Ipsum 1 02 apple aa11 Dummy text 2 02 banana ab12 Dummy text 3 03 orange ad04 Random text 4 04 Latin words 5 05 apple ac03 Randomised words 6 05 banana ac04 Randomised words 7 05 orange aa41 Randomised words 8 05 cherry af12 Randomised words 9 06 apple aa32 Dolorem Ipsum
其中存在ID相同、Notes列值相同,但TYPE和SN列有时为空有时非空的行。
我希望将现有DataFrame转换为按ID分组合并为单行的形式,如下所示:
ID TYPE_1 TYPE_2 TYPE_3 TYPE_4 SN_1 SN_2 SN_3 SN_4 Count Notes 0 01 0 Lorem Ipsum 1 02 apple banana aa11 ab12 2 Dummy text 2 03 orange ad04 1 Random text 3 04 0 Latin words 4 05 apple banana orange cherry ac03 ac04 aa41 af12 4 Randomised words 5 06 apple aa32 1 Dolorem Ipsum
我知道需要按ID分组,但后续该如何操作?不同DataFrame中同一ID的行数不确定,无法预先创建对应列,请问该如何实现?
解决方案
可以用Pandas的分组、序号标记及透视表组合操作实现,核心逻辑是给每个ID下的行分配序号,再通过透视把TYPE和SN列自动展开为多列,无需预先定义列数:
步骤1:导入库并构造原数据
import pandas as pd data = { 'ID': ['01', '02', '02', '03', '04', '05', '05', '05', '05', '06'], 'TYPE': ['', 'apple', 'banana', 'orange', '', 'apple', 'banana', 'orange', 'cherry', 'apple'], 'SN': ['', 'aa11', 'ab12', 'ad04', '', 'ac03', 'ac04', 'aa41', 'af12', 'aa32'], 'Notes': ['Lorem Ipsum', 'Dummy text', 'Dummy text', 'Random text', 'Latin words', 'Randomised words', 'Randomised words', 'Randomised words', 'Randomised words', 'Dolorem Ipsum'] } df = pd.DataFrame(data)
步骤2:给每个ID下的行添加序号
按ID分组后,为每组内的行分配从1开始的序号,作为后续列名的后缀:
df['seq'] = df.groupby('ID').cumcount() + 1
步骤3:透视展开TYPE和SN列
通过透视表把行转成列,自动生成TYPE_1、SN_1这类命名的列:
type_df = df.pivot(index='ID', columns='seq', values='TYPE').add_prefix('TYPE_') sn_df = df.pivot(index='ID', columns='seq', values='SN').add_prefix('SN_')
步骤4:统计有效行数(Count列)
统计每个ID下TYPE非空的行数,全为空则记为0:
count_df = df.groupby('ID')['TYPE'].apply(lambda x: x[x != ''].count()).rename('Count')
步骤5:提取唯一的Notes值
同一ID的Notes值一致,直接取每组第一个值:
notes_df = df.groupby('ID')['Notes'].first()
步骤6:合并结果并整理列顺序
将所有子DataFrame合并,调整列顺序到目标格式:
result = pd.concat([type_df, sn_df, count_df, notes_df], axis=1).reset_index() # 调整列顺序,匹配目标格式 cols = ['ID'] + [col for col in result.columns if col.startswith('TYPE_')] + \ [col for col in result.columns if col.startswith('SN_')] + ['Count', 'Notes'] result = result[cols].fillna('')
执行后result即为所需格式,无论每个ID有多少行,都会自动生成对应数量的TYPE和SN列。
内容的提问来源于stack exchange,提问作者bhdrozgn
相关产品推荐
相关产品推荐

