如何对Pandas DataFrame分组后拆分前三特征及百分比至对应列?
问题描述
我有如下Pandas DataFrame:
clientid date generatedTime feature featurePercentage 0 12345 2022-11-18 00:00:00 2022-11-23 08:58:09 timely_log 1.0 1 12345 2022-11-19 00:00:00 2022-11-24 08:55:46 red 0.822815 2 12345 2022-11-19 00:00:00 2022-11-24 08:55:46 timely_log 0.177185
需要按clientid和date分组,将feature和featurePercentage按百分比从高到低拆分到新列:最高值对应First(百分比)和First_feature(特征名),次高对应Second和Second_feature,以此类推保留前三组,不足的位置填None。期望输出如下:
clientid date generatedTime First_feature First Second_feature Second Third_feature Third 0 12345 2022-11-18 00:00:00 2022-11-23 08:58:09 timely_log 1.0 None None None None 1 12345 2022-11-19 00:00:00 2022-11-24 08:55:46 red 0.822815 timely_log 0.177185 None None
解决方案
可以通过以下步骤实现需求:
- 分组排序并分配排名:按
clientid和date分组,组内按featurePercentage降序排列,为每行分配1起始的排名 - 转换为宽格式:用
pivot把长格式数据转成宽格式,只保留前三排名的内容 - 重命名列名:将生成的多级列名调整为要求的
First_feature、First等格式 - 合并基础列:将每个分组内唯一的
generatedTime列合并到结果中
具体代码如下:
import pandas as pd # 构造示例数据 df = pd.DataFrame({ 'clientid': [12345, 12345, 12345], 'date': ['2022-11-18 00:00:00', '2022-11-19 00:00:00', '2022-11-19 00:00:00'], 'generatedTime': ['2022-11-23 08:58:09', '2022-11-24 08:55:46', '2022-11-24 08:55:46'], 'feature': ['timely_log', 'red', 'timely_log'], 'featurePercentage': [1.0, 0.822815, 0.177185] }) # 1. 分组并按百分比降序排名 df['rank'] = df.groupby(['clientid', 'date'])['featurePercentage'].rank(ascending=False, method='first').astype(int) # 2. 转成宽格式,只保留1-3名 pivoted = df.pivot(index=['clientid', 'date'], columns='rank', values=['feature', 'featurePercentage']) pivoted = pivoted.reindex(columns=range(1,4), level=1) # 3. 重命名列 col_mapping = { ('feature', 1): 'First_feature', ('featurePercentage', 1): 'First', ('feature', 2): 'Second_feature', ('featurePercentage', 2): 'Second', ('feature', 3): 'Third_feature', ('featurePercentage', 3): 'Third' } pivoted.columns = [col_mapping[col] for col in pivoted.columns] # 4. 合并generatedTime列 base_cols = df.groupby(['clientid', 'date'])['generatedTime'].first().reset_index() result = base_cols.merge(pivoted.reset_index(), on=['clientid', 'date']) # 重置索引并将NaN替换为None result = result.reset_index(drop=True).fillna(value=None) print(result)
运行代码后即可得到符合要求的输出结果。
内容的提问来源于stack exchange,提问作者monte
相关产品推荐
相关产品推荐

