Skip to content

Commit c5015c1

Browse files
committed
BUG: fix construction of Series from dict with nested lists
closes pandas-dev#18626
1 parent 6e56195 commit c5015c1

File tree

3 files changed

+25
-20
lines changed

3 files changed

+25
-20
lines changed

doc/source/whatsnew/v0.22.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ Other
246246

247247
- Improved error message when attempting to use a Python keyword as an identifier in a numexpr query (:issue:`18221`)
248248
- Fixed a bug where creating a Series from an array that contains both tz-naive and tz-aware values will result in a Series whose dtype is tz-aware instead of object (:issue:`16406`)
249+
- Fixed construction of a :class:`Series` from a ``dict`` containing nested lists as values (:issue:`18625`)
249250
- Fixed construction of a :class:`Series` from a ``dict`` containing ``NaN`` as key (:issue:`18480`)
250251
- Adding a ``Period`` object to a ``datetime`` or ``Timestamp`` object will now correctly raise a ``TypeError`` (:issue:`17983`)
251252
-

pandas/core/series.py

+13-20
Original file line numberDiff line numberDiff line change
@@ -3177,7 +3177,8 @@ def _try_cast(arr, take_fast_path):
31773177

31783178
# GH #846
31793179
if isinstance(data, (np.ndarray, Index, Series)):
3180-
3180+
if data.ndim > 1:
3181+
raise ValueError('Data must be 1-dimensional')
31813182
if dtype is not None:
31823183
subarr = np.array(data, copy=False)
31833184

@@ -3208,7 +3209,11 @@ def _try_cast(arr, take_fast_path):
32083209
return subarr
32093210

32103211
elif isinstance(data, (list, tuple)) and len(data) > 0:
3211-
if dtype is not None:
3212+
if all(is_list_like(item) for item in data):
3213+
# Ensure nested lists are not interpreted as further dimensions:
3214+
subarr = np.empty(len(data), dtype='object')
3215+
subarr[:] = data
3216+
elif dtype is not None:
32123217
try:
32133218
subarr = _try_cast(data, False)
32143219
except Exception:
@@ -3232,9 +3237,7 @@ def _try_cast(arr, take_fast_path):
32323237

32333238
# scalar like, GH
32343239
if getattr(subarr, 'ndim', 0) == 0:
3235-
if isinstance(data, list): # pragma: no cover
3236-
subarr = np.array(data, dtype=object)
3237-
elif index is not None:
3240+
if index is not None:
32383241
value = data
32393242

32403243
# figure out the dtype from the value (upcast if necessary)
@@ -3249,21 +3252,11 @@ def _try_cast(arr, take_fast_path):
32493252

32503253
else:
32513254
return subarr.item()
3252-
3253-
# the result that we want
3254-
elif subarr.ndim == 1:
3255-
if index is not None:
3256-
3257-
# a 1-element ndarray
3258-
if len(subarr) != len(index) and len(subarr) == 1:
3259-
subarr = construct_1d_arraylike_from_scalar(
3260-
subarr[0], len(index), subarr.dtype)
3261-
3262-
elif subarr.ndim > 1:
3263-
if isinstance(data, np.ndarray):
3264-
raise Exception('Data must be 1-dimensional')
3265-
else:
3266-
subarr = _asarray_tuplesafe(data, dtype=dtype)
3255+
elif index is not None:
3256+
# maybe_cast_to_datetime() transforms scalars in 1-element ndarrays
3257+
if len(subarr) != len(index) and len(subarr) == 1:
3258+
subarr = construct_1d_arraylike_from_scalar(
3259+
subarr[0], len(index), subarr.dtype)
32673260

32683261
# This is to prevent mixed-type Series getting all casted to
32693262
# NumPy string type, e.g. NaN --> '-1#IND'.

pandas/tests/series/test_constructors.py

+11
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,17 @@ def test_constructor_dict(self):
651651
expected.iloc[1] = 1
652652
assert_series_equal(result, expected)
653653

654+
@pytest.mark.parametrize('input_class', [list, tuple])
655+
@pytest.mark.parametrize('dtype', ['object', None])
656+
def test_constructor_dict_nested_lists(self, input_class, dtype):
657+
# GH 18625
658+
d = {'a': input_class([input_class([1, 2, 3]),
659+
input_class([4, 5, 6])]),
660+
'b': input_class([input_class([7, 8, 9])])}
661+
result = Series(d, index=['a', 'b'], dtype=dtype)
662+
expected = Series([d['a'], d['b']], index=['a', 'b'])
663+
assert_series_equal(result, expected)
664+
654665
@pytest.mark.parametrize("value", [2, np.nan, None, float('nan')])
655666
def test_constructor_dict_nan_key(self, value):
656667
# GH 18480

0 commit comments

Comments
 (0)