Прежде чем пытаться использовать лучшие / альтернативные итераторы, вы должны попытаться выполнить задачу без итерации (то есть сделать что-то с скомпилированным numpy
кодом)
In [347]: arr = np.random.randint(-40,40,(2,3,4))
Например, есть метод clip
:
In [348]: arr.clip(-20, 20)
Out[348]:
array([[[-20, -20, 20, -6],
[-15, -17, -8, -20],
[ 2, -20, -16, 20]],
[[-20, 3, -20, 17],
[ 20, 20, 20, -17],
[ 11, -20, 20, 0]]])
и деление всего на 20 тривиально в numpy
:
In [349]: _/20
Out[349]:
array([[[-1. , -1. , 1. , -0.3 ],
[-0.75, -0.85, -0.4 , -1. ],
[ 0.1 , -1. , -0.8 , 1. ]],
[[-1. , 0.15, -1. , 0.85],
[ 1. , 1. , 1. , -0.85],
[ 0.55, -1. , 1. , 0. ]]])
Еще лучше, научитесь делать подобные вещи с логическим маскированием:
In [351]: arr
Out[351]:
array([[[-32, -30, 39, -6],
[-15, -17, -8, -34],
[ 2, -31, -16, 35]],
[[-39, 3, -37, 17],
[ 31, 30, 28, -17],
[ 11, -24, 26, 0]]])
In [354]: mask1 = arr<-20
In [355]: mask2 = arr>20
In [356]: mask1
Out[356]:
array([[[ True, True, False, False],
[False, False, False, True],
[False, True, False, False]],
[[ True, False, True, False],
[False, False, False, False],
[False, True, False, False]]])
In [357]: mask2
Out[357]:
array([[[False, False, True, False],
[False, False, False, False],
[False, False, False, True]],
[[False, False, False, False],
[ True, True, True, False],
[False, False, True, False]]])
In [358]: arr[mask1]=-20
In [359]: arr[mask2]=20
In [360]: arr
Out[360]:
array([[[-20, -20, 20, -6],
[-15, -17, -8, -20],
[ 2, -20, -16, 20]],
[[-20, 3, -20, 17],
[ 20, 20, 20, -17],
[ 11, -20, 20, 0]]])
Что касается вашей итерации, важно помнить, что в любой итерации Python вы не можете использовать
для х в ...:
х = -20,0
чтобы изменить источник. Это присваивание x=...
присваивает новое значение переменной x
и разрывает ее связь с итерацией. Попробуйте это с простым списком, если вы не понимаете, почему. Вы должны изменить переменную на месте. Если x
- простое целое число, которое невозможно.
На первой итерации вы индексируете и изменяете all_frames_flow
, так что это работает:
all_frames_flow [counter1] [counter2, counter3, counter4] = - 20,0
nditer
предоставляет изменяемую переменную итерации, поэтому вы можете сделать:
In [364]: with np.nditer(arr, op_flags=['readwrite'], order = 'K') as it:
...: for x in it:
...: #print x
...: if (x < -20.0):
...: x[...]=-20.0 # change x in-place
...: if (x > 20.0):
...: x[...] = 20.0
...:
Все nditer
примеры, которые изменяют значения, должны использовать эту запись [...]=
.
Я не рекомендую использовать nditer
, по крайней мере, не код Python. В коде Python это наиболее полезно как способ тестирования идей, которые будут реализованы в вашем собственном скомпилированном коде (с cython
). Это не дает никаких преимуществ в скорости.