【问题标题】:Array of indizes of unique values唯一值索引数组
【发布时间】:2017-08-03 12:24:53
【问题描述】:

我从包含 N 唯一值 (product(a.shape) >= N) 的数组 a 开始。
我需要在a 中各个元素的位置从a 中的唯一值的(排序)列表中找到具有索引0 .. N-1 的数组b

举个例子

import numpy as np
np.random.seed(42)
a = np.random.choice([0.1,1.3,7,9.4], size=(4,3))
print a

a 打印为

[[ 7.   9.4  0.1]
 [ 7.   7.   9.4]
 [ 0.1  0.1  7. ]
 [ 1.3  7.   7. ]]

唯一值是[0.1, 1.3, 7.0, 9.4],所以需要的结果b

[[2 3 0]
 [2 2 3]
 [0 0 2]
 [1 2 2]]

(例如,a[0,0] 的值是 7.7. 的索引为 2;因此是 b[0,0] == 2。)

自从numpy does not have an index function, 我可以使用循环来做到这一点。循环输入数组,如下所示:

u = np.unique(a).tolist()
af = a.flatten()
b = np.empty(len(af), dtype=int)
for i in range(len(af)):
    b[i] = u.index(af[i])
b = b.reshape(a.shape)
print b

或循环遍历唯一值如下:

u = np.unique(a)
b = np.empty(a.shape, dtype=int)
for i in range(len(u)):
    b[np.where(a == u[i])] = i
print b

我认为,在a 中并非所有值都不同的情况下,第二种循环唯一值的方法已经比第一种更有效;但是,它仍然涉及到这个循环,并且与就地操作相比效率相当低。

所以我的问题是:获取数组b 的最有效方法是什么,其中填充了a 的唯一值的索引?

【问题讨论】:

    标签: python arrays numpy indexing


    【解决方案1】:

    您可以使用 np.unique 及其可选参数 return_inverse -

    np.unique(a, return_inverse=1)[1].reshape(a.shape)
    

    示例运行 -

    In [308]: a
    Out[308]: 
    array([[ 7. ,  9.4,  0.1],
           [ 7. ,  7. ,  9.4],
           [ 0.1,  0.1,  7. ],
           [ 1.3,  7. ,  7. ]])
    
    In [309]: np.unique(a, return_inverse=1)[1].reshape(a.shape)
    Out[309]: 
    array([[2, 3, 0],
           [2, 2, 3],
           [0, 0, 2],
           [1, 2, 2]])
    

    通过source code of np.unique,这对我来说看起来很有效,但仍然删除了不必要的部分,我们最终会得到另一个解决方案,就像这样 -

    def unique_return_inverse(a):
        ar = a.flatten()     
        perm = ar.argsort()
        aux = ar[perm]
        flag = np.concatenate(([True], aux[1:] != aux[:-1]))
        iflag = np.cumsum(flag) - 1
        inv_idx = np.empty(ar.shape, dtype=np.intp)
        inv_idx[perm] = iflag
        return inv_idx
    

    时间安排 -

    In [444]: a= np.random.randint(0,1000,(1000,400))
    
    In [445]: np.allclose( np.unique(a, return_inverse=1)[1],unique_return_inverse(a))
    Out[445]: True
    
    In [446]: %timeit np.unique(a, return_inverse=1)[1]
    10 loops, best of 3: 30.4 ms per loop
    
    In [447]: %timeit unique_return_inverse(a)
    10 loops, best of 3: 29.5 ms per loop
    

    与内置相比没有很大的改进。

    【讨论】:

    • 哇,这已经是一个很好的被接受的候选人了。但是它返回(创建)两个大小为a 的数组,对吗?那么在内存方面可能有更有效的解决方案?!
    • @ImportanceOfBeingErnest 添加了另一个非常非常微小的改进。
    猜你喜欢
    • 2020-11-12
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 2019-03-30
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多