Skip to content

Commit 08f0609

Browse files
committed
Merge pull request #5704 from jreback/loc_astype
BUG: loc assignment with astype buggy, (GH5702)
2 parents ceec8bf + 4bc7843 commit 08f0609

File tree

3 files changed

+41
-16
lines changed

3 files changed

+41
-16
lines changed

doc/source/release.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -636,8 +636,8 @@ Bug Fixes
636636
(causing the original stack trace to be truncated).
637637
- Fix selection with ``ix/loc`` and non_unique selectors (:issue:`4619`)
638638
- Fix assignment with iloc/loc involving a dtype change in an existing column
639-
(:issue:`4312`) have internal setitem_with_indexer in core/indexing to use
640-
Block.setitem
639+
(:issue:`4312`, :issue:`5702`) have internal setitem_with_indexer in core/indexing
640+
to use Block.setitem
641641
- Fixed bug where thousands operator was not handled correctly for floating
642642
point numbers in csv_import (:issue:`4322`)
643643
- Fix an issue with CacheableOffset not properly being used by many

pandas/core/internals.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -601,8 +601,12 @@ def setitem(self, indexer, value):
601601
"different length than the value")
602602

603603
try:
604-
# set and return a block
605-
values[indexer] = value
604+
# if we are an exact match (ex-broadcasting),
605+
# then use the resultant dtype
606+
if len(arr_value.shape) and arr_value.shape[0] == values.shape[0] and np.prod(arr_value.shape) == np.prod(values.shape):
607+
values = arr_value.reshape(values.shape)
608+
else:
609+
values[indexer] = value
606610

607611
# coerce and try to infer the dtypes of the result
608612
if np.isscalar(value):

pandas/tests/test_indexing.py

+33-12
Original file line numberDiff line numberDiff line change
@@ -1376,21 +1376,42 @@ def gen_expected(df,mask):
13761376
expected = gen_expected(df,mask)
13771377
assert_frame_equal(result,expected)
13781378

1379-
def test_astype_assignment_with_iloc(self):
1379+
def test_astype_assignment(self):
13801380

1381-
# GH4312
1381+
# GH4312 (iloc)
13821382
df_orig = DataFrame([['1','2','3','.4',5,6.,'foo']],columns=list('ABCDEFG'))
13831383

13841384
df = df_orig.copy()
1385-
df.iloc[:,0:3] = df.iloc[:,0:3].astype(int)
1386-
result = df.get_dtype_counts().sort_index()
1387-
expected = Series({ 'int64' : 4, 'float64' : 1, 'object' : 2 }).sort_index()
1388-
assert_series_equal(result,expected)
1385+
df.iloc[:,0:2] = df.iloc[:,0:2].astype(int)
1386+
expected = DataFrame([[1,2,'3','.4',5,6.,'foo']],columns=list('ABCDEFG'))
1387+
assert_frame_equal(df,expected)
13891388

13901389
df = df_orig.copy()
1391-
df.iloc[:,0:3] = df.iloc[:,0:3].convert_objects(convert_numeric=True)
1392-
result = df.get_dtype_counts().sort_index()
1393-
expected = Series({ 'int64' : 4, 'float64' : 1, 'object' : 2 }).sort_index()
1390+
df.iloc[:,0:2] = df.iloc[:,0:2].convert_objects(convert_numeric=True)
1391+
expected = DataFrame([[1,2,'3','.4',5,6.,'foo']],columns=list('ABCDEFG'))
1392+
assert_frame_equal(df,expected)
1393+
1394+
# GH5702 (loc)
1395+
df = df_orig.copy()
1396+
df.loc[:,'A'] = df.loc[:,'A'].astype(int)
1397+
expected = DataFrame([[1,'2','3','.4',5,6.,'foo']],columns=list('ABCDEFG'))
1398+
assert_frame_equal(df,expected)
1399+
1400+
df = df_orig.copy()
1401+
df.loc[:,['B','C']] = df.loc[:,['B','C']].astype(int)
1402+
expected = DataFrame([['1',2,3,'.4',5,6.,'foo']],columns=list('ABCDEFG'))
1403+
assert_frame_equal(df,expected)
1404+
1405+
# full replacements / no nans
1406+
df = DataFrame({'A': [1., 2., 3., 4.]})
1407+
df.iloc[:, 0] = df['A'].astype(np.int64)
1408+
expected = DataFrame({'A': [1, 2, 3, 4]})
1409+
assert_frame_equal(df,expected)
1410+
1411+
df = DataFrame({'A': [1., 2., 3., 4.]})
1412+
df.loc[:, 'A'] = df['A'].astype(np.int64)
1413+
expected = DataFrame({'A': [1, 2, 3, 4]})
1414+
assert_frame_equal(df,expected)
13941415

13951416
def test_astype_assignment_with_dups(self):
13961417

@@ -1496,22 +1517,22 @@ def f():
14961517
assert_frame_equal(df,expected)
14971518

14981519
# mixed dtype frame, overwrite
1499-
expected = DataFrame(dict({ 'A' : [0,2,4], 'B' : Series([0.,2.,4.]) }))
1520+
expected = DataFrame(dict({ 'A' : [0,2,4], 'B' : Series([0,2,4]) }))
15001521
df = df_orig.copy()
15011522
df['B'] = df['B'].astype(np.float64)
15021523
df.ix[:,'B'] = df.ix[:,'A']
15031524
assert_frame_equal(df,expected)
15041525

15051526
# single dtype frame, partial setting
15061527
expected = df_orig.copy()
1507-
expected['C'] = df['A'].astype(np.float64)
1528+
expected['C'] = df['A']
15081529
df = df_orig.copy()
15091530
df.ix[:,'C'] = df.ix[:,'A']
15101531
assert_frame_equal(df,expected)
15111532

15121533
# mixed frame, partial setting
15131534
expected = df_orig.copy()
1514-
expected['C'] = df['A'].astype(np.float64)
1535+
expected['C'] = df['A']
15151536
df = df_orig.copy()
15161537
df.ix[:,'C'] = df.ix[:,'A']
15171538
assert_frame_equal(df,expected)

0 commit comments

Comments
 (0)