Skip to content

Commit 90e067b

Browse files
committed
Merge pull request #10308 from behzadnouri/block-type-loss
BUG: bug in setitem where type promotion is applied to entire block
2 parents a8b5798 + 5c39467 commit 90e067b

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

doc/source/whatsnew/v0.16.2.txt

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ Bug Fixes
140140

141141
- Bug in getting timezone data with ``dateutil`` on various platforms ( :issue:`9059`, :issue:`8639`, :issue:`9663`, :issue:`10121`)
142142
- Bug in display datetimes with mixed frequencies uniformly; display 'ms' datetimes to the proper precision. (:issue:`10170`)
143+
- Bug in ``setitem`` where type pormotion is applied to entire block (:issue:`10280`)
143144

144145
- Bug in ``Series`` arithmetic methods may incorrectly hold names (:issue:`10068`)
145146

pandas/core/indexing.py

+9
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,15 @@ def _setitem_with_indexer(self, indexer, value):
204204

205205
# maybe partial set
206206
take_split_path = self.obj._is_mixed_type
207+
208+
# if there is only one block/type, still have to take split path
209+
# unless the block is one-dimensional or it can hold the value
210+
if not take_split_path and self.obj._data.blocks:
211+
blk, = self.obj._data.blocks
212+
if 1 < blk.ndim: # in case of dict, keys are indices
213+
val = list(value.values()) if isinstance(value,dict) else value
214+
take_split_path = not blk._can_hold_element(val)
215+
207216
if isinstance(indexer, tuple):
208217
nindexer = []
209218
for i, idx in enumerate(indexer):

pandas/tests/test_indexing.py

+25
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,31 @@ def test_setitem_dtype_upcast(self):
23302330
expected = DataFrame([{"a": 1, "c" : 'foo'}, {"a": 3, "b": 2, "c" : np.nan}])
23312331
assert_frame_equal(df,expected)
23322332

2333+
# GH10280
2334+
df = DataFrame(np.arange(6).reshape(2, 3), index=list('ab'),
2335+
columns=['foo', 'bar', 'baz'])
2336+
2337+
for val in [3.14, 'wxyz']:
2338+
left = df.copy()
2339+
left.loc['a', 'bar'] = val
2340+
right = DataFrame([[0, val, 2], [3, 4, 5]], index=list('ab'),
2341+
columns=['foo', 'bar', 'baz'])
2342+
2343+
assert_frame_equal(left, right)
2344+
self.assertTrue(com.is_integer_dtype(left['foo']))
2345+
self.assertTrue(com.is_integer_dtype(left['baz']))
2346+
2347+
left = DataFrame(np.arange(6).reshape(2, 3) / 10.0, index=list('ab'),
2348+
columns=['foo', 'bar', 'baz'])
2349+
left.loc['a', 'bar'] = 'wxyz'
2350+
2351+
right = DataFrame([[0, 'wxyz', .2], [.3, .4, .5]], index=list('ab'),
2352+
columns=['foo', 'bar', 'baz'])
2353+
2354+
assert_frame_equal(left, right)
2355+
self.assertTrue(com.is_float_dtype(left['foo']))
2356+
self.assertTrue(com.is_float_dtype(left['baz']))
2357+
23332358
def test_setitem_iloc(self):
23342359

23352360

0 commit comments

Comments
 (0)