Pandas分组内排序:基于分组索引对数组组内排序(分组顺序不变)
基于未排序分组的组内排序(保留原分组出现顺序)
如果你需要根据分组索引数组定义的边界,对目标数组做组内排序,同时要求分组本身无需预先排序,且排序后严格保留分组的原有出现顺序,这里有一个高效的NumPy实现方案:
import numpy as np def groupwise_sort(group_idx, a, reverse=False): # 先按分组索引归拢同组元素,再对组内元素按目标数组升/降序排序 sortidx = np.lexsort((-a if reverse else a, group_idx)) # 通过双重稳定排序,恢复原分组的出现顺序,同时保留组内排序结果 revidx = np.argsort(np.argsort(group_idx, kind='mergesort'), kind='mergesort') return a[sortidx][revidx]
代码逻辑拆解:
np.lexsort步骤:这个函数会按传入元组的从后往前顺序排序——先把group_idx相同的元素归为一组,再对每个组内的元素按a(或逆序的-a)排序。这一步能保证组内有序,但整个数组的分组顺序是按group_idx的数值大小排列的,不是原数组中分组的出现顺序。- 双重
argsort步骤:这里特意用了稳定排序(kind='mergesort')来避免打乱同组内的排序结果。第一次argsort(group_idx)得到的是把group_idx按数值排序后的索引,第二次对这个结果做argsort,相当于生成一个「逆映射」,能把按数值排序后的分组重新还原为原数组中分组的出现顺序,同时完美保留组内的排序结果。 - 最终返回:通过两次索引映射,我们就得到了组内有序、分组顺序和原数组完全一致的目标数组。
示例用法:
# 测试用例 group_idx = np.array([2, 0, 2, 1, 0]) a = np.array([5, 3, 1, 4, 2]) # 组内升序排序,保留原分组顺序 result_asc = groupwise_sort(group_idx, a) print(result_asc) # 输出: [1 2 5 4 3] # 组内降序排序 result_desc = groupwise_sort(group_idx, a, reverse=True) print(result_desc) # 输出: [5 3 1 4 2]
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

