|
58 | 58 | is_dict_like,
|
59 | 59 | is_integer_dtype,
|
60 | 60 | is_interval_dtype,
|
| 61 | + is_numeric_dtype, |
61 | 62 | is_scalar,
|
62 | 63 | )
|
63 | 64 | from pandas.core.dtypes.missing import (
|
@@ -172,9 +173,18 @@ def _wrap_agged_manager(self, mgr: Manager) -> Series:
|
172 | 173 | # NB: caller is responsible for setting ser.index
|
173 | 174 | return ser
|
174 | 175 |
|
175 |
| - def _get_data_to_aggregate(self) -> SingleManager: |
| 176 | + def _get_data_to_aggregate( |
| 177 | + self, *, numeric_only: bool = False, name: str | None = None |
| 178 | + ) -> SingleManager: |
176 | 179 | ser = self._selected_obj
|
177 | 180 | single = ser._mgr
|
| 181 | + if numeric_only and not is_numeric_dtype(ser.dtype): |
| 182 | + # GH#41291 match Series behavior |
| 183 | + kwd_name = "numeric_only" |
| 184 | + raise TypeError( |
| 185 | + f"Cannot use {kwd_name}=True with " |
| 186 | + f"{type(self).__name__}.{name} and non-numeric dtypes." |
| 187 | + ) |
178 | 188 | return single
|
179 | 189 |
|
180 | 190 | def _iterate_slices(self) -> Iterable[Series]:
|
@@ -380,10 +390,16 @@ def _wrap_applied_output(
|
380 | 390 | """
|
381 | 391 | if len(values) == 0:
|
382 | 392 | # GH #6265
|
| 393 | + if is_transform: |
| 394 | + # GH#47787 see test_group_on_empty_multiindex |
| 395 | + res_index = data.index |
| 396 | + else: |
| 397 | + res_index = self.grouper.result_index |
| 398 | + |
383 | 399 | return self.obj._constructor(
|
384 | 400 | [],
|
385 | 401 | name=self.obj.name,
|
386 |
| - index=self.grouper.result_index, |
| 402 | + index=res_index, |
387 | 403 | dtype=data.dtype,
|
388 | 404 | )
|
389 | 405 | assert values is not None
|
@@ -1136,14 +1152,12 @@ def cov(
|
1136 | 1152 | @property
|
1137 | 1153 | @doc(Series.is_monotonic_increasing.__doc__)
|
1138 | 1154 | def is_monotonic_increasing(self) -> Series:
|
1139 |
| - result = self._op_via_apply("is_monotonic_increasing") |
1140 |
| - return result |
| 1155 | + return self.apply(lambda ser: ser.is_monotonic_increasing) |
1141 | 1156 |
|
1142 | 1157 | @property
|
1143 | 1158 | @doc(Series.is_monotonic_decreasing.__doc__)
|
1144 | 1159 | def is_monotonic_decreasing(self) -> Series:
|
1145 |
| - result = self._op_via_apply("is_monotonic_decreasing") |
1146 |
| - return result |
| 1160 | + return self.apply(lambda ser: ser.is_monotonic_decreasing) |
1147 | 1161 |
|
1148 | 1162 | @doc(Series.hist.__doc__)
|
1149 | 1163 | def hist(
|
@@ -1181,8 +1195,7 @@ def hist(
|
1181 | 1195 | @property
|
1182 | 1196 | @doc(Series.dtype.__doc__)
|
1183 | 1197 | def dtype(self) -> Series:
|
1184 |
| - result = self._op_via_apply("dtype") |
1185 |
| - return result |
| 1198 | + return self.apply(lambda ser: ser.dtype) |
1186 | 1199 |
|
1187 | 1200 | @doc(Series.unique.__doc__)
|
1188 | 1201 | def unique(self) -> Series:
|
@@ -1428,9 +1441,13 @@ def _wrap_applied_output(
|
1428 | 1441 | ):
|
1429 | 1442 |
|
1430 | 1443 | if len(values) == 0:
|
1431 |
| - result = self.obj._constructor( |
1432 |
| - index=self.grouper.result_index, columns=data.columns |
1433 |
| - ) |
| 1444 | + if is_transform: |
| 1445 | + # GH#47787 see test_group_on_empty_multiindex |
| 1446 | + res_index = data.index |
| 1447 | + else: |
| 1448 | + res_index = self.grouper.result_index |
| 1449 | + |
| 1450 | + result = self.obj._constructor(index=res_index, columns=data.columns) |
1434 | 1451 | result = result.astype(data.dtypes, copy=False)
|
1435 | 1452 | return result
|
1436 | 1453 |
|
@@ -1542,9 +1559,9 @@ def _cython_transform(
|
1542 | 1559 | # test_transform_numeric_ret
|
1543 | 1560 | # With self.axis == 1, _get_data_to_aggregate does a transpose
|
1544 | 1561 | # so we always have a single block.
|
1545 |
| - mgr: Manager2D = self._get_data_to_aggregate() |
1546 |
| - if numeric_only: |
1547 |
| - mgr = mgr.get_numeric_data(copy=False) |
| 1562 | + mgr: Manager2D = self._get_data_to_aggregate( |
| 1563 | + numeric_only=numeric_only, name=how |
| 1564 | + ) |
1548 | 1565 |
|
1549 | 1566 | def arr_func(bvalues: ArrayLike) -> ArrayLike:
|
1550 | 1567 | return self.grouper._cython_operation(
|
@@ -1719,18 +1736,11 @@ def _transform_item_by_item(self, obj: DataFrame, wrapper) -> DataFrame:
|
1719 | 1736 | # iterate through columns, see test_transform_exclude_nuisance
|
1720 | 1737 | # gets here with non-unique columns
|
1721 | 1738 | output = {}
|
1722 |
| - inds = [] |
1723 | 1739 | for i, (colname, sgb) in enumerate(self._iterate_column_groupbys(obj)):
|
1724 | 1740 | output[i] = sgb.transform(wrapper)
|
1725 |
| - inds.append(i) |
1726 |
| - |
1727 |
| - if not output: |
1728 |
| - raise TypeError("Transform function invalid for data types") |
1729 |
| - |
1730 |
| - columns = obj.columns.take(inds) |
1731 | 1741 |
|
1732 | 1742 | result = self.obj._constructor(output, index=obj.index)
|
1733 |
| - result.columns = columns |
| 1743 | + result.columns = obj.columns |
1734 | 1744 | return result
|
1735 | 1745 |
|
1736 | 1746 | def filter(self, func, dropna: bool = True, *args, **kwargs):
|
@@ -1864,12 +1874,18 @@ def _gotitem(self, key, ndim: int, subset=None):
|
1864 | 1874 |
|
1865 | 1875 | raise AssertionError("invalid ndim for _gotitem")
|
1866 | 1876 |
|
1867 |
| - def _get_data_to_aggregate(self) -> Manager2D: |
| 1877 | + def _get_data_to_aggregate( |
| 1878 | + self, *, numeric_only: bool = False, name: str | None = None |
| 1879 | + ) -> Manager2D: |
1868 | 1880 | obj = self._obj_with_exclusions
|
1869 | 1881 | if self.axis == 1:
|
1870 |
| - return obj.T._mgr |
| 1882 | + mgr = obj.T._mgr |
1871 | 1883 | else:
|
1872 |
| - return obj._mgr |
| 1884 | + mgr = obj._mgr |
| 1885 | + |
| 1886 | + if numeric_only: |
| 1887 | + mgr = mgr.get_numeric_data(copy=False) |
| 1888 | + return mgr |
1873 | 1889 |
|
1874 | 1890 | def _indexed_output_to_ndframe(
|
1875 | 1891 | self, output: Mapping[base.OutputKey, ArrayLike]
|
@@ -2677,8 +2693,8 @@ def hist(
|
2677 | 2693 | @property
|
2678 | 2694 | @doc(DataFrame.dtypes.__doc__)
|
2679 | 2695 | def dtypes(self) -> Series:
|
2680 |
| - result = self._op_via_apply("dtypes") |
2681 |
| - return result |
| 2696 | + # error: Incompatible return value type (got "DataFrame", expected "Series") |
| 2697 | + return self.apply(lambda df: df.dtypes) # type: ignore[return-value] |
2682 | 2698 |
|
2683 | 2699 | @doc(DataFrame.corrwith.__doc__)
|
2684 | 2700 | def corrwith(
|
|
0 commit comments