映射数组以在Python中有效排名

时间:2016-05-01 19:51:12

标签: python arrays numpy

您好我试图将一系列数字映射到他们的行列。因此,例如[2,5,3]将变为[0,2,1]。

我目前正在使用np.where来查找数组中的排名,但事实证明这需要很长时间,因为我必须为非常大的数组(超过200万个数据点)执行此操作。

如果有人对如何实现这一点有任何建议,我将非常感激!

[编辑]这是目前更改特定行的代码:

def change_nodes(row): 
  a = row
  new_a = node_map[node_map[:,1] == a][0][0]
  return new_a

[编辑2]重复的数字应另外具有相同的等级

[编辑3]此外,唯一数字应该只计入一次排名。例如,该列表[2,3,3,4,5,7,7,7,7,8,1]的排名将是:

{1:0,2:1,3:2,4:3,5:4,7:5,8:6}

3 个答案:

答案 0 :(得分:4)

您要使用的是WooCommerce - Auto Complete paid virtual Orders (depending on Payment methods)

>>> import numpy as np
>>> x = np.array([2, 5, 3])
>>> x.argsort()
array([0, 2, 1])

有关调整关系处理方式的想法,请参阅numpy.argsort及其答案。

答案 1 :(得分:2)

我有一个只有vanilla Python的变体:

a = [2,5,3]
aSORT = list(a)
aSORT.sort()
for x in aSORT:
    a[a.index(x)] = aSORT.index(x)
print(a)

在我的测试中,此处发布的numpy版本需要0.1406秒来对列表[2,5,3,62,5,2,5,1000,100,-1,-9]进行排序,而使用我的方法只需0.0154秒。

答案 2 :(得分:2)

这是一个有效的解决方案,并使用index与解决方案进行比较(index解决方案对于问题的添加(编辑3)限制也不正确)

import numpy as np

def rank1(x):
    # Sort values i = 0, 1, 2, .. using x[i] as key
    y = sorted(range(len(x)), key = lambda i: x[i])
    # Map each value of x to a rank. If a value is already associated with a
    # rank, the rank is updated. Iterate in reversed order so we get the
    # smallest rank for each value.
    rank = { x[y[i]]: i for i in xrange(len(y) -1, -1 , -1) }
    # Remove gaps in the ranks
    kv = sorted(rank.iteritems(), key = lambda p: p[1])
    for i in range(len(kv)):
        kv[i] = (kv[i][0], i)
    rank = { p[0]: p[1] for p in kv }
    # Pre allocate a array to fill with ranks
    r = np.zeros((len(x),), dtype=np.int)
    for i, v in enumerate(x):
        r[i] = rank[v]
    return r

def rank2(x):
    x_sorted = sorted(x)
    # creates a new list to preserve x
    rank = list(x)
    for v in x_sorted:
        rank[rank.index(v)] = x_sorted.index(v)
    return rank

比较结果

>>> d = np.arange(1000)
>>> random.shuffle(d)
>>> %timeit rank1(d)
100 loops, best of 3: 1.97 ms per loop
>>> %timeit rank2(d)
1 loops, best of 3: 226 ms per loop

>>> d = np.arange(10000)
>>> random.shuffle(d)
>>> %timeit rank1(d)
10 loops, best of 3: 32 ms per loop
>>> %timeit rank2(d)
1 loops, best of 3: 24.4 s per loop

>>> d = np.arange(100000)
>>> random.shuffle(d)
>>> %timeit rank1(d)
1 loops, best of 3: 433 ms per loop

>>> d = np.arange(2000000)
>>> random.shuffle(d)
>>> %timeit rank1(d)
1 loops, best of 3: 11.2 s per loop

index解决方案的问题是时间复杂度为O(n ^ 2)。我的解决方案的时间复杂度是O(n lg n),即排序时间。