Skip to content

Commit

Permalink
WIP: allow border results in DataArrayRolling.reduce
Browse files Browse the repository at this point in the history
* When reducing over a rolling window, DataArrayRolling.reduce()
  only returns values where the complete rolling window is fully
  conatined within the base array; the remaining locations where
  the window overlaps the array border are filled with NaN
* However, in some situations, it is desirable to obtain values from the
  reducer function for all locations.  This commit adds a keyword
  argument, `include_border`, to `DataArrayRolling.reduce()` and
  `DataSetRolling.reduce()` to allow this behavior.
  • Loading branch information
kmsquire committed May 16, 2019
1 parent bd78b7f commit 4ec82e1
Showing 1 changed file with 35 additions and 3 deletions.
38 changes: 35 additions & 3 deletions xarray/core/rolling.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def construct(self, window_dim, stride=1, fill_value=dtypes.NA):
coords=self.obj.coords)
return result.isel(**{self.dim: slice(None, None, stride)})

def reduce(self, func, **kwargs):
def reduce(self, func, include_border=False, **kwargs):
"""Reduce the items in this group by applying `func` along some
dimension(s).
Expand All @@ -204,18 +204,46 @@ def reduce(self, func, **kwargs):
Function which can be called in the form
`func(x, **kwargs)` to return the result of collapsing an
np.ndarray over an the rolling dimension.
include_border : boolean, False
Include results where the rolling window partially falls outside
of the array border. If False, these locations contain np.nan.
**kwargs : dict
Additional keyword arguments passed on to `func`.
Returns
-------
reduced : DataArray
Array with summarized data.
Examples
--------
>>> da = DataArray(np.arange(8).reshape(2, 4), dims=('a', 'b'))
>>>
>>> rolling = da.rolling(b=3)
>>> rolling.construct('window_dim')
<xarray.DataArray (a: 2, b: 4, window_dim: 3)>
array([[[np.nan, np.nan, 0], [np.nan, 0, 1], [0, 1, 2], [1, 2, 3]],
[[np.nan, np.nan, 4], [np.nan, 4, 5], [4, 5, 6], [5, 6, 7]]])
Dimensions without coordinates: a, b, window_dim
>>>
>>> rolling.reduce(np.sum)
<xarray.DataArray (a: 2, b: 4)>
array([[nan, nan, 3., 6.],
[nan, nan, 15., 18.]])
Dimensions without coordinates: a, b
>>>
>>> rolling.reduce(np.nansum, include_border=True)
<xarray.DataArray (a: 2, b: 4)>
array([[ 0., 1., 3., 6.],
[ 4., 9., 15., 18.]])
"""
rolling_dim = utils.get_temp_dimname(self.obj.dims, '_rolling_dim')
windows = self.construct(rolling_dim)
result = windows.reduce(func, dim=rolling_dim, **kwargs)

if include_border:
return result

# Find valid windows based on count.
counts = self._counts()
return result.where(counts >= self._min_periods)
Expand Down Expand Up @@ -347,7 +375,7 @@ def __init__(self, obj, windows, min_periods=None, center=False):
self.rollings[key] = DataArrayRolling(
da, windows, min_periods, center)

def reduce(self, func, **kwargs):
def reduce(self, func, include_border=False, **kwargs):
"""Reduce the items in this group by applying `func` along some
dimension(s).
Expand All @@ -357,6 +385,9 @@ def reduce(self, func, **kwargs):
Function which can be called in the form
`func(x, **kwargs)` to return the result of collapsing an
np.ndarray over an the rolling dimension.
include_border : boolean, False
Include results where the rolling window partially falls outside
of the array border. If False, these locations contain np.nan.
**kwargs : dict
Additional keyword arguments passed on to `func`.
Expand All @@ -369,7 +400,8 @@ def reduce(self, func, **kwargs):
reduced = OrderedDict()
for key, da in self.obj.data_vars.items():
if self.dim in da.dims:
reduced[key] = self.rollings[key].reduce(func, **kwargs)
reduced[key] = self.rollings[key].reduce(
func, include_border=include_border, **kwargs)
else:
reduced[key] = self.obj[key]
return Dataset(reduced, coords=self.obj.coords)
Expand Down

0 comments on commit 4ec82e1

Please sign in to comment.