Repository: pandas-dev/pandas
Pull request: BUG: Should not raise error in concatenating Series with numpy scalar and tuple names (GH21015)
- [x] closes #21015 
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry


Problem statement:
BUG: error in concatting Series with numpy scalar / tuple names
```
In [2]: s1 = pd.Series({'a': 1.5}, name=np.int64(190))

In [3]: s2 = pd.Series([], name=(43, 0))

In [4]: pd.concat([s1, s2])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-5f754290d56c> in <module>()
----> 1 pd.concat([s1, s2])

~/scipy/pandas/pandas/core/reshape/concat.py in concat(objs, axis, join, join_axes, ignore_index, keys, levels, names, verify_integrity, sort, copy)
    224                        verify_integrity=verify_integrity,
    225                        copy=copy, sort=sort)
--> 226     return op.get_result()
    227 
    228 

~/scipy/pandas/pandas/core/reshape/concat.py in get_result(self)
    385             # stack blocks
    386             if self.axis == 0:
--> 387                 name = com._consensus_name_attr(self.objs)
    388 
    389                 mgr = self.objs[0]._data.concat([x._data for x in self.objs],

~/scipy/pandas/pandas/core/common.py in _consensus_name_attr(objs)
     56     name = objs[0].name
     57     for obj in objs[1:]:
---> 58         if obj.name != name:
     59             return None
     60     return name

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
```

It looks maybe a bit of a strange corner case, but you can get both cases rather easily (the one from selecting from Int64Index axis (not default RangeIndex), the other from MultiIndex axis), for example:

```
In [15]: df1 = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'], index=[0, 1])

In [16]: df2 = pd.DataFrame([[5, 6], [7, 8]], columns=['c', 'd'], index=pd.MultiIndex.from_tuples([(0, 0), (1, 1)]))

In [17]: pd.concat([df1.iloc[0], df2.iloc[0]])
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
```

The reason for the error is that if you compare a tuple and a numpy scalar, it gives an array as result:

```
In [18]: (0, 0) == np.int64(0)
Out[18]: array([ True,  True], dtype=bool)
```

Hints from issue discussion:

Commit message: GH21015

Changed to negative test for bool or np.bool_

Patch to review:
diff --git a/pandas/core/common.py b/pandas/core/common.py
index b9182bfd2cbe2..473b2f5874846 100644
--- a/pandas/core/common.py
+++ b/pandas/core/common.py
@@ -55,7 +55,11 @@ def flatten(l):
 def _consensus_name_attr(objs):
     name = objs[0].name
     for obj in objs[1:]:
-        if obj.name != name:
+        name_check = (obj.name != name)
+        if not isinstance(name_check, (bool, np.bool_)):
+            # 'If' test can also be a positive for 'np.ndarray'
+            return None
+        elif name_check:
             return None
     return name
 
diff --git a/pandas/tests/reshape/test_concat.py b/pandas/tests/reshape/test_concat.py
index f5e58fa70e1c4..f577b67476298 100644
--- a/pandas/tests/reshape/test_concat.py
+++ b/pandas/tests/reshape/test_concat.py
@@ -2350,6 +2350,21 @@ def test_concat_datetime_timezone(self):
 
         tm.assert_frame_equal(result, expected)
 
+    def test_concat_series_name_npscalar_tuple(self):
+        # GH21015
+        s1 = pd.Series({'a': 1.5}, name=np.int64(190))
+        s2 = pd.Series([], name=(43, 0))
+        result = pd.concat([s1, s2])
+        expected = pd.Series({'a': 1.5})
+        tm.assert_series_equal(result, expected)
+
+        df1 = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'], index=[0, 1])
+        df2 = pd.DataFrame([[5, 6], [7, 8]], columns=['c', 'd'],
+                           index=pd.MultiIndex.from_tuples([(0, 0), (1, 1)]))
+        result = pd.concat([df1.iloc[0], df2.iloc[0]])
+        expected = pd.Series({'a': 1, 'b': 2, 'c': 5, 'd': 6})
+        tm.assert_series_equal(result, expected)
+
 
 @pytest.mark.parametrize('pdt', [pd.Series, pd.DataFrame, pd.Panel])
 @pytest.mark.parametrize('dt', np.sctypes['float'])


Code review comments:
diff_hunk: @@ -55,7 +55,11 @@ def flatten(l):
 def _consensus_name_attr(objs):
     name = objs[0].name
     for obj in objs[1:]:
-        if obj.name != name:
+        name_check = (obj.name != name)
+        if not isinstance(name_check, (bool, np.bool_)):
path: pandas/core/common.py
text: @user1:
Can you use a try...except block here to catch the ValueError instead of type introspection?

@author:
@user1 thanks - will make the changes. Should I add whatsnew note to v0.23.1?

@user1:
Yes that works

@author:
Done