Repository: pandas-dev/pandas

Issue:
concat with ExtensionArray and object upcasting fails
```python
In [1]: import pandas as pd

In [2]: from pandas.tests.extension.decimal.array import *

In [3]: result = pd.concat([pd.Series(DecimalArray([decimal.Decimal(1)])), pd.Series([1])])

In [4]: result.shape
Out[4]: (2, 1)
```

and the repr fails, since things are messed up.


Discussion:
This can be fixed after the RC if things are tricky.
I think the fix is:

```patch
diff --git a/pandas/core/dtypes/concat.py b/pandas/core/dtypes/concat.py
index 377ef7a..cf54212 100644
--- a/pandas/core/dtypes/concat.py
+++ b/pandas/core/dtypes/concat.py
@@ -176,7 +176,8 @@ def _concat_compat(to_concat, axis=0):
 
     extensions = [is_extension_array_dtype(x) for x in to_concat]
     if any(extensions):
-        to_concat = [np.atleast_2d(x.astype('object')) for x in to_concat]
+        if axis == 1:
+            to_concat = [np.atleast_2d(x.astype('object')) for x in to_concat]
 
```

can do a PR tomorrow morning

Resolving patch:
diff --git a/pandas/core/dtypes/concat.py b/pandas/core/dtypes/concat.py
--- a/pandas/core/dtypes/concat.py
+++ b/pandas/core/dtypes/concat.py
@@ -175,7 +175,7 @@ def is_nonempty(x):
         return _concat_sparse(to_concat, axis=axis, typs=typs)
 
     extensions = [is_extension_array_dtype(x) for x in to_concat]
-    if any(extensions):
+    if any(extensions) and axis == 1:
         to_concat = [np.atleast_2d(x.astype('object')) for x in to_concat]
 
     if not nonempty:


Test patch:
diff --git a/pandas/tests/extension/base/reshaping.py b/pandas/tests/extension/base/reshaping.py
--- a/pandas/tests/extension/base/reshaping.py
+++ b/pandas/tests/extension/base/reshaping.py
@@ -64,6 +64,31 @@ def test_concat_mixed_dtypes(self, data):
         expected = pd.concat([df1.astype('object'), df2.astype('object')])
         self.assert_frame_equal(result, expected)
 
+        result = pd.concat([df1['A'], df2['A']])
+        expected = pd.concat([df1['A'].astype('object'),
+                              df2['A'].astype('object')])
+        self.assert_series_equal(result, expected)
+
+    def test_concat_columns(self, data, na_value):
+        df1 = pd.DataFrame({'A': data[:3]})
+        df2 = pd.DataFrame({'B': [1, 2, 3]})
+
+        expected = pd.DataFrame({'A': data[:3], 'B': [1, 2, 3]})
+        result = pd.concat([df1, df2], axis=1)
+        self.assert_frame_equal(result, expected)
+        result = pd.concat([df1['A'], df2['B']], axis=1)
+        self.assert_frame_equal(result, expected)
+
+        # non-aligned
+        df2 = pd.DataFrame({'B': [1, 2, 3]}, index=[1, 2, 3])
+        expected = pd.DataFrame({
+            'A': data._from_sequence(list(data[:3]) + [na_value]),
+            'B': [np.nan, 1, 2, 3]})
+        result = pd.concat([df1, df2], axis=1)
+        self.assert_frame_equal(result, expected)
+        result = pd.concat([df1['A'], df2['B']], axis=1)
+        self.assert_frame_equal(result, expected)
+
     def test_align(self, data, na_value):
         a = data[:3]
         b = data[2:5]
diff --git a/pandas/tests/extension/category/test_categorical.py b/pandas/tests/extension/category/test_categorical.py
--- a/pandas/tests/extension/category/test_categorical.py
+++ b/pandas/tests/extension/category/test_categorical.py
@@ -67,6 +67,10 @@ class TestConstructors(base.BaseConstructorsTests):
 
 
 class TestReshaping(base.BaseReshapingTests):
+    @pytest.mark.skip(reason="Unobserved categories preseved in concat.")
+    def test_concat_columns(self, data, na_value):
+        pass
+
     @pytest.mark.skip(reason="Unobserved categories preseved in concat.")
     def test_align(self, data, na_value):
         pass