diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index a3499f857d158..96cb64e1ffb0e 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -726,6 +726,7 @@ Indexing - Bug in :meth:`DataFrame.iloc.__setitem__` creating a new array instead of overwriting ``Categorical`` values in-place (:issue:`32831`) - Bug in :class:`Interval` where a :class:`Timedelta` could not be added or subtracted from a :class:`Timestamp` interval (:issue:`32023`) - Bug in :meth:`DataFrame.copy` _item_cache not invalidated after copy causes post-copy value updates to not be reflected (:issue:`31784`) +- Fixed regression in :meth:`DataFrame.loc` and :meth:`Series.loc` throwing an error when a ``datetime64[ns, tz]`` value is provided (:issue:`32395`) - Bug in `Series.__getitem__` with an integer key and a :class:`MultiIndex` with leading integer level failing to raise ``KeyError`` if the key is not present in the first level (:issue:`33355`) - Bug in :meth:`DataFrame.iloc` when slicing a single column-:class:`DataFrame`` with ``ExtensionDtype`` (e.g. ``df.iloc[:, :1]``) returning an invalid result (:issue:`32957`) - Bug in :meth:`DatetimeIndex.insert` and :meth:`TimedeltaIndex.insert` causing index ``freq`` to be lost when setting an element into an empty :class:`Series` (:issue:33573`) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index c052c6c9d7d1d..d880bd81bd947 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -824,8 +824,10 @@ def setitem(self, indexer, value): if is_extension_array_dtype(getattr(value, "dtype", None)): # We need to be careful not to allow through strings that # can be parsed to EADtypes + is_ea_value = True arr_value = value else: + is_ea_value = False arr_value = np.array(value) if transpose: @@ -853,6 +855,11 @@ def setitem(self, indexer, value): values[indexer] = value return self.make_block(Categorical(self.values, dtype=arr_value.dtype)) + elif exact_match and is_ea_value: + # GH#32395 if we're going to replace the values entirely, just + # substitute in the new array + return self.make_block(arr_value) + # if we are an exact match (ex-broadcasting), # then use the resultant dtype elif exact_match: diff --git a/pandas/tests/extension/base/setitem.py b/pandas/tests/extension/base/setitem.py index dece8098c8542..eed9a584cc030 100644 --- a/pandas/tests/extension/base/setitem.py +++ b/pandas/tests/extension/base/setitem.py @@ -301,3 +301,31 @@ def test_setitem_preserves_views(self, data): data[0] = data[1] assert view1[0] == data[1] assert view2[0] == data[1] + + def test_setitem_dataframe_column_with_index(self, data): + # https://github.com/pandas-dev/pandas/issues/32395 + df = expected = pd.DataFrame({"data": pd.Series(data)}) + result = pd.DataFrame(index=df.index) + result.loc[df.index, "data"] = df["data"] + self.assert_frame_equal(result, expected) + + def test_setitem_dataframe_column_without_index(self, data): + # https://github.com/pandas-dev/pandas/issues/32395 + df = expected = pd.DataFrame({"data": pd.Series(data)}) + result = pd.DataFrame(index=df.index) + result.loc[:, "data"] = df["data"] + self.assert_frame_equal(result, expected) + + def test_setitem_series_with_index(self, data): + # https://github.com/pandas-dev/pandas/issues/32395 + ser = expected = pd.Series(data, name="data") + result = pd.Series(index=ser.index, dtype=np.object, name="data") + result.loc[ser.index] = ser + self.assert_series_equal(result, expected) + + def test_setitem_series_without_index(self, data): + # https://github.com/pandas-dev/pandas/issues/32395 + ser = expected = pd.Series(data, name="data") + result = pd.Series(index=ser.index, dtype=np.object, name="data") + result.loc[:] = ser + self.assert_series_equal(result, expected)