diff --git a/doc/source/whatsnew/v0.15.1.txt b/doc/source/whatsnew/v0.15.1.txt index 04aec92f448c7..af312e3e22275 100644 --- a/doc/source/whatsnew/v0.15.1.txt +++ b/doc/source/whatsnew/v0.15.1.txt @@ -118,7 +118,8 @@ Bug Fixes -- Bug in numeric index operations of add/sub with Float/Index Index with numpy arrays (:issue:`8608`) +- Bug in numeric index operations of add/sub with Float/Index Index with numpy arrays (:issue:`8608` +- Bug in setitem with empty indexer and unwanted coercion of dtypes (:issue:`8669`) diff --git a/pandas/core/internals.py b/pandas/core/internals.py index 89e1cd6ce0fb6..6dd123996b125 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -549,10 +549,31 @@ def setitem(self, indexer, value): "different length than the value") try: + + def _is_scalar_indexer(indexer): + # treat a len 0 array like a scalar + # return True if we are all scalar indexers + + if arr_value.ndim == 1: + if not isinstance(indexer, tuple): + indexer = tuple([indexer]) + + def _is_ok(idx): + + if np.isscalar(idx): + return True + elif isinstance(idx, slice): + return False + return len(idx) == 0 + + return all([ _is_ok(idx) for idx in indexer ]) + return False + + # 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 ]))): + # or empty indexers (so no astyping) + # GH 6043, 8669 (empty) + if _is_scalar_indexer(indexer): values[indexer] = value # if we are an exact match (ex-broadcasting), diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index a2f3284efcb82..7bc5ca0bfb2e7 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -1043,6 +1043,13 @@ def test_loc_setitem_frame(self): expected = DataFrame(dict(A = Series(val1,index=keys1), B = Series(val2,index=keys2))).reindex(index=index) assert_frame_equal(df, expected) + # GH 8669 + # invalid coercion of nan -> int + df = DataFrame({'A' : [1,2,3], 'B' : np.nan }) + df.loc[df.B > df.A, 'B'] = df.A + expected = DataFrame({'A' : [1,2,3], 'B' : np.nan}) + assert_frame_equal(df, expected) + # GH 6546 # setting with mixed labels df = DataFrame({1:[1,2],2:[3,4],'a':['a','b']}) @@ -1055,7 +1062,6 @@ def test_loc_setitem_frame(self): df.loc[0,[1,2]] = [5,6] assert_frame_equal(df, expected) - def test_loc_setitem_frame_multiples(self): # multiple setting df = DataFrame({ 'A' : ['foo','bar','baz'],