Skip to content

Commit 5577014

Browse files
committed
Merge branch 'main' into ref-gbops-ea
2 parents a68b093 + 0ccad38 commit 5577014

File tree

10 files changed

+692
-270
lines changed

10 files changed

+692
-270
lines changed

asv_bench/benchmarks/indexing.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,24 @@ def setup(self):
290290
self.dti = dti
291291
self.dti2 = dti2
292292

293+
index = np.random.choice(dti, 10000, replace=True)
294+
df = DataFrame(index=index, data={"a": 1})
295+
df_sort = df.sort_index()
296+
self.df = df
297+
self.df_sort = df_sort
298+
293299
def time_get_indexer_mismatched_tz(self):
294300
# reached via e.g.
295301
# ser = Series(range(len(dti)), index=dti)
296302
# ser[dti2]
297303
self.dti.get_indexer(self.dti2)
298304

305+
def time_loc_unsorted(self):
306+
self.df.loc["2016-6-11"]
307+
308+
def time_loc_sorted(self):
309+
self.df_sort.loc["2016-6-11"]
310+
299311

300312
class CategoricalIndexIndexing:
301313

pandas/_libs/window/indexers.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@ def calculate_variable_window_bounds(
88
min_periods,
99
center: bool,
1010
closed: str | None,
11-
step: int | None,
1211
index: np.ndarray, # const int64_t[:]
1312
) -> tuple[npt.NDArray[np.int64], npt.NDArray[np.int64]]: ...

