I have an 3D array that is a mask. Additionally, I have some indices that encode where (array position) some values should be saved.
Everything seems to be working fine, except that the output matrix is still empty after assigning the values to the desired positions.
I can not see what I am missing here. I have also tried numpy.put
with no luck.
import numpy as np
# Initialize output matrix (here the results will be stored)
results = np.zeros((67, 67, 45))
# define the mask - where to put the calculated values in the results array
mask = np.random.randint(2, size=(67, 67, 45)).astype(bool)
# store the results only in these positions
index_keep = range(0, 13732)
values = np.ones((13732,))
results[mask][index_keep] = values.copy()
# the results array is still empty
print(results.sum())
#0
When you index an array with a boolean mask, the elements are extracted and placed into a 1-D array. This pretty much had to be the case, since the selected elements of the mask are not evenly space across our within any dimension. The expression results[mask] = value
is equivalent to results.__setitem__(mask, value)
: clearly an in-place modification on result
. However results[mask][index_keep] = value
is equivalent to result.__getitem__(mask).__setitem__(index_keep, value)
. The in-place operation happens on a temporary array that is completely discarded.
The solution is to play with the index to get a single call to __setitem__
on the object you want. One way to do that is to apply index_keep
to mask
. You would first have to convert mask
to linear indices, e.g. with np.flatnonzero
:
result.ravel()[np.flatnonzero(mask)[index_keep]] = value
This will work as long as ravel
returns a view, which it should in most cases. If result
is a contiguous array, this will work all the time. It wont work if result
is already a subset of a larger array.
This approach has the advantage that it uses only a single index array, and it works for any number of dimensions. Using np.where
could be adapted to do the same, but would require more temporary storage. The disadvantage is of course that this approach is limited to contiguous arrays.
P.S. You almost certainly don't need to copy value
. Its elements won't be modified, and the assignment will already make the copy into the appropriate locations of result
. Making a copy just creates a needless temporary array that will be discarded immediately.
You can use numpy.where
on your mask
, which will allow you to get a view of your results
array to index.
x, y, z = np.where(mask)
results[x[index_keep], y[index_keep], z[index_keep]] = values
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With