diff --git a/doc/source/whatsnew/v0.16.1.txt b/doc/source/whatsnew/v0.16.1.txt index ca316bbac8474..eaf8054c69b18 100644 --- a/doc/source/whatsnew/v0.16.1.txt +++ b/doc/source/whatsnew/v0.16.1.txt @@ -69,7 +69,7 @@ Bug Fixes - Bug in ``transform`` causing length mismatch when null entries were present and a fast aggregator was being used (:issue:`9697`) - +- Bug in ``DataFrame`` slicing may not retain metadata (:issue:`9776`) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index e05709d7a180f..555954f112f5a 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1179,6 +1179,7 @@ def _slice(self, slobj, axis=0, kind=None): """ axis = self._get_block_manager_axis(axis) result = self._constructor(self._data.get_slice(slobj, axis=axis)) + result = result.__finalize__(self) # this could be a view # but only in a single-dtyped view slicable case diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 1acad4cf978a8..31dc7de1e1b67 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -14057,6 +14057,28 @@ def test_assign_bad(self): with tm.assertRaises(KeyError): df.assign(C=df.A, D=lambda x: x['A'] + x['C']) + def test_dataframe_metadata(self): + + class TestDataFrame(DataFrame): + _metadata = ['testattr'] + + @property + def _constructor(self): + return TestDataFrame + + + df = TestDataFrame({'X': [1, 2, 3], 'Y': [1, 2, 3]}, + index=['a', 'b', 'c']) + df.testattr = 'XXX' + + self.assertEqual(df.testattr, 'XXX') + self.assertEqual(df[['X']].testattr, 'XXX') + self.assertEqual(df.loc[['a', 'b'], :].testattr, 'XXX') + self.assertEqual(df.iloc[[0, 1], :].testattr, 'XXX') + # GH9776 + self.assertEqual(df.iloc[0:1, :].testattr, 'XXX') + + def skip_if_no_ne(engine='numexpr'): if engine == 'numexpr': try: