diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 81d15de4f833a..65f76f7e295a6 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6876,8 +6876,10 @@ def fillna( "with dict/Series column " "by column" ) - - result = self if inplace else self.copy() + if using_copy_on_write(): + result = self.copy(deep=None) + else: + result = self if inplace else self.copy() is_dict = isinstance(downcast, dict) for k, v in value.items(): if k not in result: @@ -6931,8 +6933,10 @@ def fillna( result.iloc[:, loc] = res_loc else: result.isetitem(loc, res_loc) - - return result if not inplace else None + if inplace: + return self._update_inplace(result) + else: + return result elif not is_list_like(value): if axis == 1: diff --git a/pandas/tests/copy_view/test_interp_fillna.py b/pandas/tests/copy_view/test_interp_fillna.py index 930f6a42f1057..c3e1e5f39384b 100644 --- a/pandas/tests/copy_view/test_interp_fillna.py +++ b/pandas/tests/copy_view/test_interp_fillna.py @@ -180,6 +180,21 @@ def test_fillna(using_copy_on_write): tm.assert_frame_equal(df_orig, df) +def test_fillna_dict(using_copy_on_write): + df = DataFrame({"a": [1.5, np.nan], "b": 1}) + df_orig = df.copy() + + df2 = df.fillna({"a": 100.5}) + if using_copy_on_write: + assert np.shares_memory(get_array(df, "b"), get_array(df2, "b")) + assert not np.shares_memory(get_array(df, "a"), get_array(df2, "a")) + else: + assert not np.shares_memory(get_array(df, "b"), get_array(df2, "b")) + + df2.iloc[0, 1] = 100 + tm.assert_frame_equal(df_orig, df) + + @pytest.mark.parametrize("downcast", [None, False]) def test_fillna_inplace(using_copy_on_write, downcast): df = DataFrame({"a": [1.5, np.nan], "b": 1}) diff --git a/pandas/tests/extension/json/test_json.py b/pandas/tests/extension/json/test_json.py index 2e5e2fc77d6c4..d7b9874555046 100644 --- a/pandas/tests/extension/json/test_json.py +++ b/pandas/tests/extension/json/test_json.py @@ -301,6 +301,18 @@ def test_searchsorted(self, data_for_sorting): def test_equals(self, data, na_value, as_series): super().test_equals(data, na_value, as_series) + def test_fillna_copy_frame(self, data_missing, using_copy_on_write): + arr = data_missing.take([1, 1]) + df = pd.DataFrame({"A": arr}) + + filled_val = df.iloc[0, 0] + result = df.fillna(filled_val) + + if using_copy_on_write: + assert df.A.values is result.A.values + else: + assert df.A.values is not result.A.values + class TestCasting(BaseJSON, base.BaseCastingTests): @pytest.mark.xfail(reason="failing on np.array(self, dtype=str)")