#numpy
#numpy
Вопрос:
Вот MWE, который иллюстрирует проблему, с которой я столкнулся:
import numpy as np
arr = np.full((3, 3), -1, dtype="i,i")
doesnt_work = arr == (-1, -1)
n_arr = np.full((3, 3), -1, dtype=int)
works = n_arr == 10
arr
предполагается, что это массив кортежей, но он ведет себя не так, как ожидалось.
works
это массив логических значений, как и ожидалось, но doesnt_work
есть False
. Есть ли способ заставить numpy выполнять поэлементные сравнения для более сложных типов, или мне нужно прибегнуть к пониманию списка, сглаживанию и изменению формы?
Есть вторая проблема:
f = arr[(0, 0)] == (-1, -1)
f
является False
, потому arr[(0,0)]
что имеет тип numpy.void
, а не кортеж. Таким образом, даже если бы сравнение по компонентам сработало, это дало бы неверный результат. Есть ли умный numpy способ сделать это или я должен просто прибегнуть к пониманию списка?
Комментарии:
1. Обратите внимание, что вы можете использовать Numpy views для переноса представления массива заданного типа в другой тип, чтобы сравнение работало (как объясняется в ответе Саймона).
2.
numpy
используется()
для обозначенияrecords
структурированного массива, но это для того, чтобы отличать их от[]
используемых для обозначения измерений. Таким образом, while()
используется для ввода и отображения, вы должны использоватьarr[0,0].item()
для получения фактическогоtuple
.
Ответ №1:
Обе проблемы на самом деле являются одной и той же проблемой! И оба связаны с пользовательским типом данных, который вы создали при указании dtype="i,i"
.
Если вы запустите arr.dtype
, вы получите dtype([('f0', '<i4'), ('f1', '<i4')])
. Это 2 целых числа со знаком, которые помещаются в один непрерывный блок памяти. Это не кортеж python. Таким образом, понятно, почему наивное сравнение завершается неудачей, поскольку (-1,-1)
является кортежем python и не представлен в памяти так же, как тип данных numpy.
Однако, если вы сравните с a_comp = np.array((-1,-1), dtype="i,i")
, вы получите точное поведение, которое вы ожидаете!
Вы можете прочитать больше о том, как работает пользовательский dtype, в документах numpy: https://numpy.org/doc/stable/reference/arrays.dtypes.html
О, и для решения того, что np.void
есть: это исходит из идеи, что это пустой указатель c, что по сути означает, что это адрес непрерывного блока памяти неопределенного типа. Но, если вы (программист) знаете, что будет храниться в этой памяти (в данном случае два целых числа подряд), все в порядке, если вы будете осторожны (сравните с тем же пользовательским типом данных).