Ноль или точка с произвольным оператором

Я хотел бы использовать что-то вроде np.dot или (предпочтительно) np.einsum эффективно выполнять ту же функцию, но с альтернативным ufunc вместо np.multiply, Например, рассмотрим эти два массива:

>>> a
array([[0, 1],
       [1, 1],
       [1, 0]])
>>> b
array([[0, 0],
       [1, 0],
       [1, 0],
       [0, 0]])

Теперь предположим, что я хочу посчитать количество элементов в каждой строке a равны соответствующим элементам в каждом ряду b, Я хотел бы иметь возможность сделать эквивалент следующего (примечание: выходные данные ниже сфабрикованы, но значения - это то, что я ожидал бы увидеть):

>>> np.dot(a, b.T, ufunc=np.equal)
array([[1, 0, 0, 1],
       [0, 1, 1, 0],
       [1, 2, 2, 1]])

Есть ли способ сделать это?

3 ответа

Решение

Вы можете использовать трансляцию из ответа Дивакара вместе с Numberxpr:

numexpr.evaluate('sum(1*(a == b), axis=2)', {'a': a[:,None]})

1*() это обходной путь. Я подтвердил, что это не выделяет большой временный массив.

Есть старая проблема на NumPy GitHub с просьбой об обобщении einsum это позволило бы использовать другие функции. Текущая версия просто реализует сумму продуктов. Насколько я знаю, никто не взялся за этот проект.

Несколько лет назад я залатал einsumисправление обработки обозначения "...". Так что у меня есть хорошее представление о том, как это реализовано; и, возможно, мог бы адаптировать мой эмулятор Python / cython, чтобы добавить эту функцию. Настоящий einsum код написан на c,

Я думаю, что если вам не нравится подход Divakar, вам придется написать свою собственную версию с cython,

Вы могли бы использовать broadcasting для такой задачи подсчета совпадений -

(a[:,None] == b).sum(2)

Пробный прогон -

In [36]: a
Out[36]: 
array([[0, 1],
       [1, 1],
       [1, 0]])

In [37]: b
Out[37]: 
array([[0, 0],
       [1, 0],
       [1, 0],
       [0, 0]])

In [38]: (a[:,None] == b).sum(2)
Out[38]: 
array([[1, 0, 0, 1],
       [0, 1, 1, 0],
       [1, 2, 2, 1]])

Если вы действительно хотите нанять np.einsum а также np.equal вот способ сформировать более ранний подход, чтобы дать нам желаемый результат -

np.einsum('ijk->ij',np.equal(a[:,None],b).astype(int))
Другие вопросы по тегам