Skip to content

rolling.construct alignment #3671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mark-boer opened this issue Jan 8, 2020 · 4 comments
Closed

rolling.construct alignment #3671

mark-boer opened this issue Jan 8, 2020 · 4 comments

Comments

@mark-boer
Copy link
Contributor

mark-boer commented Jan 8, 2020

Hello xarray team

I was trying to implement functionality similar to Scikit Image's view_as_windows, but I was having a hard time with the boundary conditions. I understand this request is very similar to rolling with periodic boundary conditions #2007.

MCVE Code Sample

>>> arr = xr.DataArray(np.arange(4), dims=("x",))
>>> arr.rolling(x=2).construct("roll_x", stride=2)
<xarray.DataArray (x: 2, roll_x: 2)>
array([[nan,  0.],
       [ 1.,  2.]])
Dimensions without coordinates: x, roll_x

Expected Output

It would be nice to be able to easily get an output of:

<xarray.DataArray (x: 2, roll_x: 2)>
array([[0., 1.],
       [2., 3.]])
Dimensions without coordinates: x, roll_x

Possible workarounds

With the upcoming features of pad (#3596) and rolling: periodic (#2011) it is actually not that hard to work around with:

arr.pad(x=(1,0)).rolling(x=2).construct("roll_x", stride=2).isel(x=slice(1,None))
# or
arr.roll(x=-1).rolling(x=2, boundary="periodic").construct("roll_x", stride=2)

Idea

Would it be possible to add a keyword argument to either rolling() or construct() that expects an alignment of "left", "right" or "center". I understand that this could break interface copied from Pandas, but I hope it could be useful to others as well.

@mark-boer
Copy link
Contributor Author

Small update:

I was currently using:

data = (
    data.rolling(x=window_size ).construct("roll_x")
    .rolling(y=window_size ).construct("roll_y")
    .isel(x=slice(window_size - 1, None, stride), y=slice(window_size - 1, None, stride))
    .stack(n=("x", "y"))
)

but this was performing quite badly for larger arrays. However after having a look at DataArrayRolling and rewriting this piece of code to the following, performance was good.

data = (
    data.rolling(x=window_size ).construct("roll_x")
    .isel(x=slice(window_size - 1, None, stride))
    .rolling(y=window_size ).construct("roll_y")
    .isel(y=slice(window_size - 1, None, stride))
    .stack(n=("x", "y"))
)

I saw that DataArrayRolling.construct() also uses a slice (isel) to create the strided array, so there is not much of a performance penalty of first creating a rolling window with stride 1 and then slicing the data.

However, if you want to add strides to the 'Strided rolling' (#3607) it would be nice to still be able to create rolling windows that start at index 0.

By the way: feel free to close this issue, if you do not see a need for an alignment option.

@fujiisoup
Copy link
Member

Hi @mark-boer for raising an issue.
I am not sure if I got the point exactly, but the following is similar to what you want?

In [81]: arr = xr.DataArray(np.arange(4), dims=("x",)) 
    ...: arr.rolling(x=2).construct("roll_x").isel(x=slice(1, None, 2))        
Out[81]: 
<xarray.DataArray (x: 2, roll_x: 2)>
array([[0., 1.],
       [2., 3.]])
Dimensions without coordinates: x, roll_x

@mark-boer
Copy link
Contributor Author

Hi @fujiisoup, thx for your response.

That is exactly what I needed and what I used to do. But I mistakenly thought that there was a performance penalty to doing this. But the performance decrease turned out to be the result of the order in which I rolled and sliced.

@fujiisoup
Copy link
Member

But I mistakenly thought that there was a performance penalty to doing this.

Yes, construct(stride=2) does exactly the same thing before returning an array.

return result.isel(**{self.dim: slice(None, None, stride)})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants