Starting with Divaker's padded x
N = 4 # width factor
x_ext = np.concatenate((x,[None]*(N-1)))
Since we aren't doing math on it, padding with None (which makes an object array) or np.nan
(which makes a float) shouldn't make much difference.
The column stack could be eliminated with a little change to the indexing:
idx = np.r_[0,np.arange(N)] + np.arange(x_ext.size-N+1)[:,None]
this produces
array([[ 0, 0, 1, 2, 3],
[ 1, 1, 2, 3, 4],
[ 2, 2, 3, 4, 5],
[ 3, 3, 4, 5, 6],
[ 4, 4, 5, 6, 7],
...
so the full result is
x_ext[idx]
================
A different approach is to use striding to create a kind of rolling window.
as_strided = np.lib.stride_tricks.as_strided
arr2D = as_strided(x_ext, shape=(15,4), strides=(4,4))
This is one of easier applications of as_strided
. shape
is straight forward - the shape of the desired result (without the repeat column) (x.shape[0],N)
.
In [177]: x_ext.strides
Out[177]: (4,)
For 1d array of this type, the step to the next item is 4 bytes. If I reshape the array to 2d with 3 columns, the stride to the next row is 12 - 3*4 (3 offset).
In [181]: x_ext.reshape(6,3).strides
Out[181]: (12, 4)
Using strides=(4,4)
means that the step to next row is just 4 bytes, one element in original.
as_strided(x_ext,shape=(8,4),strides=(8,4))
produces a 2 item overlap
array([[58, 56, 54, 52],
[54, 52, 50, 48],
[50, 48, 46, 44],
[46, 44, 42, 40],
....
The potentially dangerous part of as_strided
is that it is possible to create an array that samples memory outside of the original data buffer. Usually that appears as large random numbers where None
appears in this example. It's the same sort of error that you would encounter if C code if you were careless in using array pointers and indexing.
The as_strided
array is a view (the repeated values are not copied). So writing to that array could be dangerous. The column_stack
with x
will make a copy, replicating the repeated values as needed.