2017-02-17 4 views
1

Say У меня есть массив большой 2D Numpy (назовем его ), который содержит целые числа от 0 до 9.Имея несколько условными равенства для Numpy массивов

Я пытаюсь написать функцию, которая возвращает двоичный массив Numpy (назовите его B) той же формы, что и A, который имеет следующие функции.

Запись в B равен 1, если соответствующий элемент в A появляется в данном списке L; в противном случае запись равна нулю.

Ниже показано, что, вероятно, не самый эффективный код для этого.

A = np.random.randint(0, 10, (5, 5)) 
L = [3,4,5] 

B = np.zeros(A.shape) 
for e in L: 
    B[A==e] = 1 

Есть ли более быстрый способ?

Спасибо!

ответ

2

Вот два варианта numpy с np.in1d который представляет собой векторизованную версию in из базового python. Когда массив велик, первый вариант показывает некоторую скорость до:

Вариант один (быстрый один):

np.in1d(A, L).reshape(A.shape).astype(int) 

Вариант два (медленный):

np.apply_along_axis(np.in1d, 0, A, L).astype(int) 

KG Временное распределение:

A = np.random.randint(0, 10, (1000, 1000)) 
L = [3,4,5] 
​ 
def loop(): 
    B = np.zeros(A.shape) 
    for e in L: 
     B[A==e] = 1 
    return B 

%timeit np.in1d(A, L).reshape(A.shape).astype(int) 
# 100 loops, best of 3: 6.4 ms per loop 

%timeit loop() 
# 100 loops, best of 3: 16.8 ms per loop 

%timeit np.apply_along_axis(np.in1d, 1, A, L).astype(int) 
# 10 loops, best of 3: 21.5 ms per loop 

%timeit np.apply_along_axis(np.in1d, 0, A, L).astype(int) 
# 10 loops, best of 3: 35.1 ms per loop 

Результат проверки:

B1 = loop() 
B2 = np.apply_along_axis(np.in1d, 0, A, L).astype(int) 
B3 = np.apply_along_axis(np.in1d, 1, A, L).astype(int) 
B4 = np.in1d(A, arrL).reshape(A.shape).astype(int) 

(B1 == B2).all() 
# True 

(B1 == B3).all() 
# True 

(B1 == B4).all() 
# True 
+0

Мои результаты синхронизации при условии, другой рассказ , Я использую python 3.5 и numpy 1.10.4 из anaconda, а исходный цикл примерно в 3 раза быстрее, чем использование in1d. EDIT: Теперь я вижу, что вы использовали случайную матрицу 1000x1000. Я буду повторять с такой же матрицей. –

+0

@ HAL9001 Я просто тестировал на python 3, я получаю довольно последовательный результат. Первый вариант np.in1d ​​выполняется быстрее. Насколько велик массив, который вы тестируете? – Psidom

+0

Результаты Psidom были подтверждены при использовании 1000x1000. –

2

Использование @ 1000x1000 матрицы Psidom, я ввел два других методов, и включал в себя np.in1d метод, который @Psidom при условии.

Используется итеративная сумма, другая - итеративная побитовая или.

Итеративный побитовый или, trial2(), доказывает себя ниже, обеспечивая результат, который примерно в 4 раза быстрее оригинала и в 2 раза быстрее, чем num3 in3d, однако обратите внимание, что он обеспечивает результат матрицы, который имеет тип boolean.

Когда побитовый метод изменен, чтобы вернуть целочисленный результат, trial2_int(), его скорость в основном эквивалентнаnumpy.

A = np.random.randint(0,10,(1000,1000)) 
L = [3,4,5] 
def original(): 
    B = np.zeros(A.shape) 
    for e in L: 
     B[A==e] = 1 
    return B 

def trial1(): 
    B = np.empty(A.shape) 
    for e in L: 
    B += A == e 
    return B 

def trial2(): 
    B = A==L[0] 
    for e in L[1:]: 
    B |= A == e 
    return B 

def trial2_int(): 
    B = trial2() 
    return B.astype(int) 

def trial_Psidom(): 
    B = np.in1d(A,L).reshape(A.shape).astype(int) 
    return B 

Результаты:

%timeit original() 
# 100 loops, best of 3: 10.5 ms per loop 
%timeit trial1() 
# 100 loops, best of 3: 9.43 ms per loop 
%timeit trial2() 
# 100 loops, best of 3: 2.37 ms per loop 
%timeit trial2_int() 
# 100 loops, best of 3: 5.31 ms per loop 
%timeit trial_Psidom() 
# 100 loops, best of 3: 5.37 ms per loop  
+0

Если 'L' является малым относительно' A', 'np.in1d' делает raveled версию вашего' trial2' - итерацию на 'L' и используйте' B | = ... '. – hpaulj

3

Похоже, он падает мне указать на очевидное:

def AinL(A, L): 
    B = np.zeros((10,), int) 
    B[L] = 1 
    return B[A] 

контрольные показатели:

10x10 #L=3 
orig  0.6665631101932377 
HAL  0.4370500799268484 
Psidom 1.13961720908992 
PP  0.23527960386127234 

100x100 #L=3 
orig  0.3015591569710523 
HAL  0.29902734607458115 
Psidom 0.4470538650639355 
PP  0.18963343487121165 

1000x1000 #L=4 
orig  0.5516874771565199 
HAL  0.5967503408901393 
Psidom 0.6331975681241602 
PP  0.23225238709710538 

10000x1000 #L=2 
orig  0.8539429588709027 
HAL  0.9840140701271594 
Psidom 1.0392512339167297 
PP  0.7203555379528552 
Смежные вопросы