Skip to content

Commit 1ae03e0

Browse files
committed
BUG/API: df['col'] = value and df.loc[:,'col'] = value are now completely equivalent;
previously the .loc would not necessarily coerce the dtype of the resultant series (GH6149)
1 parent ab27073 commit 1ae03e0

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

doc/source/release.rst

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ API Changes
6363
values. A single indexer that is out-of-bounds and drops the dimensions of the object will still raise
6464
``IndexError`` (:issue:`6296`)
6565
- ``select_as_multiple`` will always raise a ``KeyError``, when a key or the selector is not found (:issue:`6177`)
66+
- ``df['col'] = value`` and ``df.loc[:,'col'] = value`` are now completely equivalent;
67+
previously the ``.loc`` would not necessarily coerce the dtype of the resultant series (:issue:`6149`)
6668

6769
Experimental Features
6870
~~~~~~~~~~~~~~~~~~~~~

pandas/core/indexing.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,18 @@ def setter(item, v):
394394
s = self.obj[item]
395395
pi = plane_indexer[0] if lplane_indexer == 1 else plane_indexer
396396

397-
# set the item, possibly having a dtype change
398-
s = s.copy()
399-
s._data = s._data.setitem(indexer=pi, value=v)
400-
s._maybe_update_cacher(clear=True)
397+
# perform the equivalent of a setitem on the info axis
398+
# as we have a null slice which means essentially reassign to the columns
399+
# of a multi-dim object
400+
# GH6149
401+
if isinstance(pi, tuple) and all(_is_null_slice(idx) for idx in pi):
402+
s = v
403+
else:
404+
# set the item, possibly having a dtype change
405+
s = s.copy()
406+
s._data = s._data.setitem(indexer=pi, value=v)
407+
s._maybe_update_cacher(clear=True)
408+
401409
self.obj[item] = s
402410

403411
def can_do_equal_len():

pandas/tests/test_indexing.py

+46
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,52 @@ def test_loc_general(self):
690690
assert_series_equal(result,expected)
691691
self.assertEqual(result.dtype, object)
692692

693+
def test_loc_setitem_consistency(self):
694+
695+
# GH 6149
696+
# coerce similary for setitem and loc when rows have a null-slice
697+
expected = DataFrame({ 'date': Series(0,index=range(5),dtype=np.int64),
698+
'val' : Series(range(5),dtype=np.int64) })
699+
700+
df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'),
701+
'val' : Series(range(5),dtype=np.int64) })
702+
df.loc[:,'date'] = 0
703+
assert_frame_equal(df,expected)
704+
705+
df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'),
706+
'val' : Series(range(5),dtype=np.int64) })
707+
df.loc[:,'date'] = np.array(0,dtype=np.int64)
708+
assert_frame_equal(df,expected)
709+
710+
df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'),
711+
'val' : Series(range(5),dtype=np.int64) })
712+
df.loc[:,'date'] = np.array([0,0,0,0,0],dtype=np.int64)
713+
assert_frame_equal(df,expected)
714+
715+
expected = DataFrame({ 'date': Series('foo',index=range(5)),
716+
'val' : Series(range(5),dtype=np.int64) })
717+
df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'),
718+
'val' : Series(range(5),dtype=np.int64) })
719+
df.loc[:,'date'] = 'foo'
720+
assert_frame_equal(df,expected)
721+
722+
expected = DataFrame({ 'date': Series(1.0,index=range(5)),
723+
'val' : Series(range(5),dtype=np.int64) })
724+
df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'),
725+
'val' : Series(range(5),dtype=np.int64) })
726+
df.loc[:,'date'] = 1.0
727+
assert_frame_equal(df,expected)
728+
729+
# empty (essentially noops)
730+
expected = DataFrame(columns=['x', 'y'])
731+
df = DataFrame(columns=['x', 'y'])
732+
df.loc[:, 'x'] = 1
733+
assert_frame_equal(df,expected)
734+
735+
df = DataFrame(columns=['x', 'y'])
736+
df['x'] = 1
737+
assert_frame_equal(df,expected)
738+
693739
def test_loc_setitem_frame(self):
694740
df = self.frame_labels
695741

0 commit comments

Comments
 (0)