Skip to content

Commit 596c591

Browse files
authored
Merge branch 'main' into cooolheater-issue59965
2 parents db6a83f + d41884b commit 596c591

File tree

15 files changed

+149
-83
lines changed

15 files changed

+149
-83
lines changed

ci/code_checks.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
8181
-i "pandas.Timestamp.resolution PR02" \
8282
-i "pandas.Timestamp.tzinfo GL08" \
8383
-i "pandas.arrays.ArrowExtensionArray PR07,SA01" \
84-
-i "pandas.arrays.IntervalArray.length SA01" \
8584
-i "pandas.arrays.NumpyExtensionArray SA01" \
8685
-i "pandas.arrays.TimedeltaArray PR07,SA01" \
8786
-i "pandas.core.groupby.DataFrameGroupBy.plot PR02" \

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Other enhancements
5656
- :meth:`DataFrame.plot.scatter` argument ``c`` now accepts a column of strings, where rows with the same string are colored identically (:issue:`16827` and :issue:`16485`)
5757
- :func:`read_parquet` accepts ``to_pandas_kwargs`` which are forwarded to :meth:`pyarrow.Table.to_pandas` which enables passing additional keywords to customize the conversion to pandas, such as ``maps_as_pydicts`` to read the Parquet map data type as python dictionaries (:issue:`56842`)
5858
- :meth:`DataFrameGroupBy.transform`, :meth:`SeriesGroupBy.transform`, :meth:`DataFrameGroupBy.agg`, :meth:`SeriesGroupBy.agg`, :meth:`RollingGroupby.apply`, :meth:`ExpandingGroupby.apply`, :meth:`Rolling.apply`, :meth:`Expanding.apply`, :meth:`DataFrame.apply` with ``engine="numba"`` now supports positional arguments passed as kwargs (:issue:`58995`)
59+
- :meth:`Rolling.agg`, :meth:`Expanding.agg` and :meth:`ExponentialMovingWindow.agg` now accept :class:`NamedAgg` aggregations through ``**kwargs`` (:issue:`28333`)
5960
- :meth:`Series.map` can now accept kwargs to pass on to func (:issue:`59814`)
6061
- :meth:`pandas.concat` will raise a ``ValueError`` when ``ignore_index=True`` and ``keys`` is not ``None`` (:issue:`59274`)
6162
- :meth:`str.get_dummies` now accepts a ``dtype`` parameter to specify the dtype of the resulting DataFrame (:issue:`47872`)

pandas/core/arrays/interval.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,20 @@ def length(self) -> Index:
13061306
"""
13071307
Return an Index with entries denoting the length of each Interval.
13081308
1309+
The length of an interval is calculated as the difference between
1310+
its `right` and `left` bounds. This property is particularly useful
1311+
when working with intervals where the size of the interval is an important
1312+
attribute, such as in time-series analysis or spatial data analysis.
1313+
1314+
See Also
1315+
--------
1316+
arrays.IntervalArray.left : Return the left endpoints of each Interval in
1317+
the IntervalArray as an Index.
1318+
arrays.IntervalArray.right : Return the right endpoints of each Interval in
1319+
the IntervalArray as an Index.
1320+
arrays.IntervalArray.mid : Return the midpoint of each Interval in the
1321+
IntervalArray as an Index.
1322+
13091323
Examples
13101324
--------
13111325

pandas/core/window/ewm.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ def online(
490490
klass="Series/Dataframe",
491491
axis="",
492492
)
493-
def aggregate(self, func, *args, **kwargs):
493+
def aggregate(self, func=None, *args, **kwargs):
494494
return super().aggregate(func, *args, **kwargs)
495495

496496
agg = aggregate
@@ -981,7 +981,7 @@ def reset(self) -> None:
981981
"""
982982
self._mean.reset()
983983

984-
def aggregate(self, func, *args, **kwargs):
984+
def aggregate(self, func=None, *args, **kwargs):
985985
raise NotImplementedError("aggregate is not implemented.")
986986

