xarray icon indicating copy to clipboard operation
xarray copied to clipboard

DataArray .rolling() unclear behaviour when center=False

Open juliencarponcy opened this issue 1 year ago • 3 comments

What is your issue?

Hi,

I am using the rolling().construct() method which I found very convenient and efficient.

I had timeseries with 2 dimensions: time and channel. I used the construct to produce small overlapping windows of samples on all channels:

xr_data['full_windowed_eeg'] = xr_data['resampled_eeg'] \
							.rolling(resampled_time=window_size, min_periods=None) \
							.construct("window_tvec", stride=1, keep_attrs=True) \
							.dropna('resampled_time') \
							.rename({'resampled_time':'window_time'}).copy()

However, after not obtaining the result I expected, I found out that the new coord window_time, was corresponding to the original time coords at the end/right of the window, and not as the first time coord of the window as I expected.

There is no argument to specify this apparently, as in its current state, it allows only for taking the "center coord" or the "right coord" (if center=False).

I expect that the way I wanted it is not so uncommon, so implementing that possibility would be great. But more urgently, I would find it extremely useful and avoiding puzzling debbugging if this behaviour was clearly explained in the API reference.

But maybe I am missing something here?

Thanks for your great work !

juliencarponcy avatar Apr 19 '24 13:04 juliencarponcy

Thanks for opening your first issue here at xarray! Be sure to follow the issue template! If you have an idea for a solution, we would really welcome a Pull Request with proposed changes. See the Contributing Guide for more. It may take us a while to respond here, but we really value your contribution. Contributors like you help make xarray better. Thank you!

welcome[bot] avatar Apr 19 '24 13:04 welcome[bot]

I think you're being surprised by the fact that rolling.construct pads with window-1 NaNs at the start of the dimension. This behaviour is not configurable at the moment.

dcherian avatar Apr 19 '24 15:04 dcherian

Indeed, I saw it and get rid of it at one point with dropna(). I guess it is worth mentioning / expliciting a little bit in the docs. The puzzling behaviour, is that for plotting, as per my previous code I have to indroduce an .isel(<3rd_dim>=-1) instead of just .isel(<3rd_dim>=0) if I want to plot signal aligned. More annoying is that if I want to fetch in another DataArray (here 'full_code') based on the newly created time_vector, it fetches data offseted by the window_size. To correct, I'll probably have to introduce a .shift({'window_time': -window_size}) on the time vector created by .construct()

For the plots, I remedy with .isel(<3rd_dim>=-1) instead of just .isel(<3rd_dim>=0) as stated before:

from matplotlib import pyplot as plt
t_before_s = 0.5
t_after_s = 0.5
time_slice = slice(xr_test_data.epoch_onsets[0] + pd.Timedelta(-t_before_s,'s'), xr_test_data.epoch_onsets[0] + pd.Timedelta(t_after_s,'s'))

plt.figure()
xr_test_data['raw_eeg'].sel(time=time_slice, channel='O1').plot.line(x='time', hue='channel')
plt.figure()
xr_test_data['resampled_eeg'].sel(resampled_time=time_slice, channel='O1').plot.line(x='resampled_time', hue='channel')
plt.figure()
xr_test_data['full_code'].sel(resampled_time=time_slice).plot.line(x='resampled_time')
plt.figure()
xr_test_data['windowed_eeg'].sel(window_time=time_slice, channel='O1').isel(window_tvec=-1).plot.line()

I do not feel confident enough to explicit the behaviour of construct() and specify examples by myself for the docs, but will gladly assist and contribute if someone feels like it.

juliencarponcy avatar Apr 19 '24 15:04 juliencarponcy