From 3b5057220568f16ee4a24cc6b65aa9ccf040bba6 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Thu, 19 Nov 2020 10:49:36 -0800 Subject: [PATCH 1/4] Move tests to appripriate locations, use less pd. --- pandas/tests/window/conftest.py | 1 + pandas/tests/window/test_api.py | 26 ----------------- pandas/tests/window/test_apply.py | 11 ------- pandas/tests/window/test_expanding.py | 26 +++++++---------- pandas/tests/window/test_numba.py | 9 ++++++ pandas/tests/window/test_rolling.py | 31 ++++++-------------- pandas/tests/window/test_win_type.py | 41 +++++++++++++++++++++++++-- 7 files changed, 67 insertions(+), 78 deletions(-) diff --git a/pandas/tests/window/conftest.py b/pandas/tests/window/conftest.py index 64e679336abb8..dd24e0f4c461d 100644 --- a/pandas/tests/window/conftest.py +++ b/pandas/tests/window/conftest.py @@ -305,6 +305,7 @@ def series(): return _create_series() +# Use frame_or_series @pytest.fixture(params=[_create_series(), _create_frame()]) def which(request): """Turn parametrized which as fixture for series and frame""" diff --git a/pandas/tests/window/test_api.py b/pandas/tests/window/test_api.py index 6e5d7b4df00e1..ac77bfe0dfb48 100644 --- a/pandas/tests/window/test_api.py +++ b/pandas/tests/window/test_api.py @@ -1,8 +1,6 @@ import numpy as np import pytest -import pandas.util._test_decorators as td - import pandas as pd from pandas import DataFrame, Index, Series, Timestamp, concat import pandas._testing as tm @@ -238,30 +236,6 @@ def test_count_nonnumeric_types(): tm.assert_frame_equal(result, expected) -@td.skip_if_no_scipy -@pytest.mark.filterwarnings("ignore:can't resolve:ImportWarning") -def test_window_with_args(): - # make sure that we are aggregating window functions correctly with arg - r = Series(np.random.randn(100)).rolling( - window=10, min_periods=1, win_type="gaussian" - ) - expected = concat([r.mean(std=10), r.mean(std=0.01)], axis=1) - expected.columns = ["", ""] - result = r.aggregate([lambda x: x.mean(std=10), lambda x: x.mean(std=0.01)]) - tm.assert_frame_equal(result, expected) - - def a(x): - return x.mean(std=10) - - def b(x): - return x.mean(std=0.01) - - expected = concat([r.mean(std=10), r.mean(std=0.01)], axis=1) - expected.columns = ["a", "b"] - result = r.aggregate([a, b]) - tm.assert_frame_equal(result, expected) - - def test_preserve_metadata(): # GH 10565 s = Series(np.arange(100), name="foo") diff --git a/pandas/tests/window/test_apply.py b/pandas/tests/window/test_apply.py index b7343d835fa6e..076578f4dc3c4 100644 --- a/pandas/tests/window/test_apply.py +++ b/pandas/tests/window/test_apply.py @@ -1,9 +1,6 @@ import numpy as np import pytest -from pandas.errors import NumbaUtilError -import pandas.util._test_decorators as td - from pandas import DataFrame, Index, MultiIndex, Series, Timestamp, date_range import pandas._testing as tm @@ -133,14 +130,6 @@ def test_invalid_raw_numba(): Series(range(1)).rolling(1).apply(lambda x: x, raw=False, engine="numba") -@td.skip_if_no("numba") -def test_invalid_kwargs_nopython(): - with pytest.raises(NumbaUtilError, match="numba does not support kwargs with"): - Series(range(1)).rolling(1).apply( - lambda x: x, kwargs={"a": 1}, engine="numba", raw=True - ) - - @pytest.mark.parametrize("args_kwargs", [[None, {"par": 10}], [(10,), None]]) def test_rolling_apply_args_kwargs(args_kwargs): # GH 33433 diff --git a/pandas/tests/window/test_expanding.py b/pandas/tests/window/test_expanding.py index ace6848a58c9c..9278802cb1b21 100644 --- a/pandas/tests/window/test_expanding.py +++ b/pandas/tests/window/test_expanding.py @@ -118,30 +118,27 @@ def test_expanding_axis(axis_frame): tm.assert_frame_equal(result, expected) -@pytest.mark.parametrize("constructor", [Series, DataFrame]) -def test_expanding_count_with_min_periods(constructor): +def test_expanding_count_with_min_periods(frame_or_series): # GH 26996 - result = constructor(range(5)).expanding(min_periods=3).count() - expected = constructor([np.nan, np.nan, 3.0, 4.0, 5.0]) + result = frame_or_series(range(5)).expanding(min_periods=3).count() + expected = frame_or_series([np.nan, np.nan, 3.0, 4.0, 5.0]) tm.assert_equal(result, expected) -@pytest.mark.parametrize("constructor", [Series, DataFrame]) -def test_expanding_count_default_min_periods_with_null_values(constructor): +def test_expanding_count_default_min_periods_with_null_values(frame_or_series): # GH 26996 values = [1, 2, 3, np.nan, 4, 5, 6] expected_counts = [1.0, 2.0, 3.0, 3.0, 4.0, 5.0, 6.0] - result = constructor(values).expanding().count() - expected = constructor(expected_counts) + result = frame_or_series(values).expanding().count() + expected = frame_or_series(expected_counts) tm.assert_equal(result, expected) -@pytest.mark.parametrize("constructor", [Series, DataFrame]) -def test_expanding_count_with_min_periods_exceeding_series_length(constructor): +def test_expanding_count_with_min_periods_exceeding_series_length(frame_or_series): # GH 25857 - result = constructor(range(5)).expanding(min_periods=6).count() - expected = constructor([np.nan, np.nan, np.nan, np.nan, np.nan]) + result = frame_or_series(range(5)).expanding(min_periods=6).count() + expected = frame_or_series([np.nan, np.nan, np.nan, np.nan, np.nan]) tm.assert_equal(result, expected) @@ -246,10 +243,9 @@ def test_center_deprecate_warning(): df.expanding() -@pytest.mark.parametrize("constructor", ["DataFrame", "Series"]) -def test_expanding_sem(constructor): +def test_expanding_sem(frame_or_series): # GH: 26476 - obj = getattr(pd, constructor)([0, 1, 2]) + obj = frame_or_series([0, 1, 2]) result = obj.expanding().sem() if isinstance(result, DataFrame): result = Series(result[0].values) diff --git a/pandas/tests/window/test_numba.py b/pandas/tests/window/test_numba.py index 3dd09bc4b752a..e890108b22c3e 100644 --- a/pandas/tests/window/test_numba.py +++ b/pandas/tests/window/test_numba.py @@ -1,6 +1,7 @@ import numpy as np import pytest +from pandas.errors import NumbaUtilError import pandas.util._test_decorators as td from pandas import DataFrame, Series, option_context @@ -112,3 +113,11 @@ def f(x): result = s.rolling(2).apply(f, engine=None, raw=True) expected = s.rolling(2).apply(f, engine="numba", raw=True) tm.assert_series_equal(expected, result) + + +@td.skip_if_no("numba", "0.46.0") +def test_invalid_kwargs_nopython(): + with pytest.raises(NumbaUtilError, match="numba does not support kwargs with"): + Series(range(1)).rolling(1).apply( + lambda x: x, kwargs={"a": 1}, engine="numba", raw=True + ) diff --git a/pandas/tests/window/test_rolling.py b/pandas/tests/window/test_rolling.py index 75e1a771b70ea..84635de366d1e 100644 --- a/pandas/tests/window/test_rolling.py +++ b/pandas/tests/window/test_rolling.py @@ -4,7 +4,6 @@ import pytest from pandas.errors import UnsupportedFunctionCall -import pandas.util._test_decorators as td import pandas as pd from pandas import DataFrame, Series, date_range @@ -62,17 +61,6 @@ def test_invalid_constructor(which, w): c(window=2, min_periods=1, center=w) -@td.skip_if_no_scipy -def test_constructor_with_win_type(which): - # GH 13383 - c = which.rolling - - msg = "window must be > 0" - - with pytest.raises(ValueError, match=msg): - c(-1, win_type="boxcar") - - @pytest.mark.parametrize("window", [timedelta(days=3), pd.Timedelta(days=3)]) def test_constructor_with_timedelta_window(window): # GH 15440 @@ -466,24 +454,22 @@ def test_min_periods1(): tm.assert_series_equal(result, expected) -@pytest.mark.parametrize("constructor", [Series, DataFrame]) -def test_rolling_count_with_min_periods(constructor): +def test_rolling_count_with_min_periods(frame_or_series): # GH 26996 - result = constructor(range(5)).rolling(3, min_periods=3).count() - expected = constructor([np.nan, np.nan, 3.0, 3.0, 3.0]) + result = frame_or_series(range(5)).rolling(3, min_periods=3).count() + expected = frame_or_series([np.nan, np.nan, 3.0, 3.0, 3.0]) tm.assert_equal(result, expected) -@pytest.mark.parametrize("constructor", [Series, DataFrame]) -def test_rolling_count_default_min_periods_with_null_values(constructor): +def test_rolling_count_default_min_periods_with_null_values(frame_or_series): # GH 26996 values = [1, 2, 3, np.nan, 4, 5, 6] expected_counts = [1.0, 2.0, 3.0, 2.0, 2.0, 2.0, 3.0] # GH 31302 with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): - result = constructor(values).rolling(3).count() - expected = constructor(expected_counts) + result = frame_or_series(values).rolling(3).count() + expected = frame_or_series(expected_counts) tm.assert_equal(result, expected) @@ -890,10 +876,9 @@ def test_rolling_period_index(index, window, func, values): tm.assert_series_equal(result, expected) -@pytest.mark.parametrize("constructor", ["DataFrame", "Series"]) -def test_rolling_sem(constructor): +def test_rolling_sem(frame_or_series): # GH: 26476 - obj = getattr(pd, constructor)([0, 1, 2]) + obj = frame_or_series([0, 1, 2]) result = obj.rolling(2, min_periods=1).sem() if isinstance(result, DataFrame): result = Series(result[0].values) diff --git a/pandas/tests/window/test_win_type.py b/pandas/tests/window/test_win_type.py index eab62b3383283..c75857dd2600c 100644 --- a/pandas/tests/window/test_win_type.py +++ b/pandas/tests/window/test_win_type.py @@ -4,8 +4,8 @@ from pandas.errors import UnsupportedFunctionCall import pandas.util._test_decorators as td -import pandas as pd -from pandas import Series +from pandas import DataFrame, Series, concat +import pandas._testing as tm @td.skip_if_no_scipy @@ -62,7 +62,7 @@ def test_numpy_compat(method): @td.skip_if_no_scipy @pytest.mark.parametrize("arg", ["median", "kurt", "skew"]) def test_agg_function_support(arg): - df = pd.DataFrame({"A": np.arange(5)}) + df = DataFrame({"A": np.arange(5)}) roll = df.rolling(2, win_type="triang") msg = f"'{arg}' is not a valid function for 'Window' object" @@ -82,3 +82,38 @@ def test_invalid_scipy_arg(): msg = r"boxcar\(\) got an unexpected" with pytest.raises(TypeError, match=msg): Series(range(3)).rolling(1, win_type="boxcar").mean(foo="bar") + + +@td.skip_if_no_scipy +def test_constructor_with_win_type(which): + # GH 13383 + c = which.rolling + + msg = "window must be > 0" + + with pytest.raises(ValueError, match=msg): + c(-1, win_type="boxcar") + + +@td.skip_if_no_scipy +@pytest.mark.filterwarnings("ignore:can't resolve:ImportWarning") +def test_window_with_args(): + # make sure that we are aggregating window functions correctly with arg + r = Series(np.random.randn(100)).rolling( + window=10, min_periods=1, win_type="gaussian" + ) + expected = concat([r.mean(std=10), r.mean(std=0.01)], axis=1) + expected.columns = ["", ""] + result = r.aggregate([lambda x: x.mean(std=10), lambda x: x.mean(std=0.01)]) + tm.assert_frame_equal(result, expected) + + def a(x): + return x.mean(std=10) + + def b(x): + return x.mean(std=0.01) + + expected = concat([r.mean(std=10), r.mean(std=0.01)], axis=1) + expected.columns = ["a", "b"] + result = r.aggregate([a, b]) + tm.assert_frame_equal(result, expected) From 29b570a1d30ba11fc173112d01ba2bb409aaf977 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Thu, 19 Nov 2020 11:26:30 -0800 Subject: [PATCH 2/4] Consolidate fixtures and use frame_or_series --- pandas/tests/window/conftest.py | 33 +++++++-------------------- pandas/tests/window/test_ewm.py | 4 ++-- pandas/tests/window/test_expanding.py | 8 +++---- pandas/tests/window/test_rolling.py | 8 +++---- pandas/tests/window/test_win_type.py | 20 ++++++++-------- 5 files changed, 28 insertions(+), 45 deletions(-) diff --git a/pandas/tests/window/conftest.py b/pandas/tests/window/conftest.py index dd24e0f4c461d..a765f268cfb07 100644 --- a/pandas/tests/window/conftest.py +++ b/pandas/tests/window/conftest.py @@ -275,17 +275,9 @@ def consistency_data(request): return request.param -def _create_series(): - """Internal function to mock Series.""" - arr = np.random.randn(100) - locs = np.arange(20, 40) - arr[locs] = np.NaN - series = Series(arr, index=bdate_range(datetime(2009, 1, 1), periods=100)) - return series - - -def _create_frame(): - """Internal function to mock DataFrame.""" +@pytest.fixture +def frame(): + """Make mocked frame as fixture.""" return DataFrame( np.random.randn(100, 10), index=bdate_range(datetime(2009, 1, 1), periods=100), @@ -293,23 +285,14 @@ def _create_frame(): ) -@pytest.fixture -def frame(): - """Make mocked frame as fixture.""" - return _create_frame() - - @pytest.fixture def series(): """Make mocked series as fixture.""" - return _create_series() - - -# Use frame_or_series -@pytest.fixture(params=[_create_series(), _create_frame()]) -def which(request): - """Turn parametrized which as fixture for series and frame""" - return request.param + arr = np.random.randn(100) + locs = np.arange(20, 40) + arr[locs] = np.NaN + series = Series(arr, index=bdate_range(datetime(2009, 1, 1), periods=100)) + return series @pytest.fixture(params=["1 day", timedelta(days=1)]) diff --git a/pandas/tests/window/test_ewm.py b/pandas/tests/window/test_ewm.py index 69cd1d1ba069c..c026f52e94482 100644 --- a/pandas/tests/window/test_ewm.py +++ b/pandas/tests/window/test_ewm.py @@ -15,9 +15,9 @@ def test_doc_string(): df.ewm(com=0.5).mean() -def test_constructor(which): +def test_constructor(frame_or_series): - c = which.ewm + c = frame_or_series(range(5)).ewm # valid c(com=0.5) diff --git a/pandas/tests/window/test_expanding.py b/pandas/tests/window/test_expanding.py index 9278802cb1b21..3405502e54e70 100644 --- a/pandas/tests/window/test_expanding.py +++ b/pandas/tests/window/test_expanding.py @@ -19,10 +19,10 @@ def test_doc_string(): @pytest.mark.filterwarnings( "ignore:The `center` argument on `expanding` will be removed in the future" ) -def test_constructor(which): +def test_constructor(frame_or_series): # GH 12669 - c = which.expanding + c = frame_or_series(range(5)).expanding # valid c(min_periods=1) @@ -34,10 +34,10 @@ def test_constructor(which): @pytest.mark.filterwarnings( "ignore:The `center` argument on `expanding` will be removed in the future" ) -def test_constructor_invalid(which, w): +def test_constructor_invalid(frame_or_series, w): # not valid - c = which.expanding + c = frame_or_series(range(5)).expanding msg = "min_periods must be an integer" with pytest.raises(ValueError, match=msg): c(min_periods=w) diff --git a/pandas/tests/window/test_rolling.py b/pandas/tests/window/test_rolling.py index 84635de366d1e..1cfbb57d582a3 100644 --- a/pandas/tests/window/test_rolling.py +++ b/pandas/tests/window/test_rolling.py @@ -19,10 +19,10 @@ def test_doc_string(): df.rolling(2, min_periods=1).sum() -def test_constructor(which): +def test_constructor(frame_or_series): # GH 12669 - c = which.rolling + c = frame_or_series(range(5)).rolling # valid c(0) @@ -40,10 +40,10 @@ def test_constructor(which): @pytest.mark.parametrize("w", [2.0, "foo", np.array([2])]) -def test_invalid_constructor(which, w): +def test_invalid_constructor(frame_or_series, w): # not valid - c = which.rolling + c = frame_or_series(range(5)).rolling msg = ( "window must be an integer|" diff --git a/pandas/tests/window/test_win_type.py b/pandas/tests/window/test_win_type.py index c75857dd2600c..8d853bf8cb9ca 100644 --- a/pandas/tests/window/test_win_type.py +++ b/pandas/tests/window/test_win_type.py @@ -9,9 +9,9 @@ @td.skip_if_no_scipy -def test_constructor(which): +def test_constructor(frame_or_series): # GH 12669 - c = which.rolling + c = frame_or_series(range(5)).rolling # valid c(win_type="boxcar", window=2, min_periods=1) @@ -21,10 +21,10 @@ def test_constructor(which): @pytest.mark.parametrize("w", [2.0, "foo", np.array([2])]) @td.skip_if_no_scipy -def test_invalid_constructor(which, w): +def test_invalid_constructor(frame_or_series, w): # not valid - c = which.rolling + c = frame_or_series(range(5)).rolling with pytest.raises(ValueError, match="min_periods must be an integer"): c(win_type="boxcar", window=2, min_periods=w) with pytest.raises(ValueError, match="center must be a boolean"): @@ -33,16 +33,16 @@ def test_invalid_constructor(which, w): @pytest.mark.parametrize("wt", ["foobar", 1]) @td.skip_if_no_scipy -def test_invalid_constructor_wintype(which, wt): - c = which.rolling +def test_invalid_constructor_wintype(frame_or_series, wt): + c = frame_or_series(range(5)).rolling with pytest.raises(ValueError, match="Invalid win_type"): c(win_type=wt, window=2) @td.skip_if_no_scipy -def test_constructor_with_win_type(which, win_types): +def test_constructor_with_win_type(frame_or_series, win_types): # GH 12669 - c = which.rolling + c = frame_or_series(range(5)).rolling c(win_type=win_types, window=2) @@ -85,9 +85,9 @@ def test_invalid_scipy_arg(): @td.skip_if_no_scipy -def test_constructor_with_win_type(which): +def test_constructor_with_win_type(frame_or_series): # GH 13383 - c = which.rolling + c = frame_or_series(range(5)).rolling msg = "window must be > 0" From d55e3e4449d8102a8fffb0cba95a69c2e70fded6 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Thu, 19 Nov 2020 11:29:14 -0800 Subject: [PATCH 3/4] Rename test --- pandas/tests/window/test_win_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/window/test_win_type.py b/pandas/tests/window/test_win_type.py index 8d853bf8cb9ca..091b5914a7c3e 100644 --- a/pandas/tests/window/test_win_type.py +++ b/pandas/tests/window/test_win_type.py @@ -85,7 +85,7 @@ def test_invalid_scipy_arg(): @td.skip_if_no_scipy -def test_constructor_with_win_type(frame_or_series): +def test_constructor_with_win_type_invalid(frame_or_series): # GH 13383 c = frame_or_series(range(5)).rolling From 5217c53642ced98bdd43085467a4e6a61c3c009b Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Thu, 19 Nov 2020 11:42:17 -0800 Subject: [PATCH 4/4] Add TestRolling and TestExpanding to groupby tests --- pandas/tests/window/test_groupby.py | 132 ++++++++++++++-------------- 1 file changed, 68 insertions(+), 64 deletions(-) diff --git a/pandas/tests/window/test_groupby.py b/pandas/tests/window/test_groupby.py index c4de112bd6dc0..7a75ff1cff5bc 100644 --- a/pandas/tests/window/test_groupby.py +++ b/pandas/tests/window/test_groupby.py @@ -7,9 +7,8 @@ from pandas.core.groupby.groupby import get_groupby -class TestGrouperGrouping: +class TestRolling: def setup_method(self): - self.series = Series(np.arange(10)) self.frame = DataFrame({"A": [1] * 20 + [2] * 12 + [3] * 8, "B": np.arange(40)}) def test_mutated(self): @@ -152,68 +151,6 @@ def test_rolling_apply_mutability(self): result = g.rolling(window=2).sum() tm.assert_frame_equal(result, expected) - @pytest.mark.parametrize( - "f", ["sum", "mean", "min", "max", "count", "kurt", "skew"] - ) - def test_expanding(self, f): - g = self.frame.groupby("A") - r = g.expanding() - - result = getattr(r, f)() - expected = g.apply(lambda x: getattr(x.expanding(), f)()) - tm.assert_frame_equal(result, expected) - - @pytest.mark.parametrize("f", ["std", "var"]) - def test_expanding_ddof(self, f): - g = self.frame.groupby("A") - r = g.expanding() - - result = getattr(r, f)(ddof=0) - expected = g.apply(lambda x: getattr(x.expanding(), f)(ddof=0)) - tm.assert_frame_equal(result, expected) - - @pytest.mark.parametrize( - "interpolation", ["linear", "lower", "higher", "midpoint", "nearest"] - ) - def test_expanding_quantile(self, interpolation): - g = self.frame.groupby("A") - r = g.expanding() - result = r.quantile(0.4, interpolation=interpolation) - expected = g.apply( - lambda x: x.expanding().quantile(0.4, interpolation=interpolation) - ) - tm.assert_frame_equal(result, expected) - - @pytest.mark.parametrize("f", ["corr", "cov"]) - def test_expanding_corr_cov(self, f): - g = self.frame.groupby("A") - r = g.expanding() - - result = getattr(r, f)(self.frame) - - def func(x): - return getattr(x.expanding(), f)(self.frame) - - expected = g.apply(func) - tm.assert_frame_equal(result, expected) - - result = getattr(r.B, f)(pairwise=True) - - def func(x): - return getattr(x.B.expanding(), f)(pairwise=True) - - expected = g.apply(func) - tm.assert_series_equal(result, expected) - - def test_expanding_apply(self, raw): - g = self.frame.groupby("A") - r = g.expanding() - - # reduction - result = r.apply(lambda x: x.sum(), raw=raw) - expected = g.apply(lambda x: x.expanding().apply(lambda y: y.sum(), raw=raw)) - tm.assert_frame_equal(result, expected) - @pytest.mark.parametrize("expected_value,raw_value", [[1.0, True], [0.0, False]]) def test_groupby_rolling(self, expected_value, raw_value): # GH 31754 @@ -633,6 +570,73 @@ def test_groupby_rolling_index_level_and_column_label(self): tm.assert_frame_equal(result, expected) +class TestExpanding: + def setup_method(self): + self.frame = DataFrame({"A": [1] * 20 + [2] * 12 + [3] * 8, "B": np.arange(40)}) + + @pytest.mark.parametrize( + "f", ["sum", "mean", "min", "max", "count", "kurt", "skew"] + ) + def test_expanding(self, f): + g = self.frame.groupby("A") + r = g.expanding() + + result = getattr(r, f)() + expected = g.apply(lambda x: getattr(x.expanding(), f)()) + tm.assert_frame_equal(result, expected) + + @pytest.mark.parametrize("f", ["std", "var"]) + def test_expanding_ddof(self, f): + g = self.frame.groupby("A") + r = g.expanding() + + result = getattr(r, f)(ddof=0) + expected = g.apply(lambda x: getattr(x.expanding(), f)(ddof=0)) + tm.assert_frame_equal(result, expected) + + @pytest.mark.parametrize( + "interpolation", ["linear", "lower", "higher", "midpoint", "nearest"] + ) + def test_expanding_quantile(self, interpolation): + g = self.frame.groupby("A") + r = g.expanding() + result = r.quantile(0.4, interpolation=interpolation) + expected = g.apply( + lambda x: x.expanding().quantile(0.4, interpolation=interpolation) + ) + tm.assert_frame_equal(result, expected) + + @pytest.mark.parametrize("f", ["corr", "cov"]) + def test_expanding_corr_cov(self, f): + g = self.frame.groupby("A") + r = g.expanding() + + result = getattr(r, f)(self.frame) + + def func(x): + return getattr(x.expanding(), f)(self.frame) + + expected = g.apply(func) + tm.assert_frame_equal(result, expected) + + result = getattr(r.B, f)(pairwise=True) + + def func(x): + return getattr(x.B.expanding(), f)(pairwise=True) + + expected = g.apply(func) + tm.assert_series_equal(result, expected) + + def test_expanding_apply(self, raw): + g = self.frame.groupby("A") + r = g.expanding() + + # reduction + result = r.apply(lambda x: x.sum(), raw=raw) + expected = g.apply(lambda x: x.expanding().apply(lambda y: y.sum(), raw=raw)) + tm.assert_frame_equal(result, expected) + + class TestEWM: @pytest.mark.parametrize( "method, expected_data",