987987
def std(self, bias: bool = False, *args, **kwargs):

pandas/core/window/expanding.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def _get_window_indexer(self) -> BaseIndexer:
167167
klass="Series/Dataframe",
168168
axis="",
169169
)
170-
def aggregate(self, func, *args, **kwargs):
170+
def aggregate(self, func=None, *args, **kwargs):
171171
return super().aggregate(func, *args, **kwargs)
172172

173173
agg = aggregate

pandas/core/window/rolling.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@
4444

4545
from pandas.core._numba import executor
4646
from pandas.core.algorithms import factorize
47-
from pandas.core.apply import ResamplerWindowApply
47+
from pandas.core.apply import (
48+
ResamplerWindowApply,
49+
reconstruct_func,
50+
)
4851
from pandas.core.arrays import ExtensionArray
4952
from pandas.core.base import SelectionMixin
5053
import pandas.core.common as com
@@ -646,8 +649,12 @@ def _numba_apply(
646649
out = obj._constructor(result, index=index, columns=columns)
647650
return self._resolve_output(out, obj)
648651

649-
def aggregate(self, func, *args, **kwargs):
652+
def aggregate(self, func=None, *args, **kwargs):
653+
relabeling, func, columns, order = reconstruct_func(func, **kwargs)
650654
result = ResamplerWindowApply(self, func, args=args, kwargs=kwargs).agg()
655+
if isinstance(result, ABCDataFrame) and relabeling:
656+
result = result.iloc[:, order]
657+
result.columns = columns # type: ignore[union-attr]
651658
if result is None:
652659
return self.apply(func, raw=False, args=args, kwargs=kwargs)
653660
return result
@@ -1239,7 +1246,7 @@ def calc(x):
12391246
klass="Series/DataFrame",
12401247
axis="",
12411248
)
1242-
def aggregate(self, func, *args, **kwargs):
1249+
def aggregate(self, func=None, *args, **kwargs):
12431250
result = ResamplerWindowApply(self, func, args=args, kwargs=kwargs).agg()
12441251
if result is None:
12451252
# these must apply directly
@@ -1951,7 +1958,7 @@ def _raise_monotonic_error(self, msg: str):
19511958
klass="Series/Dataframe",
19521959
axis="",
19531960
)
1954-
def aggregate(self, func, *args, **kwargs):
1961+
def aggregate(self, func=None, *args, **kwargs):
19551962
return super().aggregate(func, *args, **kwargs)
19561963

19571964
agg = aggregate

