In any Python iteration,
for x in np.nditer(A):
x = (x - minimum)/(maximum - minimum)
assigning a value to the iteration variable changes its reference, and does not modify the original list/array.
I tried
for x in np.nditer(A):
x[:] = (x - minimum)/(maximum - minimum)
but got an error
ValueError: assignment destination is read-only
I have to go to the nditer
documentation, https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.nditer.html#arrays-nditer to find out how to change it to a read/write variable
In [388]: def normalize_min_max(A, axis = None):
...: ptr = axis
...: minimum = np.amin(A, ptr)
...: maximum = np.amax(A, ptr)
...: for x in np.nditer(A, op_flags=['readwrite']):
...: x[...] = (x - minimum)/(maximum - minimum)
...: return A
...:
...:
In [389]: normalize_min_max(np.arange(10))
Out[389]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
Oops, the original array is integer
In [390]: normalize_min_max(np.arange(10.))
Out[390]:
array([ 0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])
But I don't need to iterate to perform this kind of calculation:
In [391]: def normalize_min_max1(A, axis = None):
...: ptr = axis
...: minimum = np.amin(A, ptr, keepdims=True)
...: maximum = np.amax(A, ptr, keepdims=True)
...: return (A-minimum)/(maximum-minimum)
In [392]: normalize_min_max1(np.arange(10.))
Out[392]:
array([ 0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])
nditer
does work in this context because the iteration variable is modifiable, where as it isn't with for x in A: ...
. But otherwise it's a complex iterator, and does not offer any speed advantages. As shown on the nditer
tutorial page, it is most useful as a stepping stone to using nditer
in cython
.
Also your nditer
code does not work with axis values. Mine, with the keep_dims
parameter works:
In [396]: normalize_min_max1(np.arange(10.).reshape(5,2),0)
Out[396]:
array([[ 0. , 0. ],
[ 0.25, 0.25],
[ 0.5 , 0.5 ],
[ 0.75, 0.75],
[ 1. , 1. ]])
In [397]: normalize_min_max1(np.arange(10.).reshape(5,2),1)
Out[397]:
array([[ 0., 1.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.]])
In [398]: normalize_min_max1(np.arange(10.).reshape(5,2),None)
Out[398]:
array([[ 0. , 0.11111111],
[ 0.22222222, 0.33333333],
[ 0.44444444, 0.55555556],
[ 0.66666667, 0.77777778],
[ 0.88888889, 1. ]])
The nditer
code with an axis value:
In [395]: normalize_min_max(np.arange(10.).reshape(5,2),0)
...
ValueError: could not broadcast input array from shape (2) into shape ()
The nditer
variable is a 0d array, which allows it to be modified. But that complicates using it with the min/max values which may be arrays. We'd have to include those arrays in the nditer
setup. So it's possible, but normally not worth the extra work.