@@ -229,6 +229,11 @@ def _validate(self) -> None:
229
229
)
230
230
if self .method not in ["table" , "single" ]:
231
231
raise ValueError ("method must be 'table' or 'single" )
232
+ if self .step is not None :
233
+ if not is_integer (self .step ):
234
+ raise ValueError ("step must be an integer" )
235
+ elif self .step < 0 :
236
+ raise ValueError ("step must be >= 0" )
232
237
233
238
def _check_window_bounds (
234
239
self , start : np .ndarray , end : np .ndarray , num_vals : int
@@ -238,16 +243,14 @@ def _check_window_bounds(
238
243
f"start ({ len (start )} ) and end ({ len (end )} ) bounds must be the "
239
244
f"same length"
240
245
)
241
- elif not isinstance (self ._get_window_indexer (), GroupbyIndexer ) and len (
242
- start
243
- ) != (num_vals + (self .step or 1 ) - 1 ) // (self .step or 1 ):
246
+ elif len (start ) != (num_vals + (self .step or 1 ) - 1 ) // (self .step or 1 ):
244
247
raise ValueError (
245
248
f"start and end bounds ({ len (start )} ) must be the same length "
246
249
f"as the object ({ num_vals } ) divided by the step ({ self .step } ) "
247
250
f"if given and rounded up"
248
251
)
249
252
250
- def _slice_index (self , index : Index , result : Sized | None = None ) -> Index :
253
+ def _slice_axis_for_step (self , index : Index , result : Sized | None = None ) -> Index :
251
254
"""
252
255
Slices the index for a given result and the preset step.
253
256
"""
@@ -446,7 +449,7 @@ def _apply_series(
446
449
raise DataError ("No numeric types to aggregate" ) from err
447
450
448
451
result = homogeneous_func (values )
449
- index = self ._slice_index (obj .index , result )
452
+ index = self ._slice_axis_for_step (obj .index , result )
450
453
return obj ._constructor (result , index = index , name = obj .name )
451
454
452
455
def _apply_blockwise (
@@ -484,7 +487,7 @@ def hfunc(values: ArrayLike) -> ArrayLike:
484
487
res_values .append (res )
485
488
taker .append (i )
486
489
487
- index = self ._slice_index (
490
+ index = self ._slice_axis_for_step (
488
491
obj .index , res_values [0 ] if len (res_values ) > 0 else None
489
492
)
490
493
df = type (obj )._from_arrays (
@@ -524,7 +527,7 @@ def _apply_tablewise(
524
527
values = values .T if self .axis == 1 else values
525
528
result = homogeneous_func (values )
526
529
result = result .T if self .axis == 1 else result
527
- index = self ._slice_index (obj .index , result )
530
+ index = self ._slice_axis_for_step (obj .index , result )
528
531
columns = (
529
532
obj .columns
530
533
if result .shape [1 ] == len (obj .columns )
@@ -644,13 +647,13 @@ def _numba_apply(
644
647
)
645
648
result = aggregator (values , start , end , min_periods , * func_args )
646
649
result = result .T if self .axis == 1 else result
647
- index = self ._slice_index (obj .index , result )
650
+ index = self ._slice_axis_for_step (obj .index , result )
648
651
if obj .ndim == 1 :
649
652
result = result .squeeze ()
650
653
out = obj ._constructor (result , index = index , name = obj .name )
651
654
return out
652
655
else :
653
- columns = self ._slice_index (obj .columns , result .T )
656
+ columns = self ._slice_axis_for_step (obj .columns , result .T )
654
657
out = obj ._constructor (result , index = index , columns = columns )
655
658
return self ._resolve_output (out , obj )
656
659
@@ -692,7 +695,7 @@ def __init__(
692
695
obj = obj .drop (columns = self ._grouper .names , errors = "ignore" )
693
696
# GH 15354
694
697
if kwargs .get ("step" ) is not None :
695
- raise NotImplementedError ("step not implemented for rolling groupby" )
698
+ raise NotImplementedError ("step not implemented for groupby" )
696
699
super ().__init__ (obj , * args , ** kwargs )
697
700
698
701
def _apply (
@@ -938,14 +941,12 @@ class Window(BaseWindow):
938
941
The closed parameter with fixed windows is now supported.
939
942
940
943
step : int, default None
941
- When supported, applies ``[::step]`` to the resulting sequence of windows, in a
942
- computationally efficient manner. Currently supported only with fixed-length
943
- window indexers. Note that using a step argument other than None or 1 will
944
- produce a result with a different shape than the input.
945
944
946
- ..versionadded:: 1.5
945
+ ..versionadded:: 1.5.0
947
946
948
- The step parameter is only supported with fixed windows.
947
+ Evaluate the window at every ``step`` result, equivalent to slicing as
948
+ ``[::step]``. ``window`` must be an integer. Using a step argument other
949
+ than None or 1 will produce a result with a different shape than the input.
949
950
950
951
method : str {'single', 'table'}, default 'single'
951
952
@@ -1605,9 +1606,7 @@ def cov(
1605
1606
** kwargs ,
1606
1607
):
1607
1608
if self .step is not None :
1608
- raise NotImplementedError (
1609
- "step not implemented for rolling and expanding cov"
1610
- )
1609
+ raise NotImplementedError ("step not implemented for cov" )
1611
1610
1612
1611
from pandas import Series
1613
1612
@@ -1650,11 +1649,8 @@ def corr(
1650
1649
ddof : int = 1 ,
1651
1650
** kwargs ,
1652
1651
):
1653
-
1654
1652
if self .step is not None :
1655
- raise NotImplementedError (
1656
- "step not implemented for rolling and expanding corr"
1657
- )
1653
+ raise NotImplementedError ("step not implemented for corr" )
1658
1654
1659
1655
from pandas import Series
1660
1656
@@ -1749,24 +1745,16 @@ def _validate(self):
1749
1745
if self .min_periods is None :
1750
1746
self .min_periods = 1
1751
1747
1748
+ if self .step is not None :
1749
+ raise NotImplementedError (
1750
+ "step is not supported with frequency windows"
1751
+ )
1752
+
1752
1753
elif isinstance (self .window , BaseIndexer ):
1753
1754
# Passed BaseIndexer subclass should handle all other rolling kwargs
1754
1755
pass
1755
1756
elif not is_integer (self .window ) or self .window < 0 :
1756
1757
raise ValueError ("window must be an integer 0 or greater" )
1757
- # GH 15354:
1758
- # validate window indexer parameters do not raise in get_window_bounds
1759
- # this cannot be done in BaseWindow._validate because there _get_window_indexer
1760
- # would erroneously create a fixed window given a window argument like "1s" due
1761
- # to _win_freq_i8 not being set
1762
- indexer = self ._get_window_indexer ()
1763
- indexer .get_window_bounds (
1764
- num_values = 0 ,
1765
- min_periods = self .min_periods ,
1766
- center = self .center ,
1767
- closed = self .closed ,
1768
- step = self .step ,
1769
- )
1770
1758
1771
1759
def _validate_datetimelike_monotonic (self ):
1772
1760
"""
0 commit comments