Numpy Lookup (Карта или Точка) - PullRequest
       3

Numpy Lookup (Карта или Точка)

7 голосов
/ 18 февраля 2011

У меня есть большой массив NumPy:

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

и массив уникальных значений большого размера в определенном порядке:

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

Как я могу быстро (без словарей 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]])

Я чувствую себя по-настоящему глупым, потому что не могу сделать это на макушке головы или найти это в документации. Легкие очки!

Ответы [ 2 ]

7 голосов
/ 18 февраля 2011
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]]    

index содержит индексы в отсечке массива, связанной с каждым элементом A.Обратите внимание, что нам пришлось отсортировать B, поскольку np.searchsorted ожидает отсортированный массив.

index - это почти нужный ответ, за исключением того, что мы хотим отобразить

1-->1
3-->0
0-->3
2-->2

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]]

Итак, в качестве однострочного ответа, ответ:

np.argsort(B)[np.sort(B).searchsorted(A)]

Вызов np.sort(B) и np.argsort(B) неэффективенпоскольку обе операции составляют сортировку B.Для любого 1D-массива B,

np.sort(B) == B[np.argsort(B)]

Таким образом, мы можем вычислить желаемый результат немного быстрее, используя

key=np.argsort(B)
result=key[B[key].searchsorted(A)]
6 голосов
/ 18 февраля 2011

Вот, пожалуйста,

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

Первоначально я предложил:

D = np.choose(C,ii).reshape(A.shape)

Но я понял, что у этого были ограничения, когда вы переходили к большим массивам. Вместо этого, заимствуя из умного ответа @ unutbu:

D = np.argsort(B)[C].reshape(A.shape)

или однострочник

np.argsort(B)[np.digitize(A.reshape(-1,),np.sort(B)) - 1].reshape(A.shape)

Что оказалось быстрее или медленнее, чем код @ unutbu, в зависимости от размера рассматриваемых массивов и количества уникальных значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...