Mik*_*lev 8 python sorting numpy scipy
我有一个numpy数组的浮点数/整数,并希望将其元素映射到他们的行列.
如果数组没有重复项,则可以通过以下代码解决该问题
In [49]: a1
Out[49]: array([ 0.1, 5.1, 2.1, 3.1, 4.1, 1.1, 6.1, 8.1, 7.1, 9.1])
In [50]: a1.argsort().argsort()
Out[50]: array([0, 5, 2, 3, 4, 1, 6, 8, 7, 9])
Run Code Online (Sandbox Code Playgroud)
现在我想将此方法扩展到具有可能重复的数组,以便将重复项映射到相同的值.例如,我想要数组a
a2 = np.array([0.1, 1.1, 2.1, 3.1, 4.1, 1.1, 6.1, 7.1, 7.1, 1.1])
Run Code Online (Sandbox Code Playgroud)
要映射到任何一个
0 1 4 5 6 1 7 8 8 1
Run Code Online (Sandbox Code Playgroud)
或者
0 3 4 5 6 3 7 9 9 3
Run Code Online (Sandbox Code Playgroud)
或者
0 2 4 5 6 2 7 8.5 8.5 2
Run Code Online (Sandbox Code Playgroud)
在第一个/第二个案例中,如果我们只应用a2.argsort().argsort(),我们将重复项映射到它们中的最小/最大等级.第三种情况只是前两种情况的平均值.
有什么建议?
编辑(效率要求)
在最初的描述中,我忘了提及时间要求.我正在寻求numpy/scipy函数方面的解决方案,这将避免"纯python开销".为了说清楚,请考虑理查德提出的解决方案,它实际上解决了问题,但速度很慢:
def argsortdup(a1):
sorted = np.sort(a1)
ranked = []
for item in a1:
ranked.append(sorted.searchsorted(item))
return np.array(ranked)
In [86]: a2 = np.array([ 0.1, 1.1, 2.1, 3.1, 4.1, 1.1, 6.1, 7.1, 7.1, 1.1])
In [87]: %timeit a2.argsort().argsort()
1000000 loops, best of 3: 1.55 us per loop
In [88]: %timeit argsortdup(a2)
10000 loops, best of 3: 25.6 us per loop
In [89]: a = np.arange(0.1, 1000.1)
In [90]: %timeit a.argsort().argsort()
10000 loops, best of 3: 24.5 us per loop
In [91]: %timeit argsortdup(a)
1000 loops, best of 3: 1.14 ms per loop
In [92]: a = np.arange(0.1, 10000.1)
In [93]: %timeit a.argsort().argsort()
1000 loops, best of 3: 303 us per loop
In [94]: %timeit argsortdup(a)
100 loops, best of 3: 11.9 ms per loop
Run Code Online (Sandbox Code Playgroud)
从上面的分析可以清楚地看出,argsortdup比a.argsort().argsort()慢30-50倍.主要原因是使用python循环和列表.
升级到scipy评论中建议的@WarrenWeckesser 的最新版本后,scipy.stats.rankdata似乎比两者都快scipy.stats.mstats.rankdata,并且np.searchsorted是在较大阵列上执行此操作的最快方法。
In [1]: import numpy as np
In [2]: from scipy.stats import rankdata as rd
...: from scipy.stats.mstats import rankdata as rd2
...:
In [3]: array = np.arange(0.1, 1000000.1)
In [4]: %timeit np.searchsorted(np.sort(array), array)
1 loops, best of 3: 385 ms per loop
In [5]: %timeit rd(array)
10 loops, best of 3: 109 ms per loop
In [6]: %timeit rd2(array)
1 loops, best of 3: 205 ms per loop
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4286 次 |
| 最近记录: |