diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 953ccedaa5222..7f0915dbbaee4 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -426,7 +426,10 @@ def fillna( """ inplace = validate_bool_kwarg(inplace, "inplace") - mask = isna(self.values) + isna_mask = isna(self.values) + value_mask = ~isna(value) + mask = isna_mask & value_mask + mask, noop = validate_putmask(self.values, mask) if limit is not None: diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index fdeda868fdb5e..00160636aea34 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -924,7 +924,10 @@ def _try_convert_data(self, name, data, use_dtypes=True, convert_dates=True): if not self.dtype: if all(notna(data)): return data, False - return data.fillna(np.nan), True + data = data.where(notna(data), np.nan) + if isna(data).all(): + data = data.astype(np.float64) + return data, True # error: Non-overlapping identity check (left operand type: # "Union[ExtensionDtype, str, dtype[Any], Type[object], diff --git a/pandas/tests/frame/methods/test_fillna.py b/pandas/tests/frame/methods/test_fillna.py index b1ce511fc3e4c..0d0f47d58461b 100644 --- a/pandas/tests/frame/methods/test_fillna.py +++ b/pandas/tests/frame/methods/test_fillna.py @@ -153,6 +153,28 @@ def test_fillna_tzaware_different_column(self): ) tm.assert_frame_equal(result, expected) + def test_other_missing_values_not_modified( + self, unique_nulls_fixture, unique_nulls_fixture2 + ): + # GH#40498 + df = DataFrame( + { + "A": [1, unique_nulls_fixture, unique_nulls_fixture2, "four"], + "B": [2, unique_nulls_fixture, unique_nulls_fixture2, "eight"], + } + ) + value = {"A": {1: 0}, "B": {2: 0}} + result = df.fillna(value) + + expected = DataFrame( + { + "A": [1, 0, unique_nulls_fixture2, "four"], + "B": [2, unique_nulls_fixture, 0, "eight"], + } + ) + + tm.assert_frame_equal(result, expected) + def test_na_actions_categorical(self): cat = Categorical([1, 2, 3, np.nan], categories=[1, 2, 3]) diff --git a/pandas/tests/series/methods/test_fillna.py b/pandas/tests/series/methods/test_fillna.py index 03e126587ce1a..53fcf47f47aa4 100644 --- a/pandas/tests/series/methods/test_fillna.py +++ b/pandas/tests/series/methods/test_fillna.py @@ -623,6 +623,19 @@ def test_fillna_numeric_inplace(self): expected = x.fillna(value=0) tm.assert_series_equal(y, expected) + def test_fillna_other_missing_values_not_modified( + self, unique_nulls_fixture, unique_nulls_fixture2 + ): + # GH#40498 + ser = Series([1, unique_nulls_fixture, unique_nulls_fixture2, "four"]) + + value = {2: 0} + result = ser.fillna(value) + + expected = Series([1, unique_nulls_fixture, 0, "four"]) + + tm.assert_series_equal(result, expected) + # --------------------------------------------------------------- # CategoricalDtype