问题
Say I have an array
data = np.arange(6)
I want to find the sum of the entire array and the second half using np.add.reduceat.1
If I do it like this:
np.add.reduceat(data, [0, 6, 3])[::2]
I immediately get an error
IndexError: index 6 out-of-bounds in add.reduceat [0, 6)
If I do it like this
np.add.reduceat(data, [0, 5, 3])[::2]
I get the wrong answer (10 should be 15):
array([10, 12])
The only solution I have been able to come up with is to mask the locations where the last index is necessary, subtract 1 from them, and then add the last element back in there:
index = np.array([0, 6, 3])
mask = (index == data.size)
index[mask] -= 1
result = np.add.reduceat(data, index)
# Mask is shifted back by one because it's the previous element that needs to be updated
result[:-1][mask[1:]] += data[-1]
Then result[::2]
gives the desired answer. This looks like a giant kludge for something that I would expect to be an elegant one-liner (and faster than this).
1 I am fully aware that there are better ways to do this. This is just a contrived example for purposes of illustration. The real problem for this question originated with an attempt to solve numpy: fast regularly-spaced average for large numbers of line segments / points.
回答1:
I haven't used reduceat
much, but it looks like you can only have one open ended range, one add to the end
.
One way around that is to pad the array (yes, I do normally rail against using np.append
:) ):
In [165]: np.add.reduceat(np.append(x,0),[0,6,3])
Out[165]: array([15, 0, 12])
or with a full pairing of ranges:
In [166]: np.add.reduceat(np.append(x,0),[0,6,3,6])
Out[166]: array([15, 0, 12, 0])
I omitted the usual [::2] to clarify what is going on.
来源:https://stackoverflow.com/questions/52319504/how-to-specify-the-last-index-explicitly-to-np-ufunc-reduceat