From 1fa5b87a39a35fe46885a9211b01dd3f47ecbd03 Mon Sep 17 00:00:00 2001 From: jreback Date: Wed, 22 Jan 2014 20:14:38 -0500 Subject: [PATCH] BUG: Bug in setting using fancy indexing a single element with a non-scalar (e.g. a list), (GH6043) --- doc/source/release.rst | 2 ++ pandas/core/internals.py | 10 ++++++++- pandas/tests/test_indexing.py | 42 +++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index 77ce69c40bb9b..151402a8b5370 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -135,6 +135,8 @@ Bug Fixes - Bug in Series construction of mixed type with datelike and an integer (which should result in object type and not automatic conversion) (:issue:`6028`) - Possible segfault when chained indexing with an object array under numpy 1.7.1 (:issue:`6016`) + - Bug in setting using fancy indexing a single element with a non-scalar (e.g. a list), + (:issue:`6043`) pandas 0.13.0 ------------- diff --git a/pandas/core/internals.py b/pandas/core/internals.py index f73440be61600..dacab4fd6e6c6 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -605,10 +605,18 @@ def setitem(self, indexer, value): "different length than the value") try: + # setting a single element for each dim and with a rhs that could be say a list + # GH 6043 + if arr_value.ndim == 1 and ( + np.isscalar(indexer) or (isinstance(indexer, tuple) and all([ np.isscalar(idx) for idx in indexer ]))): + values[indexer] = value + # if we are an exact match (ex-broadcasting), # then use the resultant dtype - if len(arr_value.shape) and arr_value.shape[0] == values.shape[0] and np.prod(arr_value.shape) == np.prod(values.shape): + elif len(arr_value.shape) and arr_value.shape[0] == values.shape[0] and np.prod(arr_value.shape) == np.prod(values.shape): values = arr_value.reshape(values.shape) + + # set else: values[indexer] = value diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index b763b885fe7b8..f80b0d36445cf 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -1286,6 +1286,48 @@ def test_ix_get_set_consistency(self): self.assert_(df.ix['e', 8] == 45) self.assert_(df.loc['e', 8] == 45) + def test_setitem_list(self): + + # GH 6043 + # ix with a list + df = DataFrame(index=[0,1], columns=[0]) + df.ix[1,0] = [1,2,3] + df.ix[1,0] = [1,2] + + result = DataFrame(index=[0,1], columns=[0]) + result.ix[1,0] = [1,2] + + assert_frame_equal(result,df) + + # ix with an object + class TO(object): + def __init__(self, value): + self.value = value + def __str__(self): + return "[{0}]".format(self.value) + __repr__ = __str__ + def __eq__(self, other): + return self.value == other.value + def view(self): + return self + + df = DataFrame(index=[0,1], columns=[0]) + df.ix[1,0] = TO(1) + df.ix[1,0] = TO(2) + + result = DataFrame(index=[0,1], columns=[0]) + result.ix[1,0] = TO(2) + + assert_frame_equal(result,df) + + # remains object dtype even after setting it back + df = DataFrame(index=[0,1], columns=[0]) + df.ix[1,0] = TO(1) + df.ix[1,0] = np.nan + result = DataFrame(index=[0,1], columns=[0]) + + assert_frame_equal(result, df) + def test_iloc_mask(self): # GH 3631, iloc with a mask (of a series) should raise