diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 83a9edfb239e2..b4d1787697973 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -524,7 +524,7 @@ Other - Bug in :meth:`DataFrame.replace` and :meth:`Series.replace` incorrectly raising ``AssertionError`` instead of ``ValueError`` when invalid parameter combinations are passed (:issue:`36045`) - Bug in :meth:`DataFrame.replace` and :meth:`Series.replace` with numeric values and string ``to_replace`` (:issue:`34789`) - Fixed bug in metadata propagation incorrectly copying DataFrame columns as metadata when the column name overlaps with the metadata name (:issue:`37037`) -- Fixed metadata propagation in the :class:`Series.dt` and :class:`Series.str` accessors (:issue:`28283`) +- Fixed metadata propagation in the :class:`Series.dt` and :class:`Series.str` accessors and :class:`DataFrame.duplicated` and ::class:`DataFrame.stack` methods (:issue:`28283`) - Bug in :meth:`Index.union` behaving differently depending on whether operand is a :class:`Index` or other list-like (:issue:`36384`) - Passing an array with 2 or more dimensions to the :class:`Series` constructor now raises the more specific ``ValueError``, from a bare ``Exception`` previously (:issue:`35744`) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 801307a8f9481..ee8a83fd6c091 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -5286,7 +5286,8 @@ def f(vals): labels, shape = map(list, zip(*map(f, vals))) ids = get_group_index(labels, shape, sort=False, xnull=False) - return self._constructor_sliced(duplicated_int64(ids, keep), index=self.index) + result = self._constructor_sliced(duplicated_int64(ids, keep), index=self.index) + return result.__finalize__(self, method="duplicated") # ---------------------------------------------------------------------- # Sorting @@ -7096,9 +7097,11 @@ def stack(self, level=-1, dropna=True): from pandas.core.reshape.reshape import stack, stack_multiple if isinstance(level, (tuple, list)): - return stack_multiple(self, level, dropna=dropna) + result = stack_multiple(self, level, dropna=dropna) else: - return stack(self, level, dropna=dropna) + result = stack(self, level, dropna=dropna) + + return result.__finalize__(self, method="stack") def explode( self, column: Union[str, Tuple], ignore_index: bool = False diff --git a/pandas/tests/generic/test_finalize.py b/pandas/tests/generic/test_finalize.py index 9d1f52e03b3d1..9d2e5cbcc7b58 100644 --- a/pandas/tests/generic/test_finalize.py +++ b/pandas/tests/generic/test_finalize.py @@ -115,10 +115,7 @@ (pd.DataFrame, frame_data, operator.methodcaller("notnull")), (pd.DataFrame, frame_data, operator.methodcaller("dropna")), (pd.DataFrame, frame_data, operator.methodcaller("drop_duplicates")), - pytest.param( - (pd.DataFrame, frame_data, operator.methodcaller("duplicated")), - marks=not_implemented_mark, - ), + (pd.DataFrame, frame_data, operator.methodcaller("duplicated")), (pd.DataFrame, frame_data, operator.methodcaller("sort_values", by="A")), (pd.DataFrame, frame_data, operator.methodcaller("sort_index")), (pd.DataFrame, frame_data, operator.methodcaller("nlargest", 1, "A")), @@ -169,10 +166,7 @@ ), marks=not_implemented_mark, ), - pytest.param( - (pd.DataFrame, frame_data, operator.methodcaller("stack")), - marks=not_implemented_mark, - ), + (pd.DataFrame, frame_data, operator.methodcaller("stack")), pytest.param( (pd.DataFrame, frame_data, operator.methodcaller("explode", "A")), marks=not_implemented_mark,