-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
rolling_exp (nee ewm) #2650
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
Merged
Merged
rolling_exp (nee ewm) #2650
Changes from all commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
327bc54
WIP on ewm using numbagg
max-sixty 80019b6
Merge branch 'master' into ewm
max-sixty 1a3ae0b
basic functionality, no dims working yet
max-sixty af1477b
Merge branch 'master' into ewm
max-sixty 6b6b755
Merge branch 'master' into ewm
max-sixty 5b0b6ff
Merge branch 'master' into ewm
max-sixty d119905
rename to `rolling_exp`
max-sixty 1ef07f0
ensure works on either dimensions
max-sixty b30a096
window_type working
max-sixty 89541b5
add numbagg to travis install
max-sixty 9fe91d2
naming
max-sixty c71c949
Merge remote-tracking branch 'upstream/master' into ewm
max-sixty 072b7f8
formatting
max-sixty 2e4dab2
Merge branch 'master' into ewm
max-sixty bf7ac74
@shoyer's function to abstract the type of self.obj
max-sixty 061ef87
initial docstring
max-sixty fe3c9e1
add docstrings to docs
max-sixty e45629e
example
max-sixty a9809f4
correct location for docs
max-sixty c6b939b
add numbagg to print_versions
max-sixty 9cdfcb5
Merge branch 'master' into ewm
max-sixty eb38403
whatsnew
max-sixty 86b4112
updating my GH username
max-sixty 8c88f4f
Merge branch 'master' into ewm
max-sixty 818c342
Merge branch 'master' into ewm
max-sixty d65cbf2
Merge branch 'master' into ewm
max-sixty 6df2578
Merge branch 'master' into ewm
max-sixty c3481d4
Merge branch 'master' into ewm
max-sixty b28fe10
Merge branch 'master' into ewm
max-sixty 42ccd0c
pin to numbagg release
max-sixty 61da1d7
rename inner func to move_exp_nanmean
max-sixty 3996f90
Merge branch 'master' into ewm
max-sixty 55ad124
merge
max-sixty b6228d3
typo
max-sixty 9cdd140
Merge branch 'master' into ewm
max-sixty e856162
comments from PR
max-sixty 102a473
window -> alpha in numbagg
max-sixty aac0ce9
add docs
max-sixty d313821
Merge branch 'master' into ewm
max-sixty b6eebb4
doc fix
max-sixty 7e5f9d8
whatsnew update
max-sixty f64a24f
revert formatting changes to unchanged file
max-sixty 800f096
Merge branch 'master' into ewm
max-sixty 3dd86fd
Merge branch 'master' into ewm
max-sixty 431a10a
Merge branch 'master' into ewm
max-sixty ac299c2
update docstrings, adjust kwarg names
max-sixty 8b95388
mypy
max-sixty f3fc3f7
flake
max-sixty efdbd1f
pytest config tiny tweak while I'm here
max-sixty 7b094ba
Rolling exp doc updates
shoyer dd2a791
remove _attributes from RollingExp class
max-sixty File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 |
---|---|---|
|
@@ -30,3 +30,4 @@ dependencies: | |
- pydap | ||
- pip: | ||
- mypy==0.650 | ||
- numbagg |
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,106 @@ | ||
import numpy as np | ||
|
||
from .pycompat import dask_array_type | ||
|
||
|
||
def _get_alpha(com=None, span=None, halflife=None, alpha=None): | ||
# pandas defines in terms of com (converting to alpha in the algo) | ||
# so use its function to get a com and then convert to alpha | ||
|
||
com = _get_center_of_mass(com, span, halflife, alpha) | ||
return 1 / (1 + com) | ||
|
||
|
||
def move_exp_nanmean(array, *, axis, alpha): | ||
if isinstance(array, dask_array_type): | ||
raise TypeError("rolling_exp is not currently support for dask arrays") | ||
import numbagg | ||
max-sixty marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if axis == (): | ||
return array.astype(np.float64) | ||
else: | ||
return numbagg.move_exp_nanmean( | ||
array, axis=axis, alpha=alpha) | ||
|
||
|
||
def _get_center_of_mass(comass, span, halflife, alpha): | ||
""" | ||
Vendored from pandas.core.window._get_center_of_mass | ||
|
||
See licenses/PANDAS_LICENSE for the function's license | ||
""" | ||
from pandas.core import common as com | ||
valid_count = com.count_not_none(comass, span, halflife, alpha) | ||
if valid_count > 1: | ||
raise ValueError("comass, span, halflife, and alpha " | ||
"are mutually exclusive") | ||
|
||
# Convert to center of mass; domain checks ensure 0 < alpha <= 1 | ||
if comass is not None: | ||
if comass < 0: | ||
raise ValueError("comass must satisfy: comass >= 0") | ||
elif span is not None: | ||
if span < 1: | ||
raise ValueError("span must satisfy: span >= 1") | ||
comass = (span - 1) / 2. | ||
elif halflife is not None: | ||
if halflife <= 0: | ||
raise ValueError("halflife must satisfy: halflife > 0") | ||
decay = 1 - np.exp(np.log(0.5) / halflife) | ||
comass = 1 / decay - 1 | ||
elif alpha is not None: | ||
if alpha <= 0 or alpha > 1: | ||
raise ValueError("alpha must satisfy: 0 < alpha <= 1") | ||
comass = (1.0 - alpha) / alpha | ||
else: | ||
raise ValueError("Must pass one of comass, span, halflife, or alpha") | ||
|
||
return float(comass) | ||
|
||
|
||
class RollingExp: | ||
""" | ||
Exponentially-weighted moving window object. | ||
Similar to EWM in pandas | ||
|
||
Parameters | ||
---------- | ||
obj : Dataset or DataArray | ||
Object to window. | ||
windows : A single mapping from a single dimension name to window value | ||
dim : str | ||
Name of the dimension to create the rolling exponential window | ||
along (e.g., `time`). | ||
window : int | ||
Size of the moving window. The type of this is specified in | ||
`window_type` | ||
window_type : str, one of ['span', 'com', 'halflife', 'alpha'], default 'span' | ||
The format of the previously supplied window. Each is a simple | ||
numerical transformation of the others. Described in detail: | ||
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.ewm.html | ||
|
||
Returns | ||
------- | ||
RollingExp : type of input argument | ||
""" # noqa | ||
|
||
def __init__(self, obj, windows, window_type='span'): | ||
self.obj = obj | ||
dim, window = next(iter(windows.items())) | ||
self.dim = dim | ||
self.alpha = _get_alpha(**{window_type: window}) | ||
|
||
def mean(self): | ||
""" | ||
Exponentially weighted moving average | ||
|
||
Examples | ||
-------- | ||
>>> da = xr.DataArray([1,1,2,2,2], dims='x') | ||
>>> da.rolling_exp(x=2, window_type='span').mean() | ||
<xarray.DataArray (x: 5)> | ||
array([1. , 1. , 1.692308, 1.9 , 1.966942]) | ||
Dimensions without coordinates: x | ||
""" | ||
|
||
return self.obj.reduce( | ||
move_exp_nanmean, dim=self.dim, alpha=self.alpha) |
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this class attribute any longer, but leaving for the sake of conformity until we have consensus