【发布时间】:2020-10-07 06:09:08
【问题描述】:
我有任何可比较的dtype 的大型一维NumPy 数组a,它的一些元素可能会重复。
我如何找到排序索引ix,它将按降序/升序的值频率进行稳定排序(a sense described here 中的稳定性)a?
我想找到最快和最简单的方法来做到这一点。也许有现有的标准 numpy 函数可以做到这一点。
还有另一个相关的question here,但它专门要求删除数组重复项,即只输出唯一的排序值,我需要原始数组的所有值,包括重复项。
我已经编写了我的第一次试验来完成这项任务,但它不是最快的(使用 Python 的循环),并且可能不是最短/最简单的形式。如果相等元素的重复率不高且数组很大,则此 python 循环可能非常昂贵。如果在 NumPy 中可用(例如想象的np.argsort_by_freq()),那么有一个简短的函数来做这一切也很好。
import numpy as np
np.random.seed(1)
hi, n, desc = 7, 24, True
a = np.random.choice(np.arange(hi), (n,), p = (
lambda p = np.random.random((hi,)): p / p.sum()
)())
us, cs = np.unique(a, return_counts = True)
af = np.zeros(n, dtype = np.int64)
for u, c in zip(us, cs):
af[a == u] = c
if desc:
ix = np.argsort(-af, kind = 'stable') # Descending sort
else:
ix = np.argsort(af, kind = 'stable') # Ascending sort
print('rows: i_col(0) / original_a(1) / freqs(2) / sorted_a(3)')
print(' / sorted_freqs(4) / sorting_ix(5)')
print(np.stack((
np.arange(n), a, af, a[ix], af[ix], ix,
), 0))
输出:
rows: i_col(0) / original_a(1) / freqs(2) / sorted_a(3)
/ sorted_freqs(4) / sorting_ix(5)
[[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[ 1 1 1 1 3 0 5 0 3 1 1 0 0 4 6 1 3 5 5 0 0 0 5 0]
[ 7 7 7 7 3 8 4 8 3 7 7 8 8 1 1 7 3 4 4 8 8 8 4 8]
[ 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 5 5 5 5 3 3 3 4 6]
[ 8 8 8 8 8 8 8 8 7 7 7 7 7 7 7 4 4 4 4 3 3 3 1 1]
[ 5 7 11 12 19 20 21 23 0 1 2 3 9 10 15 6 17 18 22 4 8 16 13 14]]
【问题讨论】:
-
您当前的解决方案有什么问题?
-
@Nick 我在上面写了原因:1)它不是最快的(使用纯python循环)2)可能不是最短的3)重要的是降序不稳定(in this sense),但稳定我刚刚在一分钟前解决了here。
-
那么你对这个问题的预期输出是什么?
-
@Nick 在最后一个输出示例中,我需要在第 3 行末尾
4 6而不是6 4,因为它们的频率相同,并且它们按原顺序排列4 6大批。但是稳定性不是问题,我已经像上面的评论一样解决了它,只是为了 argsort 否定值。我会解决我的问题,不要打扰人们关于稳定性的问题。重要的是我想要最快的解决方案(没有 Python 循环)并且尽可能最短。 -
@Nick 如果数组很大并且其中重复的元素很少,那么这个 Python 循环将花费很长时间。
标签: python arrays numpy sorting frequency