forked from MPAS-Dev/MPAS-Analysis
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add weighted averaging of xarray datasets
This code is based on the proposed solution to an xarray issue: pydata/xarray#422 (comment) that was never incorporated into xarray itself. The results should result in correct masking when NaNs are present whereas the previous weighted averaging was resulting in zeros (because xarray sum treats NaNs as zeros). The method for storing cache files of climatologies has also been updated slightly so the new weighted averaging can be used to compute the agregated climatology from individual (typically yearly) climatologies. It is hoped (but I haven't tested) that this new weighted average will also be faster than the previous implementation.
- Loading branch information
Showing
9 changed files
with
249 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from averaging import xarray_average |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
''' | ||
Weighted averaging for xarray data sets, based on: | ||
https://github.com/pydata/xarray/issues/422#issuecomment-140823232 | ||
Authors | ||
------- | ||
Mathias Hauser (https://github.com/mathause) | ||
Xylar Asay-Davis | ||
''' | ||
|
||
import xarray | ||
|
||
|
||
def xarray_average(data, dim=None, weights=None, **kwargs): # {{{ | ||
""" | ||
weighted average for xarray objects | ||
Parameters | ||
---------- | ||
data : Dataset or DataArray | ||
the xarray object to average over | ||
dim : str or sequence of str, optional | ||
Dimension(s) over which to apply average. | ||
weights : DataArray | ||
weights to apply. Shape must be broadcastable to shape of data. | ||
kwargs : dict | ||
Additional keyword arguments passed on to internal calls to ``mean`` | ||
or ``sum`` (performed on the data set or data array but *not* those | ||
performed on the weights) | ||
Returns | ||
------- | ||
reduced : Dataset or DataArray | ||
New xarray object with average applied to its data and the indicated | ||
dimension(s) removed. | ||
Authors | ||
------- | ||
Mathias Hauser (https://github.com/mathause) | ||
Xylar Asay-Davis | ||
""" | ||
|
||
if isinstance(data, xarray.Dataset): | ||
return _average_ds(data, dim, weights, **kwargs) | ||
elif isinstance(data, xarray.DataArray): | ||
return _average_da(data, dim, weights, **kwargs) | ||
else: | ||
raise ValueError("date must be an xarray Dataset or DataArray") | ||
# }}} | ||
|
||
|
||
def _average_da(da, dim=None, weights=None, **kwargs): # {{{ | ||
""" | ||
weighted average for DataArrays | ||
Parameters | ||
---------- | ||
dim : str or sequence of str, optional | ||
Dimension(s) over which to apply average. | ||
weights : DataArray | ||
weights to apply. Shape must be broadcastable to shape of self. | ||
kwargs : dict | ||
Additional keyword arguments passed on to internal calls to ``mean`` | ||
or ``sum`` (performed on the data set or data array but *not* those | ||
performed on the weights) | ||
Returns | ||
------- | ||
reduced : DataArray | ||
New DataArray with average applied to its data and the indicated | ||
dimension(s) removed. | ||
Authors | ||
------- | ||
Mathias Hauser (https://github.com/mathause) | ||
Xylar Asay-Davis | ||
""" | ||
|
||
if weights is None: | ||
return da.mean(dim, **kwargs) | ||
else: | ||
if not isinstance(weights, xarray.DataArray): | ||
raise ValueError("weights must be a DataArray") | ||
|
||
# if NaNs are present, we need individual weights | ||
if da.notnull().any(): | ||
total_weights = weights.where(da.notnull()).sum(dim=dim) | ||
else: | ||
total_weights = weights.sum(dim) | ||
|
||
return (da * weights).sum(dim, **kwargs) / total_weights # }}} | ||
|
||
|
||
def _average_ds(ds, dim=None, weights=None, **kwargs): # {{{ | ||
""" | ||
weighted average for Datasets | ||
Parameters | ||
---------- | ||
dim : str or sequence of str, optional | ||
Dimension(s) over which to apply average. | ||
weights : DataArray | ||
weights to apply. Shape must be broadcastable to shape of data. | ||
kwargs : dict | ||
Additional keyword arguments passed on to internal calls to ``mean`` | ||
or ``sum`` (performed on the data set or data array but *not* those | ||
performed on the weights) | ||
Returns | ||
------- | ||
reduced : Dataset | ||
New Dataset with average applied to its data and the indicated | ||
dimension(s) removed. | ||
Authors | ||
------- | ||
Mathias Hauser (https://github.com/mathause) | ||
Xylar Asay-Davis | ||
""" | ||
|
||
if weights is None: | ||
return ds.mean(dim, **kwargs) | ||
else: | ||
return ds.apply(_average_da, dim=dim, weights=weights, **kwargs) # }}} | ||
|
||
# vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python |
Oops, something went wrong.