diff --git a/doc/source/v0.14.1.txt b/doc/source/v0.14.1.txt index be0b3bc543c39..779f8edd51b4e 100644 --- a/doc/source/v0.14.1.txt +++ b/doc/source/v0.14.1.txt @@ -235,3 +235,4 @@ Bug Fixes - Bug in non-monotonic ``Index.union`` may preserve ``name`` incorrectly (:issue:`7458`) - Bug in ``DatetimeIndex.intersection`` doesn't preserve timezone (:issue:`4690`) +- Bug in ``unstack`` when columns contained mixed dtypes (:issue:`7405`). diff --git a/pandas/core/reshape.py b/pandas/core/reshape.py index e1712be7b5a5f..8cb482aaa22ea 100644 --- a/pandas/core/reshape.py +++ b/pandas/core/reshape.py @@ -242,7 +242,12 @@ def get_new_index(self): # construct the new index if len(self.new_index_levels) == 1: + result_labels = result_labels[0] new_index = self.new_index_levels[0] + + if len(new_index) != len(result_labels): + new_index = new_index.take(result_labels) + new_index.name = self.new_index_names[0] else: new_index = MultiIndex(levels=self.new_index_levels, diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 4ebf3dd99a105..c969c13745786 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -11706,6 +11706,38 @@ def test_unstack_non_unique_index_names(self): with tm.assertRaises(ValueError): df.T.stack('c1') + def test_unstack_mixed_dtypes(self): + n = 5 + df = DataFrame({'A': ['a'] * n, + 'B': pd.date_range('20120101', periods=n), + 'C': np.zeros(n), + 'D': np.zeros(n, dtype='i8')}).set_index(list("AB")) + expected = df.unstack(0).iloc[:3] + result = df.iloc[:3].unstack(0) + tm.assert_frame_equal(result, expected) + + def test_unstack_mixed_dtypes_different_method(self): + n = 5 + df = DataFrame({'A': ['a'] * n, + 'B': pd.date_range('20120101', periods=n), + 'C': np.zeros(n), + 'D': np.zeros(n, dtype='i8')}).set_index(list("AB")) + result = df.iloc[:3].unstack(0) + other = df.iloc[:3].reset_index().set_index(list("AB")).unstack(0) + tm.assert_frame_equal(result, other) + + def test_unstack_mixed_dtypes_with_mi_and_nat_different_method(self): + n = 5 + B = pd.date_range('20120101', periods=n - 1).tolist() + B.insert(3, pd.NaT) + df = DataFrame({'A': ['a'] * n, + 'B': B, + 'C': np.zeros(n), + 'D': np.zeros(n, dtype='i8')}).set_index(list("AB")) + result = df.iloc[:3].unstack(0) + other = df.iloc[:3].reset_index().set_index(list("AB")).unstack(0) + tm.assert_frame_equal(result, other) + def test_repr_with_mi_nat(self): df = DataFrame({'X': [1, 2]}, index=[[pd.NaT, pd.Timestamp('20130101')], ['a', 'b']])