2016-01-18 2 views
9

В numpy, если я хочу сравнить два массива, скажем, например, я хочу проверить, все ли элементы в A меньше значений в B, я использую if (A < B).all():. Но на практике это требует выделения и оценки полного массива C = A < B, а затем вызывает на нем C.all(). Это немного отходов. Есть ли способ «сократить» сравнение, т. Е. Непосредственно оценить элемент A < B по элементу (без выделения и вычисления временного C) и остановить и вернуть False при обнаружении первого недопустимого сравнения элементов?сравнение ярлыков сравнения массива numpy

+1

Это «отходы» заметно влияют на производительность? – mfitzp

+0

В моем случае не много. Но в целом это может повлиять - я уверен, что выделение дополнительного массива 1000x1000x1000 может повредить вашей производительности. Я спрашивал из простого любопытства, я считаю, что эта краткая оценка будет очень удобной. Есть функция 'allclose()', которая, как мне кажется, прекращается, когда найден первый несогласованный элемент. Поэтому я был удивлен тем, что не нашел «allequal (a, b)», «allless (a, b)» и «allgreater (a, b)», которые, по-моему, будут очень популярны в их использовании, потому что «if (A

+0

Посмотрев на источник numpy, пока я не думаю, что есть поддержка для сокращения A mfitzp

ответ

0

Plain Python and и or использование ярлык оценка, но numpy нет.

(A < B).all() 

numpy использует строительные блоки, вещание, элемент по сравнению с элементом < и all сокращения. < работает только с другими двоичными операциями, плюс, раз и, или, gt, le и т. Д. И all походит на другие методы сокращения, any, max, sum, mean и может работать по всему массиву или по строкам или по колонны.

В одну итерацию можно написать функцию, которая объединяет all и <, но было бы трудно получить общность, о которой я только что описал.

Но если вы должны реализовать итеративное решение с помощью ярлыка и сделать это быстро, я бы предложил разработать идею с помощью nditer, а затем скомпилировать ее с помощью cython.

http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html - хороший учебник по использованию nditer, и вам понадобится использовать его в cython. nditer заботится о вещании и итерации, позволяя вам сосредоточиться на сравнении и любой сокращении.

Вот эскиз итератора, который может быть посажен в cython:

import numpy as np 

a = np.arange(4)[:,None] 
b = np.arange(2,5)[None,:] 
c = np.array(True) 
it = np.nditer([a, b, c], flags=['reduce_ok'], 
    op_flags = [['readonly'], ['readonly'],['readwrite']]) 
for x, y, z in it: 
    z[...] = x<y 
    if not z: 
     print('>',x,y) 
     break 
    else: 
     print(x,y) 
print(z) 

с образцом запуском:

1420:~/mypy$ python stack34852272.py 
(array(0), array(2)) 
(array(0), array(3)) 
(array(0), array(4)) 
(array(1), array(2)) 
(array(1), array(3)) 
(array(1), array(4)) 
('>', array(2), array(2)) 
False 

Start с дефолтом False, и другое break состояния, и вы получите сокращенный any. Обобщение теста для обработки <, <= и т. Д. Будет больше работы.

Получите что-то подобное в Python, а затем попробуйте в Cython. Если у вас возникнут проблемы с этим шагом, вернитесь с новым вопросом. SO имеет хорошую базу пользователей Cython.

1

Насколько велики вы массивы? Я бы предположил, что они очень большие, например. A.shape = (1000000) или больше, прежде чем производительность станет проблемой. Не могли бы вы использовать numpy views?

Вместо сравнения (A < B).all() или (A < B).any() вы можете попробовать определить вид, например (A[:10] < B[:10]).all(). Вот простой цикл, который может работать:

k = 0 
while((A[k*10: (k+1)*10] < B[k*10: (k+1)*10]).all()): 
    k += 1 

Вместо 10 вы можете использовать 100 или 10**3 размер сегмента, который вы хотите. Очевидно, что если размер вашего сегмента равен 1, вы говорите:

k = 0 
while (A[k] < B[k]): 
    k+= 1 

Иногда сравнение всего массива может стать интенсивным. Если A и B имеют длину 10000, и мне нужно сравнить каждую пару элементов, у меня кончится пробел.

+0

Разделение большого массива с представлениями - очень умная идея, поэтому я поддерживаю это. Но это ужасный взлом чего-то, что, я считаю, должно быть естественно в библиотеке numpy. –

Смежные вопросы