diff --git a/doc/source/release.rst b/doc/source/release.rst index 1cb5bf39ba9a7..804ca6c465bdb 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -63,6 +63,8 @@ API Changes values. A single indexer that is out-of-bounds and drops the dimensions of the object will still raise ``IndexError`` (:issue:`6296`) - ``select_as_multiple`` will always raise a ``KeyError``, when a key or the selector is not found (:issue:`6177`) +- ``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 (:issue:`6149`) Experimental Features ~~~~~~~~~~~~~~~~~~~~~ diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index f8ce855e6bfdc..ea7214d4cd020 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -394,10 +394,18 @@ def setter(item, v): s = self.obj[item] pi = plane_indexer[0] if lplane_indexer == 1 else plane_indexer - # set the item, possibly having a dtype change - s = s.copy() - s._data = s._data.setitem(indexer=pi, value=v) - s._maybe_update_cacher(clear=True) + # perform the equivalent of a setitem on the info axis + # as we have a null slice which means essentially reassign to the columns + # of a multi-dim object + # GH6149 + if isinstance(pi, tuple) and all(_is_null_slice(idx) for idx in pi): + s = v + else: + # set the item, possibly having a dtype change + s = s.copy() + s._data = s._data.setitem(indexer=pi, value=v) + s._maybe_update_cacher(clear=True) + self.obj[item] = s def can_do_equal_len(): diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index b54e87f5d5696..8ffa5f8b1bba0 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -690,6 +690,52 @@ def test_loc_general(self): assert_series_equal(result,expected) self.assertEqual(result.dtype, object) + def test_loc_setitem_consistency(self): + + # GH 6149 + # coerce similary for setitem and loc when rows have a null-slice + expected = DataFrame({ 'date': Series(0,index=range(5),dtype=np.int64), + 'val' : Series(range(5),dtype=np.int64) }) + + df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'), + 'val' : Series(range(5),dtype=np.int64) }) + df.loc[:,'date'] = 0 + assert_frame_equal(df,expected) + + df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'), + 'val' : Series(range(5),dtype=np.int64) }) + df.loc[:,'date'] = np.array(0,dtype=np.int64) + assert_frame_equal(df,expected) + + df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'), + 'val' : Series(range(5),dtype=np.int64) }) + df.loc[:,'date'] = np.array([0,0,0,0,0],dtype=np.int64) + assert_frame_equal(df,expected) + + expected = DataFrame({ 'date': Series('foo',index=range(5)), + 'val' : Series(range(5),dtype=np.int64) }) + df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'), + 'val' : Series(range(5),dtype=np.int64) }) + df.loc[:,'date'] = 'foo' + assert_frame_equal(df,expected) + + expected = DataFrame({ 'date': Series(1.0,index=range(5)), + 'val' : Series(range(5),dtype=np.int64) }) + df = DataFrame({ 'date': date_range('2000-01-01','2000-01-5'), + 'val' : Series(range(5),dtype=np.int64) }) + df.loc[:,'date'] = 1.0 + assert_frame_equal(df,expected) + + # empty (essentially noops) + expected = DataFrame(columns=['x', 'y']) + df = DataFrame(columns=['x', 'y']) + df.loc[:, 'x'] = 1 + assert_frame_equal(df,expected) + + df = DataFrame(columns=['x', 'y']) + df['x'] = 1 + assert_frame_equal(df,expected) + def test_loc_setitem_frame(self): df = self.frame_labels