Skip to main content
 首页 » 编程设计

python之存在重复值时将 numpy.array 转换为元素顺序

2024年10月25日6telwanggs

我正在寻找一种有效的方法来执行以下操作:

如果我的输入是:

np.array([9,0,1,0,3,0]) 

我希望我的输出是:

np.array([0,3,2,3,1,3]) # 9 is the highest, so it gets rank 0 
                        # 3 is the second highest, so it gets rank 1 
                        # 1 is third highest, so it gets rank 2 
                        # 0's are forth highest so they get rank 3 

我正在尝试将以下内容应用于二维矩阵:

输入:

a = np.array([[9,0,1,0,3,0], 
              [0,1,2,3,4,5], 
              [0.01,0.3,2,100,1,1], 
              [0,0,0,0,1,1], 
              [4,4,4,4,4,4]]) 

输出:

>>> get_order_array(a) 
array([[0, 3, 2, 3, 1, 3], 
       [5, 4, 3, 2, 1, 0], 
       [4, 3, 1, 0, 2, 2], 
       [1, 1, 1, 1, 0, 0], 
       [0, 0, 0, 0, 0, 0]]) 

我确实可以通过以下解决方案实现上述目标;但是,我觉得它的效率很低,所以我希望有人能提出一个更好的方法来实现我的目标。

def get_order(x): 
    unique_x = np.unique(x) 
    step_1 = np.argsort(unique_x)[::-1] 
    temp_dict = dict(zip(unique_x, step_1)) 
    return np.vectorize(temp_dict.get)(x) 
 
def get_order_array(x): 
    new_array = np.empty(x.shape, dtype=np.int) 
    for i in xrange(x.shape[0]): 
        new_array[i] = get_order(x[i]) 
    return new_array 

请您参考如下方法:

@Jaime 的回答很好(一如既往!)。这是一个替代方案,使用 scipy.stats.rankdata .

rankdata 的术语中,您需要一个“密集”的排名。您还希望以与通常相反的顺序排列这些值。为了完成相反的顺序,我们将传递 -arankdata。我们还将从排名中减去 1,这样排名从 0 而不是 1 开始。最后,您想要对二维数组的行进行排名。 rankdata 适用于一维数据,因此我们必须遍历行。

代码如下:

import numpy as np 
from scipy.stats import rankdata 
 
 
def get_order_array(a): 
    b = np.empty(a.shape, dtype=int) 
    for k, row in enumerate(a): 
        b[k] = rankdata(-row, method='dense') - 1 
    return b 
 
 
if __name__ == "__main__":     
    a = np.array([[9,0,1,0,3,0], 
                  [0,1,2,3,4,5], 
                  [0.01,0.3,2,100,1,1], 
                  [0,0,0,0,1,1], 
                  [4,4,4,4,4,4]]) 
    print get_order_array(a) 

输出:

[[0 3 2 3 1 3] 
 [5 4 3 2 1 0] 
 [4 3 1 0 2 2] 
 [1 1 1 1 0 0] 
 [0 0 0 0 0 0]]