I need to re-insert previously deleted elements in an array. The case scenario is one in which I need to minimize a loss function over a set of parameters, after fixing a subset of them. The minimizer only takes the remaining unfixed subset but I need to pass the entire set of parameters to the function to be minimized.
I thought of using np.delete with an index of the elements to exclude, and then use np.insert to undo it with the same logic, but the following does NOT work being np.insert and np.delete not symmetric in how they operate:
import numpy as np
pars = np.array([0,10,20,30,40,50])
exclude = [1,3] # index of elements to exclude
parsSubset = np.delete(pars,exclude)
excludedPars = pars[exclude]
parsRecreated = np.insert(parsSubset,exclude,excludedPars)
print(parsRecreated)
the output of such code is [ 0 10 20 40 30 50]
I include my solution below, but I wonder if there is a more elegant solution I am missing
CodePudding user response:
Here is my solution, creating a mask and using it to re-insert:
import numpy as np
pars = np.array([0,10,20,30,40,50])
exclude = [1,3] # index of elements to exclude
mask = np.array([True] * pars.size)
mask[exclude] = False
parsSubset = pars[mask]
parsRecreated = np.zeros(pars.size)
parsRecreated[mask] = parsSubset
parsRecreated[~mask] = pars[~mask]
print(parsRecreated)
CodePudding user response:
In [24]: pars = np.array([0,10,20,30,40,50])
...: exclude = [1,3] # index of elements to exclude
...:
...: parsSubset = np.delete(pars,exclude)
In [25]: pars
Out[25]: array([ 0, 10, 20, 30, 40, 50])
In [26]: parsSubset
Out[26]: array([ 0, 20, 40, 50])
In [27]: np.insert(parsSubset,exclude,100)
Out[27]: array([ 0, 100, 20, 40, 100, 50])
delete
removes these items from pars
:
In [33]: pars[exclude]
Out[33]: array([10, 30])
insert
adds items before these items in parsSubset
:
In [34]: parsSubset[exclude]
Out[34]: array([20, 50])
insert
works with respect to the current array, not the target array. Internally it does take into account that once an item is inserted before 20
, the nest insertion point will be shifted. In fact there's a line in its code
indices[order] = np.arange(numnew)
We can compensate for that with our own subtraction:
In [36]: np.insert(parsSubset,exclude-np.arange(2),100)
Out[36]: array([ 0, 100, 20, 100, 40, 50])
Internally delete
and insert
are complex since they can work with differing dimensions, and different kinds of inputs (scalar, slices, sequences). But with sequences like this, both work with a mask much as you do. There's nothing wrong with your solution, and quite possibly it is faster (without the general overhead).