在Pandas DataFrame中按Part聚类、Date子聚类排序Quantity(正值优先)
Pandas按子聚类排序:正值前置的实现方案
问题背景
现有如下Pandas DataFrame:
Part Date Quantity A 2023-10-26 -1 A 2023-10-26 1 A 2023-11-03 1 A 2023-12-15 -1 B 2023-11-09 2 B 2023-11-14 -2 B 2023-11-14 2 B 2023-11-19 2
要求:以Part为一级分组,Date为二级子分组,每个子分组内把Quantity的正值放在前面,最终要得到这样的结果:
Part Date Quantity A 2023-10-26 1 A 2023-10-26 -1 A 2023-11-03 1 A 2023-12-15 -1 B 2023-11-09 2 B 2023-11-14 2 B 2023-11-14 -2 B 2023-11-19 2
解决方案
完全没必要用双重groupby,用sort_values就能简单高效搞定,甚至不需要额外临时列。当然如果非要用groupby也能实现,但属于画蛇添足。
最优方案:直接用sort_values排序
import pandas as pd # 构造原始数据(已有DataFrame可跳过此步) df = pd.DataFrame({ 'Part': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'], 'Date': ['2023-10-26', '2023-10-26', '2023-11-03', '2023-12-15', '2023-11-09', '2023-11-14', '2023-11-14', '2023-11-19'], 'Quantity': [-1, 1, 1, -1, 2, -2, 2, 2] }) # 核心排序逻辑 df_sorted = df.sort_values( by=['Part', 'Date', df['Quantity'] > 0, 'Quantity'], ascending=[True, True, False, True] ) # 可选:重置索引,消除原索引干扰 df_sorted = df_sorted.reset_index(drop=True) print(df_sorted)
逻辑说明
df['Quantity'] > 0会生成布尔序列,正值对应True(排序时视为1),负值对应False(视为0),设置ascending=False后,1会排在0前面,实现正值前置。- 最后加
'Quantity'排序是为了保证同符号数值按大小排列,可根据需求选择保留或删除。
备选方案:用groupby实现(不推荐)
如果一定要用groupby,可以这么写,但步骤更繁琐:
df_sorted = df.groupby(['Part', 'Date'], group_keys=False).apply( lambda x: x.sort_values(by='Quantity', key=lambda y: y < 0) )
逻辑说明
- 按
Part和Date分组后,对每个子分组用sort_values,排序key用lambda y: y < 0——负值返回True(1),正值返回False(0),排序后0在前,即正值排在前面。
内容的提问来源于stack exchange,提问作者Prmake
相关产品推荐
相关产品推荐

