Pandas如何正确转置列,将多行DataFrame转为同一行多列?
如何将分组的DataFrame转换为指定宽格式?
首先先明确你的原始数据和目标格式:
原始DataFrame:
| name_by_day | name | a | b |
|---|---|---|---|
| 20170901 | 2017090101 | 118 | 241 |
| 20170901 | 2017090102 | 117 | 241 |
| 20170901 | 2017090103 | 88 | 241 |
| 20170901 | 2017090104 | 99 | 241 |
| 20170901 | 2017090105 | 87 | 241 |
目标格式:
| name_by_day | a_x | b_x | a_y | b_y | a_z | b_z | a_aa | b_aa | a_ab | b_ab |
|---|---|---|---|---|---|---|---|---|---|---|
| 20170901 | 118 | 241 | 117 | 241 | 88 | 241 | 99 | 241 | 87 | 241 |
(注:因为有5行数据,后缀会自动延伸到ab,如果你只需要x/y/z的话,可以根据实际行数调整序号逻辑,下面的方案是通用版)
下面是具体的实现步骤,用Pandas就能轻松搞定:
步骤1:准备示例数据(如果你的数据已经存在可以跳过)
import pandas as pd # 构造你的原始数据 data = { 'name_by_day': ['20170901'] * 5, 'name': ['2017090101', '2017090102', '2017090103', '2017090104', '2017090105'], 'a': [118, 117, 88, 99, 87], 'b': [241] * 5 } df = pd.DataFrame(data)
步骤2:生成分组内的序号并转换为后缀
我们需要给每个name_by_day分组里的每行分配一个唯一标识,用来生成a_x、b_x这类列名的后缀:
# 给每个分组内的行生成递增序号(从0开始) df['seq'] = df.groupby('name_by_day').cumcount() # 将序号转换为x、y、z...的后缀(0→x,1→y,以此类推) df['suffix'] = df['seq'].apply(lambda x: chr(ord('x') + x))
步骤3:重塑数据并生成新列名
用melt把宽格式转成长格式,方便我们拼接列名和后缀:
# 把a、b列转成行,保留name_by_day和suffix作为标识 df_melted = df.melt( id_vars=['name_by_day', 'suffix'], value_vars=['a', 'b'], var_name='original_col' ) # 拼接原始列名和后缀,得到新列名(比如a_x、b_x) df_melted['new_col'] = df_melted['original_col'] + '_' + df_melted['suffix']
步骤4:转换为目标宽格式
最后用pivot把数据转回宽格式,再调整列的顺序让它更符合你的预期:
# 转成宽格式 result = df_melted.pivot( index='name_by_day', columns='new_col', values='value' ).reset_index() # 按后缀的顺序排列列(x→y→z...) sorted_columns = sorted(result.columns[1:], key=lambda col: col[-1]) result = result[['name_by_day'] + sorted_columns] # 查看结果 print(result)
运行后就能得到你想要的格式啦!如果你的数据有多个name_by_day分组,这个方案也能自动处理每个分组的转换,非常通用。
内容的提问来源于stack exchange,提问作者Francesc
相关产品推荐
相关产品推荐

