Numpy Lookup(地图或点)

Pau*_*aul 7 python indexing numpy

我有一个大的numpy数组:

array([[32, 32, 99,  9, 45],  # A
       [99, 45,  9, 45, 32],
       [45, 45, 99, 99, 32],
       [ 9,  9, 32, 45, 99]])
Run Code Online (Sandbox Code Playgroud)

以及特定顺序的大量唯一值数组:

array([ 99, 32, 45, 9])       # B
Run Code Online (Sandbox Code Playgroud)

我怎样才能快速(没有python词典,没有副本A,没有python循环)替换值, A以便成为B?中值的指示:

array([[1, 1, 0, 3, 2],
       [0, 2, 3, 2, 1],
       [2, 2, 0, 0, 1],
       [3, 3, 1, 2, 0]])
Run Code Online (Sandbox Code Playgroud)

我觉得因为无法在头脑中做到这一点而感到非常愚蠢,也没有在文档中找到它.简单点!

unu*_*tbu 7

import numpy as np
A=np.array([[32, 32, 99,  9, 45],  
            [99, 45,  9, 45, 32],
            [45, 45, 99, 99, 32],
            [ 9,  9, 32, 45, 99]])

B=np.array([ 99, 32, 45, 9])

cutoffs=np.sort(B)
print(cutoffs)
# [ 9 32 45 99]

index=cutoffs.searchsorted(A)
print(index)
# [[1 1 3 0 2]
#  [3 2 0 2 1]
#  [2 2 3 3 1]
#  [0 0 1 2 3]]    
Run Code Online (Sandbox Code Playgroud)

index将索引保存到与每个元素关联的数组截止值中A.注意我们必须排序,B因为np.searchsorted需要一个排序的数组.

index 几乎是理想的答案,除了我们想要映射

1-->1
3-->0
0-->3
2-->2
Run Code Online (Sandbox Code Playgroud)

np.argsort 为我们提供了这种映射:

print(np.argsort(B))
# [3 1 2 0]
print(np.argsort(B)[1])
# 1
print(np.argsort(B)[3])
# 0
print(np.argsort(B)[0])
# 3
print(np.argsort(B)[2])
# 2

print(np.argsort(B)[index])
# [[1 1 0 3 2]
#  [0 2 3 2 1]
#  [2 2 0 0 1]
#  [3 3 1 2 0]]
Run Code Online (Sandbox Code Playgroud)

所以,作为一个单行,答案是:

np.argsort(B)[np.sort(B).searchsorted(A)]
Run Code Online (Sandbox Code Playgroud)

调用两者np.sort(B)并且np.argsort(B)效率低,因为两个操作都相当于排序B.对于任何1D阵列B,

np.sort(B) == B[np.argsort(B)]
Run Code Online (Sandbox Code Playgroud)

因此,我们可以使用更快的速度计算所需的结果

key=np.argsort(B)
result=key[B[key].searchsorted(A)]
Run Code Online (Sandbox Code Playgroud)


Jos*_*del 6

干得好

A = array([[32, 32, 99,  9, 45],  # A
   [99, 45,  9, 45, 32],
   [45, 45, 99, 99, 32],
   [ 9,  9, 32, 45, 99]])

B = array([ 99, 32, 45, 9])

ii = np.argsort(B)
C = np.digitize(A.reshape(-1,),np.sort(B)) - 1
Run Code Online (Sandbox Code Playgroud)

最初我建议:

D = np.choose(C,ii).reshape(A.shape)
Run Code Online (Sandbox Code Playgroud)

但是我意识到当你去更大的阵列时这有局限性.相反,借用@ unutbu的聪明回复:

D = np.argsort(B)[C].reshape(A.shape)
Run Code Online (Sandbox Code Playgroud)

或者单线

np.argsort(B)[np.digitize(A.reshape(-1,),np.sort(B)) - 1].reshape(A.shape)
Run Code Online (Sandbox Code Playgroud)

我发现它比@ unutbu的代码更快或更慢,具体取决于所考虑的数组的大小和唯一值的数量.