diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 75d2196fe0b1e..3cec48be9b7ef 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1365,6 +1365,7 @@ Strings - Bug in :meth:`Index.str.partition` was not nan-safe (:issue:`23558`). - Bug in :meth:`Index.str.split` was not nan-safe (:issue:`23677`). - Bug :func:`Series.str.contains` not respecting the ``na`` argument for a ``Categorical`` dtype ``Series`` (:issue:`22158`) +- Bug in :meth:`Index.str.cat` when the result contained only ``NaN`` (:issue:`24044`) Interval ^^^^^^^^ diff --git a/pandas/core/strings.py b/pandas/core/strings.py index 0b791f6f91aa3..995700e79cb50 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -2260,9 +2260,11 @@ def cat(self, others=None, sep=None, na_rep=None, join=None): result = cat_core(all_cols, sep) if isinstance(self._orig, Index): - result = Index(result, name=self._orig.name) + # add dtype for case that result is all-NA + result = Index(result, dtype=object, name=self._orig.name) else: # Series - result = Series(result, index=data.index, name=self._orig.name) + result = Series(result, dtype=object, index=data.index, + name=self._orig.name) return result _shared_docs['str_split'] = (""" diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index 117984ce89743..ced8d37678b8b 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -630,11 +630,31 @@ def test_str_cat_align_mixed_inputs(self, join): with pytest.raises(ValueError, match=rgx): s.str.cat([t, z], join=join) - def test_str_cat_raises(self): - # non-strings hiding behind object dtype - s = Series([1, 2, 3, 4], dtype='object') - with pytest.raises(TypeError, match="unsupported operand type.*"): - s.str.cat(s) + @pytest.mark.parametrize('box', [Series, Index]) + @pytest.mark.parametrize('other', [Series, Index]) + def test_str_cat_all_na(self, box, other): + # GH 24044 + + # check that all NaNs in caller / target work + s = Index(['a', 'b', 'c', 'd']) + s = s if box == Index else Series(s, index=s) + t = other([np.nan] * 4, dtype=object) + # add index of s for alignment + t = t if other == Index else Series(t, index=s) + + # all-NA target + if box == Series: + expected = Series([np.nan] * 4, index=s.index, dtype=object) + else: # box == Index + expected = Index([np.nan] * 4, dtype=object) + result = s.str.cat(t, join='left') + assert_series_or_index_equal(result, expected) + + # all-NA caller (only for Series) + if other == Series: + expected = Series([np.nan] * 4, dtype=object, index=t.index) + result = t.str.cat(s, join='left') + tm.assert_series_equal(result, expected) def test_str_cat_special_cases(self): s = Series(['a', 'b', 'c', 'd'])