diff --git a/doc/source/whatsnew/v0.19.1.txt b/doc/source/whatsnew/v0.19.1.txt index 1c5f4915bb3a4..b237d095fab34 100644 --- a/doc/source/whatsnew/v0.19.1.txt +++ b/doc/source/whatsnew/v0.19.1.txt @@ -30,3 +30,4 @@ Performance Improvements Bug Fixes ~~~~~~~~~ +- Bug in ``concat`` where names of keys were not propagated to the resulting MultiIndex (:issue:`14252`) \ No newline at end of file diff --git a/pandas/tests/frame/test_combine_concat.py b/pandas/tests/frame/test_combine_concat.py index e5aaba26135e7..b7cd8a1c01224 100644 --- a/pandas/tests/frame/test_combine_concat.py +++ b/pandas/tests/frame/test_combine_concat.py @@ -4,21 +4,21 @@ from datetime import datetime -from numpy import nan import numpy as np +from numpy import nan -from pandas.compat import lrange -from pandas import DataFrame, Series, Index, Timestamp import pandas as pd -from pandas.util.testing import (assert_series_equal, - assert_frame_equal, - assertRaisesRegexp) - -import pandas.util.testing as tm +from pandas import DataFrame, Index, Series, Timestamp +from pandas.compat import lrange from pandas.tests.frame.common import TestData +import pandas.util.testing as tm +from pandas.util.testing import (assertRaisesRegexp, + assert_frame_equal, + assert_series_equal) + class TestDataFrameConcatCommon(tm.TestCase, TestData): @@ -324,6 +324,29 @@ def test_join_multiindex_leftright(self): assert_frame_equal(df2.join(df1, how='left'), exp[['value2', 'value1']]) + def test_concat_named_keys(self): + # GH 14252 + df = pd.DataFrame({'foo': [1, 2], 'bar': [0.1, 0.2]}) + index = Index(['a', 'b'], name='baz') + concatted_named_from_keys = pd.concat([df, df], keys=index) + expected_named = pd.DataFrame( + {'foo': [1, 2, 1, 2], 'bar': [0.1, 0.2, 0.1, 0.2]}, + index=pd.MultiIndex.from_product((['a', 'b'], [0, 1]), + names=['baz', None])) + assert_frame_equal(concatted_named_from_keys, expected_named) + + index_no_name = Index(['a', 'b'], name=None) + concatted_named_from_names = pd.concat( + [df, df], keys=index_no_name, names=['baz']) + assert_frame_equal(concatted_named_from_names, expected_named) + + concatted_unnamed = pd.concat([df, df], keys=index_no_name) + expected_unnamed = pd.DataFrame( + {'foo': [1, 2, 1, 2], 'bar': [0.1, 0.2, 0.1, 0.2]}, + index=pd.MultiIndex.from_product((['a', 'b'], [0, 1]), + names=[None, None])) + assert_frame_equal(concatted_unnamed, expected_unnamed) + class TestDataFrameCombineFirst(tm.TestCase, TestData): diff --git a/pandas/tools/merge.py b/pandas/tools/merge.py index 8cdde8d92b28f..dc8b1feef51cc 100644 --- a/pandas/tools/merge.py +++ b/pandas/tools/merge.py @@ -1369,7 +1369,9 @@ def __init__(self, objs, axis=0, join='outer', join_axes=None, clean_keys.append(k) clean_objs.append(v) objs = clean_objs - keys = clean_keys + name = getattr(keys, 'name', None) + keys = Index(clean_keys) + keys.name = name if len(objs) == 0: raise ValueError('All objects passed were None') @@ -1454,7 +1456,7 @@ def __init__(self, objs, axis=0, join='outer', join_axes=None, self.axis = axis self.join_axes = join_axes self.keys = keys - self.names = names + self.names = names or getattr(keys, 'names', None) self.levels = levels self.ignore_index = ignore_index