I'm writing a simple root finder in numpy that is designed to operate on entire numpy arrays simultaneously. The basic idea of the solver is that the array not_converged
is the size of all the data points while newly_converged
is a different array that is the size of the subset of not_coverged that is
True` in that iteration.
I'd like to update the values in the overall not_converged
array to be False
when entries in the newly_converged
array become True
, but doing so using boolean indexing doesn't seem to work as I'd expect:
not_converged = np.array([True, False, True])
# A previously not converged point has now converged
newly_converged = np.array([True, False])
# Now update the converged state
not_converged[not_converged][newly_converged] = False
print(not_converged) # should be [False False True] but the array hasn't been updated
I can get this to work if I use np.where
though:
not_converged = np.array([True, False, True])
# A previously not converged point has now converged
newly_converged = np.array([True, False])
# Now update the converged state
not_converged[not_converged] = np.where(newly_converged, False, True)
print(not_converged) # Correctly updates the state
But I would have thought that the two methods above would yield identical results. Any idea why only the second method works?
CodePudding user response:
The np.where()
is equivalent to the following indexing.
Note that not_converged[not_converged][newly_converged]
is not a view into not_converged
, it's a copy, so nothing should change.
not_converged = np.array([True, False, True])
# A previously not converged point has now converged
newly_converged = np.array([True, False])
# Now update the converged state
not_converged[not_converged] = np.logical_not(newly_converged)
print(not_converged) # should be [False False True] but the array hasn't been updated
CodePudding user response:
This question is similar to one question asked before, as hpaulj comments (1, 2) well explained the reason, you can do this as:
sample = not_converged[not_converged]
sample[newly_converged] = False
not_converged[not_converged] = sample
or in simple way use ~
to invert newly_converged
instead np.logical_not
:
not_converged[not_converged] = ~newly_converged