У меня есть двумерный массив NumPy, и я хотел бы заменить все значения в нем, превышающие или равные пороговому значению T, на 255,0. Насколько мне известно, самый фундаментальный путь будет:
shape = arr.shape
result = np.zeros(shape)
for x in range(0, shape[0]):
for y in range(0, shape[1]):
if arr[x, y] >= T:
result[x, y] = 255
Какой самый лаконичный и питонный способ сделать это?
Есть ли более быстрый (возможно, менее лаконичный и / или менее питонический) способ сделать это?
Это будет частью процедуры настройки окна / уровня для МРТ-сканирования головы человека. Двумерный массив - это данные пикселей изображения.
Ответы:
Я думаю, что самый быстрый и краткий способ сделать это - использовать встроенную в NumPy индексацию Fancy. Если у вас есть
ndarray
имяarr
, вы можете заменить все элементы>255
значениемx
следующим образом:Я запустил это на своей машине со случайной матрицей 500 x 500, заменив все значения> 0,5 на 5, и это заняло в среднем 7,59 мс.
источник
arr
, а не создаетresult
массив, как в OP.A
но создавая новый массив?np.array([1,2,3]
)Так как вы на самом деле хотите другой массив, который находится
arr
гдеarr < 255
и в255
противном случае, это можно сделать просто:В целом, для нижней и / или верхней границы:
Если вы просто хотите получить доступ к значениям свыше 255 или к чему-то более сложному, ответ @ mtitan8 является более общим, но
np.clip
иnp.minimum
(илиnp.maximum
) более приятным и быстрым для вашего случая:Если вы хотите сделать это на месте (т.е. изменить
arr
вместо созданияresult
), вы можете использоватьout
параметрnp.minimum
:или
(
out=
имя является необязательным, поскольку аргументы в том же порядке, что и определение функции.)Для модификации на месте логическое индексирование значительно ускоряется (без необходимости создавать и затем изменять копию отдельно), но все же не так быстро, как
minimum
:Для сравнения, если вы хотите ограничить свои значения как минимумом, так и максимумом, без этого
clip
вам придется делать это дважды, с чем-то вродеили,
источник
a[start:stop:step]
выдает элементы массива отstart
tostop
, но вместо каждого элемента он принимает только каждыйstep
(если пренебречь,1
по умолчанию ). Таким образом, чтобы установить все вечера на ноль, вы можете сделатьa[::2] = 0
Я думаю, что вы можете достичь этого быстрее, используя
where
функцию:Например, ищем элементы больше 0,2 в массиве numpy и заменяем их на 0:
источник
Вы можете рассмотреть возможность использования numpy.putmask :
Вот сравнение производительности со встроенной индексацией Numpy:
источник
Другой способ - использовать
np.place
замену на месте и работать с многомерными массивами:источник
np.place
также был медленнее по сравнению со встроенным методом, хотя в этом комментарии утверждается обратное .Вы можете также использовать
&
,|
(и / или) для большей гибкости:значения между 5 и 10:
A[(A>5)&(A<10)]
значения больше 10 или меньше 5:
A[(A<5)|(A>10)]
источник