Home > database >  Numpy: chained boolean indexing not properly updating boolean array without using np.where
Numpy: chained boolean indexing not properly updating boolean array without using np.where

Time:07-01

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
  • Related