diff --git a/doc/source/release.rst b/doc/source/release.rst index 13e2d5a136c21..daee460fc50a1 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -136,6 +136,8 @@ Improvements to existing features - Both ExcelFile and read_excel to accept an xlrd.Book for the io (formerly path_or_buf) argument; this requires engine to be set. (:issue:`4961`). + - ``concat`` now gives a more informative error message when passed objects + that cannot be concatenated (:issue:`4608`). API Changes ~~~~~~~~~~~ diff --git a/pandas/tools/merge.py b/pandas/tools/merge.py index 5792161e0171e..ba60566a7fc55 100644 --- a/pandas/tools/merge.py +++ b/pandas/tools/merge.py @@ -1245,7 +1245,11 @@ def _get_comb_axis(self, i): if self._is_series: all_indexes = [x.index for x in self.objs] else: - all_indexes = [x._data.axes[i] for x in self.objs] + try: + all_indexes = [x._data.axes[i] for x in self.objs] + except IndexError: + types = [type(x).__name__ for x in self.objs] + raise TypeError("Cannot concatenate list of %s" % types) return _get_combined_index(all_indexes, intersect=self.intersect) @@ -1256,6 +1260,10 @@ def _get_concat_axis(self): elif self.keys is None: names = [] for x in self.objs: + if not isinstance(x, Series): + raise TypeError("Cannot concatenate type 'Series' " + "with object of type " + "%r" % type(x).__name__) if x.name is not None: names.append(x.name) else: diff --git a/pandas/tools/tests/test_merge.py b/pandas/tools/tests/test_merge.py index 203769e731022..d44564db4b830 100644 --- a/pandas/tools/tests/test_merge.py +++ b/pandas/tools/tests/test_merge.py @@ -1804,6 +1804,15 @@ def test_concat_invalid_first_argument(self): # generator ok though concat(DataFrame(np.random.rand(5,5)) for _ in range(3)) + def test_concat_mixed_types_fails(self): + df = DataFrame(randn(10, 1)) + + with tm.assertRaisesRegexp(TypeError, "Cannot concatenate.+"): + concat([df[0], df], axis=1) + + with tm.assertRaisesRegexp(TypeError, "Cannot concatenate.+"): + concat([df, df[0]], axis=1) + class TestOrderedMerge(unittest.TestCase): def setUp(self):