Let me explain it by a small example:
>>> x = np.array([[1,2], [3,4], [5,6], [7,8]])
>>> x
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
I want to have a new array that has the form
array([[0, 0, 1, 2, 3, 4],
[1, 2, 3, 4, 5, 6],
[3, 4, 5, 6, 7, 8],
[5, 6, 7, 8, 0, 0]])
Here, the context has the size +/-1, but I’d like to keep it variable.
What I’m doing so far is appending zeros to the original array:
>>> y = np.concatenate((np.zeros((1, 2)), x, np.zeros((1, 2))), axis=0)
>>> y
array([[ 0., 0.],
[ 1., 2.],
[ 3., 4.],
[ 5., 6.],
[ 7., 8.],
[ 0., 0.]])
And putting the values into a new array by reading rows of the new size:
>>> z = np.empty((x.shape[0], x.shape[1]*3))
>>> for i in range(x.shape[0]): z[i] = y[i:i+3].flatten()
That kind of works, but I find it slow, ugly and unpythonic.
Can you think of a better way to do this rearrangement? Additional thumbsup for an in-place-ish solution 🙂
There is the option of using
stride_tricks, but I will not say that this is the best answer, because while it is “the most efficient way”, that way is not always the best when considering readability and that it is playing with fire.Note that
zhere is only a view, so usez.copy()to avoid any unexpected things before editing it, otherwise in your example all 1s will change if you edit one of them. On the up side, if you mean this by “in-place”, you can now change elements inyandzwill change too.If you want to do more of this magic, maybe check out my
rolling_windowfunction from https://gist.github.com/3430219, which replaces the last line with:Important:
np.lib.stride_tricks.as_stridedby itself is generally not safe and must be used with care as it can create segmentation faults.