Skip to content

Doc-groupby-ewm #61284

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
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/source/reference/groupby.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Function application
DataFrameGroupBy.cumsum
DataFrameGroupBy.describe
DataFrameGroupBy.diff
DataFrameGroupBy.ewm
DataFrameGroupBy.ffill
DataFrameGroupBy.first
DataFrameGroupBy.head
Expand Down Expand Up @@ -130,6 +131,7 @@ Function application
SeriesGroupBy.cumsum
SeriesGroupBy.describe
SeriesGroupBy.diff
SeriesGroupBy.ewm
SeriesGroupBy.ffill
SeriesGroupBy.first
SeriesGroupBy.head
Expand Down
101 changes: 79 additions & 22 deletions pandas/core/groupby/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ class providing the base-class of operations.
from pandas.core.indexers.objects import BaseIndexer
from pandas.core.resample import Resampler
from pandas.core.window import (
ExpandingGroupby,
ExponentialMovingWindowGroupby,
RollingGroupby,
)
Expand Down Expand Up @@ -3805,35 +3804,93 @@ def rolling(
@final
@Substitution(name="groupby")
@Appender(_common_see_also)
def expanding(self, *args, **kwargs) -> ExpandingGroupby:
def ewm(self, *args, **kwargs) -> ExponentialMovingWindowGroupby:
"""
Return an expanding grouper, providing expanding
functionality per group.
Provide exponential weighted functions for the groupby.

Parameters
----------
*args
Arguments to be passed to
:meth:`~pandas.core.window.ExponentialMovingWindow`.
**kwargs
Keyword arguments to be passed to
:meth:`~pandas.core.window.ExponentialMovingWindow`.
These can include:
- com : float, optional
- span : float, optional
- halflife : float, optional
- alpha : float, optional
- min_periods : int, default 0
- adjust : bool, default True
- ignore_na : bool, default False
- axis : {0 or 'index', 1 or 'columns'}, default 0

Returns
-------
pandas.api.typing.ExpandingGroupby
"""
from pandas.core.window import ExpandingGroupby
pandas.api.typing.ExponentialMovingWindowGroupby
Return a new grouper with exponential moving window capabilities.

return ExpandingGroupby(
self._selected_obj,
*args,
_grouper=self._grouper,
**kwargs,
)
Notes
-----
Each group is treated independently, and the exponential weighted calculations
are applied separately to each group.

@final
@Substitution(name="groupby")
@Appender(_common_see_also)
def ewm(self, *args, **kwargs) -> ExponentialMovingWindowGroupby:
"""
Return an ewm grouper, providing ewm functionality per group.
When ``adjust=True``, weighted averages are calculated using weights
:math:`w_i = (1-\\alpha)^i` where :math:`i` is the number of periods from the
observations being weighted to the current period.

Returns
-------
pandas.api.typing.ExponentialMovingWindowGroupby
When ``adjust=False``, the calculation follows the recursive formula:
:math:`y_t = (1 - \\alpha) y_{t-1} + \\alpha x_t`.

Examples
--------
>>> df = pd.DataFrame(
... {
... "Class": ["A", "A", "A", "B", "B", "B"],
... "Value": [10, 20, 30, 40, 50, 60],
... }
... )
>>> df
Class Value
0 A 10
1 A 20
2 A 30
3 B 40
4 B 50
5 B 60

>>> df.groupby("Class").ewm(span=2).mean()
Value
Class
A 0 10.000000
1 17.500000
2 26.153846
B 3 40.000000
4 47.500000
5 56.153846

>>> df.groupby("Class").ewm(alpha=0.5, adjust=False).mean()
Value
Class
A 0 10.0
1 15.0
2 22.5
B 3 40.0
4 45.0
5 52.5

>>> df.groupby("Class").ewm(com=1.0, min_periods=1).std()
Value
Class
A 0 NaN
1 7.071068
2 9.636241
B 3 NaN
4 7.071068
5 9.636241
"""

from pandas.core.window import ExponentialMovingWindowGroupby

return ExponentialMovingWindowGroupby(
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/frame/test_query_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def test_query_duplicate_column_name(self, engine, parser):
}
).rename(columns={"B": "A"})

res = df.query('C == 1', engine=engine, parser=parser)
res = df.query("C == 1", engine=engine, parser=parser)

expect = DataFrame(
[[1, 1, 1]],
Expand Down Expand Up @@ -1411,7 +1411,7 @@ def test_expr_with_column_name_with_backtick_and_hash(self):
def test_expr_with_column_name_with_backtick(self):
# GH 59285
df = DataFrame({"a`b": (1, 2, 3), "ab": (4, 5, 6)})
result = df.query("`a``b` < 2") # noqa
result = df.query("`a``b` < 2")
# Note: Formatting checks may wrongly consider the above ``inline code``.
expected = df[df["a`b"] < 2]
tm.assert_frame_equal(result, expected)
Expand Down
Loading