Skip to content

Commit 67229f0

Browse files
committed
Merge pull request pandas-dev#4756 from jreback/nested
BUG/ER: (GH2702) Bug with Series indexing not raising an error when the right-hand-side has an incorrect length
2 parents 7577489 + caa3703 commit 67229f0

File tree

4 files changed

+106
-19
lines changed

4 files changed

+106
-19
lines changed

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ See :ref:`Internal Refactoring<whatsnew_0130.refactoring>`
321321
etc. (:issue:`4718`, :issue:`4628`)
322322
- Bug in using ``iloc/loc`` with a cross-sectional and duplicate indicies (:issue:`4726`)
323323
- Bug with using ``QUOTE_NONE`` with ``to_csv`` causing ``Exception``. (:issue:`4328`)
324+
- Bug with Series indexing not raising an error when the right-hand-side has an incorrect length (:issue:`2702`)
324325

325326
pandas 0.12
326327
===========

pandas/core/internals.py

+36-3
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,41 @@ def setitem(self, indexer, value):
547547
dtype, _ = com._maybe_promote(arr_value.dtype)
548548
values = values.astype(dtype)
549549

550+
transf = (lambda x: x.T) if self.ndim == 2 else (lambda x: x)
551+
values = transf(values)
552+
l = len(values)
553+
554+
# length checking
555+
# boolean with truth values == len of the value is ok too
556+
if isinstance(indexer, (np.ndarray, list)):
557+
if is_list_like(value) and len(indexer) != len(value):
558+
if not (isinstance(indexer, np.ndarray) and indexer.dtype == np.bool_ and len(indexer[indexer]) == len(value)):
559+
raise ValueError("cannot set using a list-like indexer with a different length than the value")
560+
561+
# slice
562+
elif isinstance(indexer, slice):
563+
564+
if is_list_like(value) and l:
565+
start = indexer.start
566+
stop = indexer.stop
567+
step = indexer.step
568+
if start is None:
569+
start = 0
570+
elif start < 0:
571+
start += l
572+
if stop is None or stop > l:
573+
stop = len(values)
574+
elif stop < 0:
575+
stop += l
576+
if step is None:
577+
step = 1
578+
elif step < 0:
579+
step = abs(step)
580+
if (stop-start) / step != len(value):
581+
raise ValueError("cannot set using a slice indexer with a different length than the value")
582+
550583
try:
551584
# set and return a block
552-
transf = (lambda x: x.T) if self.ndim == 2 else (lambda x: x)
553-
values = transf(values)
554585
values[indexer] = value
555586

556587
# coerce and try to infer the dtypes of the result
@@ -561,7 +592,9 @@ def setitem(self, indexer, value):
561592
values = self._try_coerce_result(values)
562593
values = self._try_cast_result(values, dtype)
563594
return [make_block(transf(values), self.items, self.ref_items, ndim=self.ndim, fastpath=True)]
564-
except:
595+
except (ValueError, TypeError) as detail:
596+
raise
597+
except (Exception) as detail:
565598
pass
566599

567600
return [ self ]

pandas/core/series.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1096,10 +1096,9 @@ def _set_labels(self, key, value):
10961096
self._set_values(indexer, value)
10971097

10981098
def _set_values(self, key, value):
1099-
values = self.values
11001099
if isinstance(key, Series):
11011100
key = key.values
1102-
values[key] = _index.convert_scalar(values, value)
1101+
self._data = self._data.setitem(key,value)
11031102

11041103
# help out SparseSeries
11051104
_get_val_at = ndarray.__getitem__

pandas/tests/test_series.py

+68-14
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,59 @@ def f():
12841284
expected = Series(np.nan,index=[9])
12851285
assert_series_equal(result, expected)
12861286

1287+
def test_where_setitem_invalid(self):
1288+
1289+
# GH 2702
1290+
# make sure correct exceptions are raised on invalid list assignment
1291+
1292+
# slice
1293+
s = Series(list('abc'))
1294+
def f():
1295+
s[0:3] = list(range(27))
1296+
self.assertRaises(ValueError, f)
1297+
1298+
s[0:3] = list(range(3))
1299+
expected = Series([0,1,2])
1300+
assert_series_equal(s, expected)
1301+
1302+
# slice with step
1303+
s = Series(list('abcdef'))
1304+
def f():
1305+
s[0:4:2] = list(range(27))
1306+
self.assertRaises(ValueError, f)
1307+
1308+
s = Series(list('abcdef'))
1309+
s[0:4:2] = list(range(2))
1310+
expected = Series([0,'b',1,'d','e','f'])
1311+
assert_series_equal(s, expected)
1312+
1313+
# neg slices
1314+
s = Series(list('abcdef'))
1315+
def f():
1316+
s[:-1] = list(range(27))
1317+
self.assertRaises(ValueError, f)
1318+
1319+
s[-3:-1] = list(range(2))
1320+
expected = Series(['a','b','c',0,1,'f'])
1321+
assert_series_equal(s, expected)
1322+
1323+
# list
1324+
s = Series(list('abc'))
1325+
def f():
1326+
s[[0,1,2]] = list(range(27))
1327+
self.assertRaises(ValueError, f)
1328+
1329+
s = Series(list('abc'))
1330+
def f():
1331+
s[[0,1,2]] = list(range(2))
1332+
self.assertRaises(ValueError, f)
1333+
1334+
# scalar
1335+
s = Series(list('abc'))
1336+
s[0] = list(range(10))
1337+
expected = Series([list(range(10)),'b','c'])
1338+
assert_series_equal(s, expected)
1339+
12871340
def test_where_broadcast(self):
12881341
# Test a variety of differently sized series
12891342
for size in range(2, 6):
@@ -2550,22 +2603,23 @@ def test_between(self):
25502603
expected = s[5:16].dropna()
25512604
assert_series_equal(result, expected)
25522605

2553-
def test_setitem_na_exception(self):
2554-
def testme1():
2555-
s = Series([2, 3, 4, 5, 6, 7, 8, 9, 10])
2556-
s[::2] = np.nan
2557-
2558-
def testme2():
2559-
s = Series([True, True, False, False])
2560-
s[::2] = np.nan
2606+
def test_setitem_na(self):
2607+
# these induce dtype changes
2608+
expected = Series([np.nan, 3, np.nan, 5, np.nan, 7, np.nan, 9, np.nan])
2609+
s = Series([2, 3, 4, 5, 6, 7, 8, 9, 10])
2610+
s[::2] = np.nan
2611+
assert_series_equal(s, expected)
25612612

2562-
def testme3():
2563-
s = Series(np.arange(10))
2564-
s[:5] = np.nan
2613+
# get's coerced to float, right?
2614+
expected = Series([np.nan, 1, np.nan, 0])
2615+
s = Series([True, True, False, False])
2616+
s[::2] = np.nan
2617+
assert_series_equal(s, expected)
25652618

2566-
self.assertRaises(Exception, testme1)
2567-
self.assertRaises(Exception, testme2)
2568-
self.assertRaises(Exception, testme3)
2619+
expected = Series([np.nan, np.nan, np.nan, np.nan, np.nan, 5, 6, 7, 8, 9])
2620+
s = Series(np.arange(10))
2621+
s[:5] = np.nan
2622+
assert_series_equal(s, expected)
25692623

25702624
def test_scalar_na_cmp_corners(self):
25712625
s = Series([2, 3, 4, 5, 6, 7, 8, 9, 10])

0 commit comments

Comments
 (0)