我遇到了同样的问题,想知道对一个数组进行排序并相应地重新排序另一个数组的不同方法的性能。
两个数组的性能比较案例
我认为这里提到的解决方案列表很全面,但我也想知道性能。因此我实现了所有算法并进行了性能比较。
使用 zip 排序两次
def zip_sort(s, p):
ordered_s, ordered_p = zip(*sorted(list(zip(s, p))))
return np.array(ordered_s, dtype=s.dtype), np.array(ordered_p, dtype=p.dtype)
使用 argsort 进行排序。这里不会考虑其他数组进行辅助排序
def argsort(s, p):
indexes = s.argsort()
return s[indexes], p[indexes]
使用 numpy recarrays 排序
def recarray_sort(s, p):
rec = np.rec.fromarrays([s, p])
rec.sort()
return rec.f0, rec.f1
使用 numpy lexsort 进行排序
def lexsort(s, p):
indexes = np.lexsort([p, s])
return s[indexes], p[indexes]
对 100000 个随机整数的两个列表 p 和 q 进行排序将产生以下性能
zip_sort
258 ms ± 7.32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
argsort
9.67 ms ± 278 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
recarray_sort
86.4 ms ± 707 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
lexsort
12.4 ms ± 288 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
因此 argsort 是最快的,但也会产生与其他算法略有不同的结果。如果不需要辅助排序,则应使用 argsort。
性能比较多数组案例
接下来,可能需要对多个数组进行这种排序。修改算法以处理多个数组看起来像
使用 zip 排序两次
def zip_sort(*arrays):
ordered_lists = zip(*sorted(list(zip(*arrays))))
return tuple(
(np.array(l, dtype=arrays[i].dtype) for i, l in enumerate(ordered_lists))
)
使用 argsort 进行排序。这里不会考虑其他数组进行辅助排序
def argsort(*arrays):
indexes = arrays[0].argsort()
return tuple((a[indexes] for a in arrays))
使用 numpy recarrays 排序
def recarray_sort(*arrays):
rec = np.rec.fromarrays(arrays)
rec.sort()
return tuple((getattr(rec, field) for field in rec.dtype.names))
使用 numpy lexsort 进行排序
def lexsort(*arrays):
indexes = np.lexsort(arrays[::-1])
return tuple((a[indexes] for a in arrays))
用每 100000 个随机整数 (arrays = [np.random.randint(10, size=100000) for _ in range (100)]) 对 100 个数组的列表进行排序,现在可以得到以下性能
zip_sort
13.9 s ± 570 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
argsort
49.8 ms ± 1.49 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
recarray_sort
491 ms ± 14.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
lexsort
881 ms ± 15.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
argsort 仍然是最快的,由于忽略了辅助排序,这似乎是合乎逻辑的。对于其他算法,那些具有辅助列排序的算法,基于 recarray 的解决方案现在胜过 lexsort 变体。
免责声明:其他数据类型的结果可能会有所不同,并且还取决于数组数据的随机性。我用 42 作为种子。