Ноль или точка с произвольным оператором
Я хотел бы использовать что-то вроде 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))