A simpler 2d case:
In [48]: index1=np.array([1,1,2,2,3,3,4,4]);
index2=np.array([0,2,1,2,3,4,4,5])
In [49]: data=np.arange(1,9)
In [50]: target=np.zeros((5,6))
In [53]: target[index1,index2]=data
In [54]: target
Out[54]:
array([[ 0., 0., 0., 0., 0., 0.],
[ 1., 0., 2., 0., 0., 0.],
[ 0., 3., 4., 0., 0., 0.],
[ 0., 0., 0., 5., 6., 0.],
[ 0., 0., 0., 0., 7., 8.]])
If you 'ravel' the indexes, you can use put
or target.flat
:
In [51]: flatindex=np.ravel_multi_index((index1,index2),target.shape)
In [52]: flatindex
Out[52]: array([ 6, 8, 13, 14, 21, 22, 28, 29], dtype=int32)
In [58]: np.put(target,flatindex,data)
In [61]: target.flat[flatindex]=data
Some quick time comparisons (for =data
, not +=data
):
In [63]: timeit target[index1,index2]=data
100000 loops, best of 3: 6.63 µs per loop
In [64]: timeit np.put(target,flatindex,data)
100000 loops, best of 3: 2.47 µs per loop
In [65]: timeit target.flat[flatindex]=data
100000 loops, best of 3: 2.77 µs per loop
In [66]: %%timeit
....: flatindex=np.ravel_multi_index((index1,index2),target.shape)
....: target.flat[flatindex]=data
....:
100000 loops, best of 3: 7.34 µs per loop
target.flat[]=
is the winner - if the raveled index is already available. This could be the case if you are repeatedly applying this calculation with the same index arrays. Keep in mind that timetests on small arrays might not scale the same with big ones.
With +=
instead, put
does not work. flat
has a speed advantage, even when the ravel
has to be calculated:
In [78]: timeit target[index1,index2]+=data
100000 loops, best of 3: 16.2 µs per loop
In [79]: timeit target.flat[flatindex]+=data
100000 loops, best of 3: 7.45 µs per loop
In [80]: %%timeit
flatindex=np.ravel_multi_index((index1,index2),target.shape)
target.flat[flatindex]+=data
....:
100000 loops, best of 3: 13.4 µs per loop
HOWEVER - if the indexes have repeats, and you want all the data
values to be added, the problem changes significantly. Direct indexing like this uses buffering, so only the last addition for a point applies.
See this recent SO question for discussion of this buffering issue and alternatives
Vector operations with numpy