Skip to content

Commit b66015c

Browse files
committed
Fix edge case for NaN/None; adapted tests; fixes
1 parent 93f6042 commit b66015c

File tree

2 files changed

+20
-14
lines changed

2 files changed

+20
-14
lines changed

pandas/core/strings.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,7 +1957,7 @@ def _get_series_list(self, others, ignore_index=False):
19571957
# once str.cat defaults to alignment, this function can be simplified;
19581958
# will not need `ignore_index` and the second boolean output anymore
19591959

1960-
from pandas import Index, Series, DataFrame
1960+
from pandas import Index, Series, DataFrame, isnull
19611961

19621962
# self._orig is either Series or Index
19631963
idx = self._orig if isinstance(self._orig, Index) else self._orig.index
@@ -1994,15 +1994,19 @@ def _get_series_list(self, others, ignore_index=False):
19941994
fut_warn = False
19951995
while others:
19961996
nxt = others.pop(0)
1997-
# safety for iterators etc.; exclude indexed objects
1998-
if (is_list_like(nxt) and
1999-
not isinstance(nxt, (DataFrame, Series, Index))):
1997+
# safety for iterators etc.; nxt is list-like as per above
1998+
# do not map indexed objects, which would lose their index
1999+
if not isinstance(nxt, (DataFrame, Series, Index)):
20002000
nxt = list(nxt)
20012001

2002-
# nested list-likes are forbidden - content must be strings
2003-
is_legal = (is_list_like(nxt) and
2004-
all(isinstance(x, compat.string_types)
2005-
for x in nxt))
2002+
# Nested list-likes are forbidden - content of nxt must be
2003+
# strings/NaN/None. Need to robustify check against
2004+
# x in nxt being list-like (otherwise ambiguous boolean).
2005+
is_legal = all((isinstance(x, compat.string_types)
2006+
or (is_list_like(x) and any(isnull(x)))
2007+
or (not is_list_like(x) and isnull(x))
2008+
or x is None)
2009+
for x in nxt)
20062010
# DataFrame is false positive of is_legal
20072011
# because "x in df" returns column names
20082012
if isinstance(nxt, DataFrame) or not is_legal:
@@ -2012,11 +2016,11 @@ def _get_series_list(self, others, ignore_index=False):
20122016
los = los + tmp[0]
20132017
fut_warn = fut_warn or tmp[1]
20142018
return (los, fut_warn)
2015-
# test if there is a mix of list-like and string/NaN/None
2019+
# test if there is a mix of list-like and non-list-like (e.g. str)
20162020
elif (any(is_list_like(x) for x in others)
20172021
and any(not is_list_like(x) for x in others)):
20182022
raise TypeError(err_msg)
2019-
else:
2023+
else: # all elements in others are _not_ list-like
20202024
return ([Series(others, index=idx)], False)
20212025
raise TypeError(err_msg)
20222026

pandas/tests/test_strings.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,22 +351,24 @@ def test_str_cat_mixed_inputs(self, series_or_index):
351351

352352
# errors for incorrect arguments in list-like
353353
rgx = 'others must be Series, Index, DataFrame,.*'
354+
# make sure None/Nan also work as string-replacements
355+
u = Series(['a', np.nan, 'c', None])
354356

355357
# mix of string and Series
356358
with tm.assert_raises_regex(TypeError, rgx):
357-
s.str.cat([s, 's'])
359+
s.str.cat([u, 'u'])
358360

359361
# DataFrame in list
360362
with tm.assert_raises_regex(TypeError, rgx):
361-
s.str.cat([s, d])
363+
s.str.cat([u, d])
362364

363365
# 2-dim ndarray in list
364366
with tm.assert_raises_regex(TypeError, rgx):
365-
s.str.cat([s, d.values])
367+
s.str.cat([u, d.values])
366368

367369
# nested lists
368370
with tm.assert_raises_regex(TypeError, rgx):
369-
s.str.cat([s, [s, d]])
371+
s.str.cat([u, [u, d]])
370372

371373
# forbidden input type, e.g. int
372374
with tm.assert_raises_regex(TypeError, rgx):

0 commit comments

Comments
 (0)