I have a 1D-array, that I want to transform into a 2D-array, where in row i the original 1D is rolled by i steps. I implemented it like this
import numpy as np
data=np.arange(0,10,2)
rolling=np.arange(len(data))
array=np.array([np.roll(data,-i) for i in rolling])
array
array([[0, 2, 4, 6, 8],
[2, 4, 6, 8, 0],
[4, 6, 8, 0, 2],
[6, 8, 0, 2, 4],
[8, 0, 2, 4, 6]])
For later purposes I would like to have the rolling in a way, such that the array is not rolled over edge, and the respective values are replaced by something else, for example np.nan
.
My intended output is
array([[0, 2, 4, 6, 8],
[2, 4, 6, 8, np.nan],
[4, 6, 8, np.nan, np.nan],
[6, 8, np.nan, np.nan, np.nan],
[8, np.nan, np.nan, np.nan, np.nan]])
The data is not necessarily as uniform as in this example, so a detection of the edge is not possible as it would be in the example. I tried around with padding, but it is neither short nor convenient, since every row would need a different padding. Also I was thinking about np.tril
or np.triu
, but those worked only for the main diagonal, but the rolling edge is not along the main diagonal.
In this example it is on the counter diagonal, but that might shift in the real example, which would look like
array=np.array([np.roll(data,-i+manualshift) for i in rolling])
EDIT: Additional example
If I introduce a larger matrix and introduce an additional shift like this
data=np.arange(0,20,2)
rolling=np.arange(len(data))
manualshift=3
array=np.array([np.roll(data,-i+manualshift) for i in rolling])
then the array would look like this:
array([[nan, nan, nan, 0, 2, 4, 6, 8, 10, 12],
[nan, nan, 0, 2, 4, 6, 8, 10, 12, 14],
[nan, 0, 2, 4, 6, 8, 10, 12, 14, 16],
[ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18],
[ 2, 4, 6, 8, 10, 12, 14, 16, 18, nan],
[ 4, 6, 8, 10, 12, 14, 16, 18, nan, nan],
[ 6, 8, 10, 12, 14, 16, 18, nan, nan, nan],
[ 8, 10, 12, 14, 16, 18, nan, nan, nan, nan],
[10, 12, 14, 16, 18, nan, nan, nan, nan, nan],
[12, 14, 16, 18, nan, nan, nan, nan, nan, nan]])
EDIT END
Is there a short solution for this?