pandas/_libs/window/indexers.pyx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ def calculate_variable_window_bounds(
1616
object min_periods, # unused but here to match get_window_bounds signature
1717
bint center,
1818
str closed,
19-
int64_t step,
2019
const int64_t[:] index
2120
):
2221
"""
@@ -39,9 +38,6 @@ def calculate_variable_window_bounds(
3938
closed : str
4039
string of side of the window that should be closed
4140
42-
step : int64
43-
Spacing between windows
44-
4541
index : ndarray[int64]
4642
time series index to roll over
4743
@@ -150,4 +146,4 @@ def calculate_variable_window_bounds(
150146
# right endpoint is open
151147
if not right_closed and not center:
152148
end[i] -= 1
153-
return start[::step], end[::step]
149+
return start, end

pandas/core/indexers/objects.py

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,6 @@ def get_window_bounds(
115115
step: int | None = None,
116116
) -> tuple[np.ndarray, np.ndarray]:
117117

118-
if step is not None:
119-
raise NotImplementedError("step not implemented for variable window")
120-
121118
# error: Argument 4 to "calculate_variable_window_bounds" has incompatible
122119
# type "Optional[bool]"; expected "bool"
123120
# error: Argument 6 to "calculate_variable_window_bounds" has incompatible
@@ -128,7 +125,6 @@ def get_window_bounds(
128125
min_periods,
129126
center, # type: ignore[arg-type]
130127
closed,
131-
1,
132128
self.index_array, # type: ignore[arg-type]
133129
)
134130

@@ -234,12 +230,10 @@ def get_window_bounds(
234230
step: int | None = None,
235231
) -> tuple[np.ndarray, np.ndarray]:
236232

237-
if step is not None:
238-
raise NotImplementedError("step not implemented for expanding window")
239-
240-
end = np.arange(1, num_values + 1, dtype=np.int64)
241-
start = np.zeros(len(end), dtype=np.int64)
242-
return start, end
233+
return (
234+
np.zeros(num_values, dtype=np.int64),
235+
np.arange(1, num_values + 1, dtype=np.int64),
236+
)
243237

244238

245239
class FixedForwardWindowIndexer(BaseIndexer):
@@ -343,8 +337,6 @@ def get_window_bounds(
343337
closed: str | None = None,
344338
step: int | None = None,
345339
) -> tuple[np.ndarray, np.ndarray]:
346-
if step is not None:
347-
raise NotImplementedError("step not implemented for groupby window")
348340

349341
# 1) For each group, get the indices that belong to the group
350342
# 2) Use the indices to calculate the start & end bounds of the window
@@ -404,11 +396,4 @@ def get_window_bounds(
404396
step: int | None = None,
405397
) -> tuple[np.ndarray, np.ndarray]:
406398

407-
if step is not None:
408-
raise NotImplementedError(
409-
"step not implemented for exponentail moving window"
410-
)
411-
return (
412-
np.array([0], dtype=np.int64),
413-
np.array([num_values], dtype=np.int64),
414-
)
399+
return np.array([0], dtype=np.int64), np.array([num_values], dtype=np.int64)

pandas/core/window/rolling.py

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ def _validate(self) -> None:
229229
)
230230
if self.method not in ["table", "single"]:
231231
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")
232237

233238
def _check_window_bounds(
234239
self, start: np.ndarray, end: np.ndarray, num_vals: int
@@ -238,16 +243,14 @@ def _check_window_bounds(
238243
f"start ({len(start)}) and end ({len(end)}) bounds must be the "
239244
f"same length"
240245
)
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):
244247
raise ValueError(
245248
f"start and end bounds ({len(start)}) must be the same length "
246249
f"as the object ({num_vals}) divided by the step ({self.step}) "
247250
f"if given and rounded up"
248251
)
249252

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:
251254
"""
252255
Slices the index for a given result and the preset step.
253256
"""
@@ -446,7 +449,7 @@ def _apply_series(
446449
raise DataError("No numeric types to aggregate") from err
447450

448451
result = homogeneous_func(values)
449-
index = self._slice_index(obj.index, result)
452+
index = self._slice_axis_for_step(obj.index, result)
450453
return obj._constructor(result, index=index, name=obj.name)
451454

452455
def _apply_blockwise(
@@ -484,7 +487,7 @@ def hfunc(values: ArrayLike) -> ArrayLike:
484487
res_values.append(res)
485488
taker.append(i)
486489

487-
index = self._slice_index(
490+
index = self._slice_axis_for_step(
488491
obj.index, res_values[0] if len(res_values) > 0 else None
489492
)
490493
df = type(obj)._from_arrays(
@@ -524,7 +527,7 @@ def _apply_tablewise(
524527
values = values.T if self.axis == 1 else values
525528
result = homogeneous_func(values)
526529
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)
528531
columns = (
529532
obj.columns
530533
if result.shape[1] == len(obj.columns)
@@ -644,13 +647,13 @@ def _numba_apply(
644647
)
645648
result = aggregator(values, start, end, min_periods, *func_args)
646649
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)
648651
if obj.ndim == 1:
649652
result = result.squeeze()
650653
out = obj._constructor(result, index=index, name=obj.name)
651654
return out
652655
else:
653-
columns = self._slice_index(obj.columns, result.T)
656+
columns = self._slice_axis_for_step(obj.columns, result.T)
654657
out = obj._constructor(result, index=index, columns=columns)
655658
return self._resolve_output(out, obj)
656659

@@ -692,7 +695,7 @@ def __init__(
692695
obj = obj.drop(columns=self._grouper.names, errors="ignore")
693696
# GH 15354
694697
if kwargs.get("step") is not None:
695-
raise NotImplementedError("step not implemented for rolling groupby")
698+
raise NotImplementedError("step not implemented for groupby")
696699
super().__init__(obj, *args, **kwargs)
697700

698701
def _apply(
@@ -938,14 +941,12 @@ class Window(BaseWindow):
938941
The closed parameter with fixed windows is now supported.
939942
940943
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.
945944
946-
..versionadded:: 1.5
945+
..versionadded:: 1.5.0
947946
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.
949950
950951
method : str {'single', 'table'}, default 'single'
951952
@@ -1605,9 +1606,7 @@ def cov(
16051606
**kwargs,
16061607
):
16071608
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")
16111610

16121611
from pandas import Series
16131612

@@ -1650,11 +1649,8 @@ def corr(
16501649
ddof: int = 1,
16511650
**kwargs,
16521651
):
1653-
16541652
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")
16581654

16591655
from pandas import Series
16601656

@@ -1749,24 +1745,16 @@ def _validate(self):
17491745
if self.min_periods is None:
17501746
self.min_periods = 1
17511747

1748+
if self.step is not None:
1749+
raise NotImplementedError(
1750+
"step is not supported with frequency windows"
1751+
)
1752+
17521753
elif isinstance(self.window, BaseIndexer):
17531754
# Passed BaseIndexer subclass should handle all other rolling kwargs
17541755
pass
17551756
elif not is_integer(self.window) or self.window < 0:
17561757
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-
)
17701758

17711759
def _validate_datetimelike_monotonic(self):
17721760
"""

pandas/io/formats/style.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,6 +2689,13 @@ def hide(
26892689
26902690
Notes
26912691
-----
2692+
.. warning::
2693+
This method only works with the output methods ``to_html``, ``to_string``
2694+
and ``to_latex``.
2695+
2696+
Other output methods, including ``to_excel``, ignore this hiding method
2697+
and will display all data.
2698+
26922699
This method has multiple functionality depending upon the combination
26932700
of the ``subset``, ``level`` and ``names`` arguments (see examples). The
26942701
``axis`` argument is used only to control whether the method is applied to row

0 commit comments

Comments
 (0)