pandas/io/sql.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ def read_sql_table( # pyright: ignore[reportOverlappingOverload]
241241
schema=...,
242242
index_col: str | list[str] | None = ...,
243243
coerce_float=...,
244-
parse_dates: list[str] | dict[str, str] | None = ...,
244+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
245245
columns: list[str] | None = ...,
246246
chunksize: None = ...,
247247
dtype_backend: DtypeBackend | lib.NoDefault = ...,
@@ -255,7 +255,7 @@ def read_sql_table(
255255
schema=...,
256256
index_col: str | list[str] | None = ...,
257257
coerce_float=...,
258-
parse_dates: list[str] | dict[str, str] | None = ...,
258+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
259259
columns: list[str] | None = ...,
260260
chunksize: int = ...,
261261
dtype_backend: DtypeBackend | lib.NoDefault = ...,
@@ -268,7 +268,7 @@ def read_sql_table(
268268
schema: str | None = None,
269269
index_col: str | list[str] | None = None,
270270
coerce_float: bool = True,
271-
parse_dates: list[str] | dict[str, str] | None = None,
271+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = None,
272272
columns: list[str] | None = None,
273273
chunksize: int | None = None,
274274
dtype_backend: DtypeBackend | lib.NoDefault = lib.no_default,
@@ -372,7 +372,7 @@ def read_sql_query( # pyright: ignore[reportOverlappingOverload]
372372
index_col: str | list[str] | None = ...,
373373
coerce_float=...,
374374
params: list[Any] | Mapping[str, Any] | None = ...,
375-
parse_dates: list[str] | dict[str, str] | None = ...,
375+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
376376
chunksize: None = ...,
377377
dtype: DtypeArg | None = ...,
378378
dtype_backend: DtypeBackend | lib.NoDefault = ...,
@@ -386,7 +386,7 @@ def read_sql_query(
386386
index_col: str | list[str] | None = ...,
387387
coerce_float=...,
388388
params: list[Any] | Mapping[str, Any] | None = ...,
389-
parse_dates: list[str] | dict[str, str] | None = ...,
389+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
390390
chunksize: int = ...,
391391
dtype: DtypeArg | None = ...,
392392
dtype_backend: DtypeBackend | lib.NoDefault = ...,
@@ -399,7 +399,7 @@ def read_sql_query(
399399
index_col: str | list[str] | None = None,
400400
coerce_float: bool = True,
401401
params: list[Any] | Mapping[str, Any] | None = None,
402-
parse_dates: list[str] | dict[str, str] | None = None,
402+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = None,
403403
chunksize: int | None = None,
404404
dtype: DtypeArg | None = None,
405405
dtype_backend: DtypeBackend | lib.NoDefault = lib.no_default,

pandas/tests/groupby/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ def get_groupby_method_args(name, obj):
22
"""
33
Get required arguments for a groupby method.
44
5-
When parametrizing a test over groupby methods (e.g. "sum", "mean", "fillna"),
5+
When parametrizing a test over groupby methods (e.g. "sum", "mean"),
66
it is often the case that arguments are required for certain methods.
77
88
Parameters
@@ -16,7 +16,7 @@ def get_groupby_method_args(name, obj):
1616
-------
1717
A tuple of required arguments for the method.
1818
"""
19-
if name in ("nth", "fillna", "take"):
19+
if name in ("nth", "take"):
2020
return (0,)
2121
if name == "quantile":
2222
return (0.5,)

pandas/tests/groupby/test_categorical.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,10 +1963,7 @@ def test_category_order_transformer(
19631963
df = df.set_index(keys)
19641964
args = get_groupby_method_args(transformation_func, df)
19651965
gb = df.groupby(keys, as_index=as_index, sort=sort, observed=observed)
1966-
warn = FutureWarning if transformation_func == "fillna" else None
1967-
msg = "DataFrameGroupBy.fillna is deprecated"
1968-
with tm.assert_produces_warning(warn, match=msg):
1969-
op_result = getattr(gb, transformation_func)(*args)
1966+
op_result = getattr(gb, transformation_func)(*args)
19701967
result = op_result.index.get_level_values("a").categories
19711968
expected = Index([1, 4, 3, 2])
19721969
tm.assert_index_equal(result, expected)

pandas/tests/groupby/test_groupby.py

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,36 +2098,14 @@ def test_group_on_empty_multiindex(transformation_func, request):
20982098
df["col_3"] = df["col_3"].astype(int)
20992099
df["col_4"] = df["col_4"].astype(int)
21002100
df = df.set_index(["col_1", "col_2"])
2101-
if transformation_func == "fillna":
2102-
args = ("ffill",)
2103-
else:
2104-
args = ()
2105-
warn = FutureWarning if transformation_func == "fillna" else None
2106-
warn_msg = "DataFrameGroupBy.fillna is deprecated"
2107-
with tm.assert_produces_warning(warn, match=warn_msg):
2108-
result = df.iloc[:0].groupby(["col_1"]).transform(transformation_func, *args)
2109-
with tm.assert_produces_warning(warn, match=warn_msg):
2110-
expected = df.groupby(["col_1"]).transform(transformation_func, *args).iloc[:0]
2101+
result = df.iloc[:0].groupby(["col_1"]).transform(transformation_func)
2102+
expected = df.groupby(["col_1"]).transform(transformation_func).iloc[:0]
21112103
if transformation_func in ("diff", "shift"):
21122104
expected = expected.astype(int)
21132105
tm.assert_equal(result, expected)
21142106

2115-
warn_msg = "SeriesGroupBy.fillna is deprecated"
2116-
with tm.assert_produces_warning(warn, match=warn_msg):
2117-
result = (
2118-
df["col_3"]
2119-
.iloc[:0]
2120-
.groupby(["col_1"])
2121-
.transform(transformation_func, *args)
2122-
)
2123-
warn_msg = "SeriesGroupBy.fillna is deprecated"
2124-
with tm.assert_produces_warning(warn, match=warn_msg):
2125-
expected = (
2126-
df["col_3"]
2127-
.groupby(["col_1"])
2128-
.transform(transformation_func, *args)
2129-
.iloc[:0]
2130-
)
2107+
result = df["col_3"].iloc[:0].groupby(["col_1"]).transform(transformation_func)
2108+
expected = df["col_3"].groupby(["col_1"]).transform(transformation_func).iloc[:0]
21312109
if transformation_func in ("diff", "shift"):
21322110
expected = expected.astype(int)
21332111
tm.assert_equal(result, expected)

pandas/tests/groupby/test_groupby_subclass.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ def test_groupby_preserves_subclass(obj, groupby_func):
3636

3737
args = get_groupby_method_args(groupby_func, obj)
3838

39-
warn = FutureWarning if groupby_func == "fillna" else None
40-
msg = f"{type(grouped).__name__}.fillna is deprecated"
41-
with tm.assert_produces_warning(warn, match=msg, raise_on_extra_warnings=False):
39+
warn = FutureWarning if groupby_func == "corrwith" else None
40+
msg = f"{type(grouped).__name__}.corrwith is deprecated"
41+
with tm.assert_produces_warning(warn, match=msg):
4242
result1 = getattr(grouped, groupby_func)(*args)
43-
with tm.assert_produces_warning(warn, match=msg, raise_on_extra_warnings=False):
43+
with tm.assert_produces_warning(warn, match=msg):
4444
result2 = grouped.agg(groupby_func, *args)
4545

4646
# Reduction or transformation kernels should preserve type

pandas/tests/groupby/test_numeric_only.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,11 @@ def test_numeric_only(kernel, has_arg, numeric_only, keys):
278278
kernel in ("first", "last")
279279
or (
280280
# kernels that work on any dtype and don't have numeric_only arg
281-
kernel in ("any", "all", "bfill", "ffill", "fillna", "nth", "nunique")
281+
kernel in ("any", "all", "bfill", "ffill", "nth", "nunique")
282282
and numeric_only is lib.no_default
283283
)
284284
):
285-
warn = FutureWarning if kernel == "fillna" else None
286-
msg = "DataFrameGroupBy.fillna is deprecated"
287-
with tm.assert_produces_warning(warn, match=msg):
288-
result = method(*args, **kwargs)
285+
result = method(*args, **kwargs)
289286
assert "b" in result.columns
290287
elif has_arg:
291288
assert numeric_only is not True

pandas/tests/groupby/test_raises.py

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ def test_groupby_raises_string(
144144
),
145145
"diff": (TypeError, "unsupported operand type"),
146146
"ffill": (None, ""),
147-
"fillna": (None, ""),
148147
"first": (None, ""),
149148
"idxmax": (None, ""),
150149
"idxmin": (None, ""),
@@ -211,10 +210,7 @@ def test_groupby_raises_string(
211210
elif groupby_func == "corrwith":
212211
msg = "Cannot perform reduction 'mean' with string dtype"
213212

214-
if groupby_func == "fillna":
215-
kind = "Series" if groupby_series else "DataFrame"
216-
warn_msg = f"{kind}GroupBy.fillna is deprecated"
217-
elif groupby_func == "corrwith":
213+
if groupby_func == "corrwith":
218214
warn_msg = "DataFrameGroupBy.corrwith is deprecated"
219215
else:
220216
warn_msg = ""
@@ -301,7 +297,6 @@ def test_groupby_raises_datetime(
301297
"cumsum": (TypeError, "datetime64 type does not support operation 'cumsum'"),
302298
"diff": (None, ""),
303299
"ffill": (None, ""),
304-
"fillna": (None, ""),
305300
"first": (None, ""),
306301
"idxmax": (None, ""),
307302
"idxmin": (None, ""),
@@ -333,10 +328,7 @@ def test_groupby_raises_datetime(
333328
"var": (TypeError, "datetime64 type does not support operation 'var'"),
334329
}[groupby_func]
335330

336-
if groupby_func == "fillna":
337-
kind = "Series" if groupby_series else "DataFrame"
338-
warn_msg = f"{kind}GroupBy.fillna is deprecated"
339-
elif groupby_func == "corrwith":
331+
if groupby_func == "corrwith":
340332
warn_msg = "DataFrameGroupBy.corrwith is deprecated"
341333
else:
342334
warn_msg = ""
@@ -457,7 +449,6 @@ def test_groupby_raises_category(
457449
r"unsupported operand type\(s\) for -: 'Categorical' and 'Categorical'",
458450
),
459451
"ffill": (None, ""),
460-
"fillna": (None, ""), # no-op with CoW
461452
"first": (None, ""),
462453
"idxmax": (None, ""),
463454
"idxmin": (None, ""),
@@ -532,10 +523,7 @@ def test_groupby_raises_category(
532523
),
533524
}[groupby_func]
534525

535-
if groupby_func == "fillna":
536-
kind = "Series" if groupby_series else "DataFrame"
537-
warn_msg = f"{kind}GroupBy.fillna is deprecated"
538-
elif groupby_func == "corrwith":
526+
if groupby_func == "corrwith":
539527
warn_msg = "DataFrameGroupBy.corrwith is deprecated"
540528
else:
541529
warn_msg = ""
@@ -650,7 +638,6 @@ def test_groupby_raises_category_on_category(
650638
),
651639
"diff": (TypeError, "unsupported operand type"),
652640
"ffill": (None, ""),
653-
"fillna": (None, ""), # no-op with CoW
654641
"first": (None, ""),
655642
"idxmax": (ValueError, "empty group due to unobserved categories")
656643
if empty_groups
@@ -710,10 +697,7 @@ def test_groupby_raises_category_on_category(
710697
),
711698
}[groupby_func]
712699

713-
if groupby_func == "fillna":
714-
kind = "Series" if groupby_series else "DataFrame"
715-
warn_msg = f"{kind}GroupBy.fillna is deprecated"
716-
elif groupby_func == "corrwith":
700+
if groupby_func == "corrwith":
717701
warn_msg = "DataFrameGroupBy.corrwith is deprecated"
718702
else:
719703
warn_msg = ""

pandas/tests/groupby/transform/test_transform.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,6 @@ def test_transform_transformation_func(transformation_func):
329329
if transformation_func == "cumcount":
330330
test_op = lambda x: x.transform("cumcount")
331331
mock_op = lambda x: Series(range(len(x)), x.index)
332-
elif transformation_func == "fillna":
333-
test_op = lambda x: x.transform("fillna", value=0)
334-
mock_op = lambda x: x.fillna(value=0)
335332
elif transformation_func == "ngroup":
336333
test_op = lambda x: x.transform("ngroup")
337334
counter = -1
@@ -1436,11 +1433,7 @@ def test_null_group_str_transformer_series(dropna, transformation_func):
14361433
dtype = object if transformation_func in ("any", "all") else None
14371434
buffer.append(Series([np.nan], index=[3], dtype=dtype))
14381435
expected = concat(buffer)
1439-
1440-
warn = FutureWarning if transformation_func == "fillna" else None
1441-
msg = "SeriesGroupBy.fillna is deprecated"
1442-
with tm.assert_produces_warning(warn, match=msg):
1443-
result = gb.transform(transformation_func, *args)
1436+
result = gb.transform(transformation_func, *args)
14441437

14451438
tm.assert_equal(result, expected)
14461439

0 commit comments

Comments
 (0)