diff --git a/doc/source/user_guide/computation.rst b/doc/source/user_guide/computation.rst index d7d025981f2f4..f9c07df956341 100644 --- a/doc/source/user_guide/computation.rst +++ b/doc/source/user_guide/computation.rst @@ -318,8 +318,8 @@ We provide a number of common statistical functions: :meth:`~Rolling.kurt`, Sample kurtosis (4th moment) :meth:`~Rolling.quantile`, Sample quantile (value at %) :meth:`~Rolling.apply`, Generic apply - :meth:`~Rolling.cov`, Unbiased covariance (binary) - :meth:`~Rolling.corr`, Correlation (binary) + :meth:`~Rolling.cov`, Sample covariance (binary) + :meth:`~Rolling.corr`, Sample correlation (binary) .. _computation.window_variance.caveats: @@ -341,6 +341,8 @@ We provide a number of common statistical functions: sample variance under the circumstances would result in a biased estimator of the variable we are trying to determine. + The same caveats apply to using any supported statistical sample methods. + .. _stats.rolling_apply: Rolling apply @@ -870,12 +872,12 @@ Method summary :meth:`~Expanding.max`, Maximum :meth:`~Expanding.std`, Sample standard deviation :meth:`~Expanding.var`, Sample variance - :meth:`~Expanding.skew`, Unbiased skewness (3rd moment) - :meth:`~Expanding.kurt`, Unbiased kurtosis (4th moment) + :meth:`~Expanding.skew`, Sample skewness (3rd moment) + :meth:`~Expanding.kurt`, Sample kurtosis (4th moment) :meth:`~Expanding.quantile`, Sample quantile (value at %) :meth:`~Expanding.apply`, Generic apply - :meth:`~Expanding.cov`, Unbiased covariance (binary) - :meth:`~Expanding.corr`, Correlation (binary) + :meth:`~Expanding.cov`, Sample covariance (binary) + :meth:`~Expanding.corr`, Sample correlation (binary) .. note:: @@ -884,6 +886,8 @@ Method summary windows. See :ref:`this section ` for more information. + The same caveats apply to using any supported statistical sample methods. + .. currentmodule:: pandas Aside from not having a ``window`` parameter, these functions have the same diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index e8fdaf0ae5d49..34f27c31febef 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -175,8 +175,8 @@ Other API changes - Added :meth:`DataFrame.value_counts` (:issue:`5377`) - :meth:`Groupby.groups` now returns an abbreviated representation when called on large dataframes (:issue:`1135`) - ``loc`` lookups with an object-dtype :class:`Index` and an integer key will now raise ``KeyError`` instead of ``TypeError`` when key is missing (:issue:`31905`) -- Using a :func:`pandas.api.indexers.BaseIndexer` with ``skew``, ``cov``, ``corr`` will now raise a ``NotImplementedError`` (:issue:`32865`) -- Using a :func:`pandas.api.indexers.BaseIndexer` with ``count``, ``min``, ``max``, ``median`` will now return correct results for any monotonic :func:`pandas.api.indexers.BaseIndexer` descendant (:issue:`32865`) +- Using a :func:`pandas.api.indexers.BaseIndexer` with ``cov``, ``corr`` will now raise a ``NotImplementedError`` (:issue:`32865`) +- Using a :func:`pandas.api.indexers.BaseIndexer` with ``count``, ``min``, ``max``, ``median``, ``skew`` will now return correct results for any monotonic :func:`pandas.api.indexers.BaseIndexer` descendant (:issue:`32865`) - Added a :func:`pandas.api.indexers.FixedForwardWindowIndexer` class to support forward-looking windows during ``rolling`` operations. - diff --git a/pandas/core/window/common.py b/pandas/core/window/common.py index 8707893dc20cf..082c2f533f3de 100644 --- a/pandas/core/window/common.py +++ b/pandas/core/window/common.py @@ -337,6 +337,7 @@ def validate_baseindexer_support(func_name: Optional[str]) -> None: "median", "std", "var", + "skew", "kurt", "quantile", } diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py index 3b14921528890..cdd61edba57ce 100644 --- a/pandas/core/window/rolling.py +++ b/pandas/core/window/rolling.py @@ -471,13 +471,13 @@ def _apply( def calc(x): x = np.concatenate((x, additional_nans)) - if not isinstance(window, BaseIndexer): + if not isinstance(self.window, BaseIndexer): min_periods = calculate_min_periods( window, self.min_periods, len(x), require_min_periods, floor ) else: min_periods = calculate_min_periods( - self.min_periods or 1, + window_indexer.window_size, self.min_periods, len(x), require_min_periods, diff --git a/pandas/tests/window/test_base_indexer.py b/pandas/tests/window/test_base_indexer.py index aee47a085eb9c..15e6a904dd11a 100644 --- a/pandas/tests/window/test_base_indexer.py +++ b/pandas/tests/window/test_base_indexer.py @@ -82,7 +82,7 @@ def get_window_bounds(self, num_values, min_periods, center, closed): df.rolling(indexer, win_type="boxcar") -@pytest.mark.parametrize("func", ["skew", "cov", "corr"]) +@pytest.mark.parametrize("func", ["cov", "corr"]) def test_notimplemented_functions(func): # GH 32865 class CustomIndexer(BaseIndexer): @@ -184,3 +184,29 @@ def test_rolling_forward_window(constructor, func, np_func, expected, np_kwargs) result3 = getattr(rolling3, func)() expected3 = constructor(rolling3.apply(lambda x: np_func(x, **np_kwargs))) tm.assert_equal(result3, expected3) + + +@pytest.mark.parametrize("constructor", [Series, DataFrame]) +def test_rolling_forward_skewness(constructor): + values = np.arange(10) + values[5] = 100.0 + + indexer = FixedForwardWindowIndexer(window_size=5) + rolling = constructor(values).rolling(window=indexer, min_periods=3) + result = rolling.skew() + + expected = constructor( + [ + 0.0, + 2.232396, + 2.229508, + 2.228340, + 2.229091, + 2.231989, + 0.0, + 0.0, + np.nan, + np.nan, + ] + ) + tm.assert_equal(result, expected)