diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 0173807cb9bd0..f89ea6dd184ee 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -137,6 +137,7 @@ Numeric Conversion ^^^^^^^^^^ +- Bug in :meth:`DataFrame.astype` not preserving subclasses (:issue:`40810`) - Bug in constructing a :class:`Series` from a float-containing list or a floating-dtype ndarray-like (e.g. ``dask.Array``) and an integer dtype raising instead of casting like we would with an ``np.ndarray`` (:issue:`40110`) - diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 58e967e4c7899..d0464ee3b9c46 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -5891,6 +5891,12 @@ def astype( # GH 19920: retain column metadata after concat result = concat(results, axis=1, copy=False) + # GH#40810 retain subclass + # Incompatible types in assignment (expression has type "NDFrameT", + # variable has type "DataFrame") + # Argument 1 to "NDFrame" has incompatible type "DataFrame"; expected + # "Union[ArrayManager, SingleArrayManager, BlockManager, SingleBlockManager]" + result = self._constructor(result) # type: ignore[arg-type,assignment] result.columns = self.columns result = result.__finalize__(self, method="astype") # https://github.com/python/mypy/issues/8354 diff --git a/pandas/tests/frame/test_subclass.py b/pandas/tests/frame/test_subclass.py index 8d9957b24300f..0d6cf39f801db 100644 --- a/pandas/tests/frame/test_subclass.py +++ b/pandas/tests/frame/test_subclass.py @@ -723,6 +723,13 @@ def test_convert_dtypes_preserves_subclass(self, gpd_style_subclass_df): result = gpd_style_subclass_df.convert_dtypes() assert isinstance(result, type(gpd_style_subclass_df)) + def test_astype_preserves_subclass(self): + # GH#40810 + df = tm.SubclassedDataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]}) + + result = df.astype({"A": np.int64, "B": np.int32, "C": np.float64}) + assert isinstance(result, tm.SubclassedDataFrame) + def test_equals_subclass(self): # https://github.com/pandas-dev/pandas/pull/34402 # allow subclass in both directions