diff --git a/doc/source/release.rst b/doc/source/release.rst index 7e11a0b036a6c..32921cb5f955b 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -165,6 +165,8 @@ Bug Fixes - Bug in ``DataFrame.apply`` when using mixed datelike reductions (:issue:`6125`) - Bug in ``DataFrame.append`` when appending a row with different columns (:issue:`6129`) - Bug in DataFrame construction with recarray and non-ns datetime dtype (:issue:`6140`) + - Bug in ``.loc`` setitem indexing with a datafrme on rhs, multiple item setting, and + a datetimelike (:issue:`6152`) pandas 0.13.0 ------------- diff --git a/pandas/core/common.py b/pandas/core/common.py index 5b82f6e140b6b..134e43bcd006a 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -275,6 +275,10 @@ def notnull(obj): return not res return -res +def _is_null_datelike_scalar(other): + """ test whether the object is a null datelike, e.g. Nat + but guard against passing a non-scalar """ + return (np.isscalar(other) and (isnull(other) or other == tslib.iNaT)) or other is pd.NaT or other is None def array_equivalent(left, right): """ diff --git a/pandas/core/internals.py b/pandas/core/internals.py index c97b9b28de18f..fdff3ab99df22 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -10,7 +10,7 @@ from pandas.core.common import (_possibly_downcast_to_dtype, isnull, notnull, _NS_DTYPE, _TD_DTYPE, ABCSeries, is_list_like, ABCSparseSeries, _infer_dtype_from_scalar, - _values_from_object) + _values_from_object, _is_null_datelike_scalar) from pandas.core.index import (Index, MultiIndex, _ensure_index, _handle_legacy_indexes) from pandas.core.indexing import (_check_slice_bounds, _maybe_convert_indices, @@ -1275,7 +1275,7 @@ def masker(v): values = masker(values) - if isnull(other) or (np.isscalar(other) and other == tslib.iNaT): + if _is_null_datelike_scalar(other): other = np.nan elif isinstance(other, np.timedelta64): other = _coerce_scalar_to_timedelta_type(other, unit='s').item() @@ -1586,7 +1586,7 @@ def _try_coerce_args(self, values, other): we are going to compare vs i8, so coerce to integer values is always ndarra like, other may not be """ values = values.view('i8') - if isnull(other) or (np.isscalar(other) and other == tslib.iNaT): + if _is_null_datelike_scalar(other): other = tslib.iNaT elif isinstance(other, datetime): other = lib.Timestamp(other).asm8.view('i8') diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index d448eb42ff153..83e36d9da3830 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -646,6 +646,27 @@ def test_loc_setitem_frame(self): result = df.ix[:,1:] assert_frame_equal(result, expected) + def test_loc_setitem_frame_multiples(self): + + # multiple setting + df = DataFrame({ 'A' : ['foo','bar','baz'], + 'B' : range(3) }) + df.loc[0:1] = df.loc[1:2] + expected = DataFrame({ 'A' : ['bar','baz','baz'], + 'B' : [1,2,2] }) + assert_frame_equal(df, expected) + + + # multiple setting with frame on rhs (with M8) + df = DataFrame({ 'date' : date_range('2000-01-01','2000-01-5'), + 'val' : range(5) }) + expected = DataFrame({ 'date' : [Timestamp('20000101'),Timestamp('20000102'),Timestamp('20000101'), + Timestamp('20000102'),Timestamp('20000103')], + 'val' : [0,1,0,1,2] }) + + df.loc[2:4] = df.loc[0:2] + assert_frame_equal(df, expected) + def test_iloc_getitem_frame(self): df = DataFrame(np.random.randn(10, 4), index=lrange(0, 20, 2), columns=lrange(0,8,2))