From bc9a9422eef9283bc05369f587ab2ebb1b3cb12e Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 23 Jan 2025 19:14:23 +0900 Subject: [PATCH 01/23] BUG: Add fillna so that cond doesnt contain NA at the beginning of _where. (#60729) --- pandas/core/generic.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index e0a4f9d9c546a..6a13b74d7c2f6 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9674,6 +9674,12 @@ def _where( if axis is not None: axis = self._get_axis_number(axis) + # We should not be filling NA. See GH#60729 + if isinstance(cond, np.ndarray): + cond[np.isnan(cond)] = True + elif isinstance(cond, NDFrame): + cond = cond.fillna(True) + # align the cond to same shape as myself cond = common.apply_if_callable(cond, self) if isinstance(cond, NDFrame): From 558569f44245717b3c636117950782df324a7a96 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 23 Jan 2025 19:31:00 +0900 Subject: [PATCH 02/23] TST: Add tests for mask with NA. (#60729) --- pandas/tests/series/indexing/test_mask.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index 3c21cd0d5ca64..aeaf24ef3926b 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -67,3 +67,19 @@ def test_mask_inplace(): rs = s.copy() rs.mask(cond, -s, inplace=True) tm.assert_series_equal(rs, s.mask(cond, -s)) + + +def test_mask_na(): + # We should not be filling pd.NA. See GH#60729 + series = Series([None, 1, 2, None, 3, 4, None]) + series = series.convert_dtypes() + cond = series <= 2 + + maskres = series.mask(cond, -99) + whereres = series.where(~(cond), -99) + + expected = Series([None, -99, -99, None, 3, 4, None]) + expected = expected.convert_dtypes() + + tm.assert_series_equal(maskres, expected) + tm.assert_series_equal(maskres, whereres) From bbbc720c7fb4a6cfca974289bd386eb3e1c39e31 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 23 Jan 2025 19:58:56 +0900 Subject: [PATCH 03/23] BUG: Fix _where to make np.ndarray mutable. (#60729) --- pandas/core/generic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 6a13b74d7c2f6..61cbabf3198c8 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9676,6 +9676,7 @@ def _where( # We should not be filling NA. See GH#60729 if isinstance(cond, np.ndarray): + cond = np.array(cond) cond[np.isnan(cond)] = True elif isinstance(cond, NDFrame): cond = cond.fillna(True) From e2f32cb51e49ad2e4f0d87af59ae755c9c78719d Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 23 Jan 2025 20:14:25 +0900 Subject: [PATCH 04/23] DOC: Add documentation regarding the bug (#60729) --- doc/source/whatsnew/v3.0.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 1d8d0f6a74cb1..5e0281f59984b 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -676,6 +676,7 @@ Interval Indexing ^^^^^^^^ +- Bug in :func:`Series.mask` unexpectedly filling pd.NA (:issue:`60729`) - Bug in :meth:`DataFrame.__getitem__` returning modified columns when called with ``slice`` in Python 3.12 (:issue:`57500`) - Bug in :meth:`DataFrame.from_records` throwing a ``ValueError`` when passed an empty list in ``index`` (:issue:`58594`) - Bug in :meth:`MultiIndex.insert` when a new value inserted to a datetime-like level gets cast to ``NaT`` and fails indexing (:issue:`60388`) From d2d5f62c120739a4b1c55fdb7bb3351d45d42337 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Sat, 25 Jan 2025 17:10:57 +0900 Subject: [PATCH 05/23] ENH: Optimze test_mask_na() Co-authored-by: WillAyd --- pandas/tests/series/indexing/test_mask.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index aeaf24ef3926b..3f2dcb8239099 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -1,7 +1,10 @@ import numpy as np import pytest -from pandas import Series +from pandas import ( + Int64Dtype, + Series, +) import pandas._testing as tm @@ -71,15 +74,8 @@ def test_mask_inplace(): def test_mask_na(): # We should not be filling pd.NA. See GH#60729 - series = Series([None, 1, 2, None, 3, 4, None]) - series = series.convert_dtypes() - cond = series <= 2 + series = Series([None, 1, 2, None, 3, 4, None], dtype=Int64Dtype()) + result = series.mask(series <= 2, -99) + expected = Series([None, 1, 2, None, -99, -99, None], dtype=Int64Dtype()) - maskres = series.mask(cond, -99) - whereres = series.where(~(cond), -99) - - expected = Series([None, -99, -99, None, 3, 4, None]) - expected = expected.convert_dtypes() - - tm.assert_series_equal(maskres, expected) - tm.assert_series_equal(maskres, whereres) + tm.assert_series_equal(result, expected) From 475f2d15ea61aaf7789785b764186944dbf16a9b Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Sat, 25 Jan 2025 18:24:13 +0900 Subject: [PATCH 06/23] BUG: Fix a bug in test_mask_na() (#60729) --- pandas/tests/series/indexing/test_mask.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index 3f2dcb8239099..de1a3ff5b64e1 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -76,6 +76,6 @@ def test_mask_na(): # We should not be filling pd.NA. See GH#60729 series = Series([None, 1, 2, None, 3, 4, None], dtype=Int64Dtype()) result = series.mask(series <= 2, -99) - expected = Series([None, 1, 2, None, -99, -99, None], dtype=Int64Dtype()) + expected = Series([None, -99, -99, None, 3, 4, None], dtype=Int64Dtype()) tm.assert_series_equal(result, expected) From db30b581bf3bb2bbeb833b8920f93d7f7cd91299 Mon Sep 17 00:00:00 2001 From: SALCAN <68040183+sanggon6107@users.noreply.github.com> Date: Sun, 9 Feb 2025 12:34:02 +0900 Subject: [PATCH 07/23] Update doc/source/whatsnew/v3.0.0.rst Co-authored-by: Xiao Yuan --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 5e0281f59984b..62db1e993acd3 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -676,7 +676,7 @@ Interval Indexing ^^^^^^^^ -- Bug in :func:`Series.mask` unexpectedly filling pd.NA (:issue:`60729`) +- Bug in :meth:`Series.mask` unexpectedly filling ``pd.NA`` (:issue:`60729`) - Bug in :meth:`DataFrame.__getitem__` returning modified columns when called with ``slice`` in Python 3.12 (:issue:`57500`) - Bug in :meth:`DataFrame.from_records` throwing a ``ValueError`` when passed an empty list in ``index`` (:issue:`58594`) - Bug in :meth:`MultiIndex.insert` when a new value inserted to a datetime-like level gets cast to ``NaT`` and fails indexing (:issue:`60388`) From cb94cf7f610cd13f6ea50ded62cd34f5461986b4 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Mon, 3 Mar 2025 16:15:22 +0900 Subject: [PATCH 08/23] Add test arguments for test_mask_na Co-authored by: rhshadrach --- pandas/tests/series/indexing/test_mask.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index de1a3ff5b64e1..c53ab264bdac3 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -2,7 +2,6 @@ import pytest from pandas import ( - Int64Dtype, Series, ) import pandas._testing as tm @@ -72,10 +71,11 @@ def test_mask_inplace(): tm.assert_series_equal(rs, s.mask(cond, -s)) -def test_mask_na(): +@pytest.mark.parametrize("dtype", ["Int64", "int64[pyarrow]"]) +def test_mask_na(dtype): # We should not be filling pd.NA. See GH#60729 - series = Series([None, 1, 2, None, 3, 4, None], dtype=Int64Dtype()) + series = Series([None, 1, 2, None, 3, 4, None], dtype=dtype) result = series.mask(series <= 2, -99) - expected = Series([None, -99, -99, None, 3, 4, None], dtype=Int64Dtype()) + expected = Series([None, -99, -99, None, 3, 4, None], dtype=dtype) tm.assert_series_equal(result, expected) From 71e442ea456c80d0036ac7aa41282dfae8271480 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Mon, 3 Mar 2025 16:20:57 +0900 Subject: [PATCH 09/23] Fix whatsnew --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index d4dab7dec4d64..1cd8c48413d1d 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -691,11 +691,11 @@ Interval Indexing ^^^^^^^^ -- Bug in :meth:`Series.mask` unexpectedly filling ``pd.NA`` (:issue:`60729`) - Bug in :meth:`DataFrame.__getitem__` returning modified columns when called with ``slice`` in Python 3.12 (:issue:`57500`) - Bug in :meth:`DataFrame.from_records` throwing a ``ValueError`` when passed an empty list in ``index`` (:issue:`58594`) - Bug in :meth:`DataFrame.loc` with inconsistent behavior of loc-set with 2 given indexes to Series (:issue:`59933`) - Bug in :meth:`MultiIndex.insert` when a new value inserted to a datetime-like level gets cast to ``NaT`` and fails indexing (:issue:`60388`) +- Bug in :meth:`Series.mask` unexpectedly filling ``pd.NA`` (:issue:`60729`) - Bug in printing :attr:`Index.names` and :attr:`MultiIndex.levels` would not escape single quotes (:issue:`60190`) Missing From b6bd3af0c85ca23e8497732b9b49ea57d4a970f2 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Mon, 3 Mar 2025 17:44:11 +0900 Subject: [PATCH 10/23] Fix test failures by adding importorskip --- pandas/tests/series/indexing/test_mask.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index c53ab264bdac3..44b4e4cb3bc17 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -73,6 +73,8 @@ def test_mask_inplace(): @pytest.mark.parametrize("dtype", ["Int64", "int64[pyarrow]"]) def test_mask_na(dtype): + if dtype == "int64[pyarrow]": + pytest.importorskip("pyarrow") # We should not be filling pd.NA. See GH#60729 series = Series([None, 1, 2, None, 3, 4, None], dtype=dtype) result = series.mask(series <= 2, -99) From 8bac9979db2d8c44264b3f8b86ab9090537cf0ef Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Mon, 3 Mar 2025 20:16:30 +0900 Subject: [PATCH 11/23] Fill True when tuple or list cond has np.nan/pd.NA --- pandas/core/generic.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 969f98d0eeadb..efaeb78e09503 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9698,15 +9698,19 @@ def _where( if axis is not None: axis = self._get_axis_number(axis) + cond = common.apply_if_callable(cond, self) + # We should not be filling NA. See GH#60729 if isinstance(cond, np.ndarray): cond = np.array(cond) - cond[np.isnan(cond)] = True + cond[isna(cond)] = True elif isinstance(cond, NDFrame): cond = cond.fillna(True) + elif isinstance(cond, (list, tuple)): + cond = np.array(cond) + cond[isna(cond)] = True # align the cond to same shape as myself - cond = common.apply_if_callable(cond, self) if isinstance(cond, NDFrame): # CoW: Make sure reference is not kept alive if cond.ndim == 1 and self.ndim == 2: From f154cf5a34356379437002d387ce12d3e84726ad Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Tue, 4 Mar 2025 22:50:22 +0900 Subject: [PATCH 12/23] Optimize _where --- pandas/core/generic.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index efaeb78e09503..a684ebdfdd4f5 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9698,20 +9698,10 @@ def _where( if axis is not None: axis = self._get_axis_number(axis) - cond = common.apply_if_callable(cond, self) - - # We should not be filling NA. See GH#60729 - if isinstance(cond, np.ndarray): - cond = np.array(cond) - cond[isna(cond)] = True - elif isinstance(cond, NDFrame): - cond = cond.fillna(True) - elif isinstance(cond, (list, tuple)): - cond = np.array(cond) - cond[isna(cond)] = True - # align the cond to same shape as myself + cond = common.apply_if_callable(cond, self) if isinstance(cond, NDFrame): + cond = cond.fillna(True) # CoW: Make sure reference is not kept alive if cond.ndim == 1 and self.ndim == 2: cond = cond._constructor_expanddim( @@ -9723,6 +9713,7 @@ def _where( else: if not hasattr(cond, "shape"): cond = np.asanyarray(cond) + cond[isna(cond)] = True if cond.shape != self.shape: raise ValueError("Array conditional must be same shape as self") cond = self._constructor(cond, **self._construct_axes_dict(), copy=False) From eed6121e43e45f7b5e503c43883269a4a70bd495 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Tue, 4 Mar 2025 22:57:27 +0900 Subject: [PATCH 13/23] Optimize test_mask_na --- pandas/tests/series/indexing/test_mask.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index 44b4e4cb3bc17..38ad2338389e9 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -1,9 +1,9 @@ import numpy as np import pytest -from pandas import ( - Series, -) +import pandas.util._test_decorators as td + +from pandas import Series import pandas._testing as tm @@ -71,10 +71,14 @@ def test_mask_inplace(): tm.assert_series_equal(rs, s.mask(cond, -s)) -@pytest.mark.parametrize("dtype", ["Int64", "int64[pyarrow]"]) +@pytest.mark.parametrize( + "dtype", + [ + "Int64", + pytest.param("int64[pyarrow]", marks=td.skip_if_no("pyarrow")), + ], +) def test_mask_na(dtype): - if dtype == "int64[pyarrow]": - pytest.importorskip("pyarrow") # We should not be filling pd.NA. See GH#60729 series = Series([None, 1, 2, None, 3, 4, None], dtype=dtype) result = series.mask(series <= 2, -99) From 9ac81f04045127ee8d339787cd6c7f63ac52a1c1 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Wed, 5 Mar 2025 19:43:26 +0900 Subject: [PATCH 14/23] Add np.array for read-only ndarray --- pandas/core/generic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index a684ebdfdd4f5..154721cbf966d 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9713,6 +9713,8 @@ def _where( else: if not hasattr(cond, "shape"): cond = np.asanyarray(cond) + else: + cond = np.array(cond) cond[isna(cond)] = True if cond.shape != self.shape: raise ValueError("Array conditional must be same shape as self") From 8c5ffff2dbe2eba102f5f87a7a0f1d1a86f9afb3 Mon Sep 17 00:00:00 2001 From: SALCAN <68040183+sanggon6107@users.noreply.github.com> Date: Thu, 6 Mar 2025 08:46:41 +0900 Subject: [PATCH 15/23] Update generic.py Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> --- pandas/core/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 154721cbf966d..7c29cbcedf2a4 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9714,7 +9714,7 @@ def _where( if not hasattr(cond, "shape"): cond = np.asanyarray(cond) else: - cond = np.array(cond) + cond = extract_array(cond, extract_numpy=True) cond[isna(cond)] = True if cond.shape != self.shape: raise ValueError("Array conditional must be same shape as self") From 55165171c2cdaa4c2dd325bc05eb2eb757aa049e Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 6 Mar 2025 20:43:53 +0900 Subject: [PATCH 16/23] Revert generic.py --- pandas/core/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 7c29cbcedf2a4..154721cbf966d 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9714,7 +9714,7 @@ def _where( if not hasattr(cond, "shape"): cond = np.asanyarray(cond) else: - cond = extract_array(cond, extract_numpy=True) + cond = np.array(cond) cond[isna(cond)] = True if cond.shape != self.shape: raise ValueError("Array conditional must be same shape as self") From 9556aa4160b02848c49ec3f527a01e27809ca7a2 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Fri, 7 Mar 2025 20:10:21 +0900 Subject: [PATCH 17/23] Replace np.array with fillna --- pandas/core/generic.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 154721cbf966d..5410a4a9b1f0b 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9713,12 +9713,11 @@ def _where( else: if not hasattr(cond, "shape"): cond = np.asanyarray(cond) - else: - cond = np.array(cond) cond[isna(cond)] = True if cond.shape != self.shape: raise ValueError("Array conditional must be same shape as self") cond = self._constructor(cond, **self._construct_axes_dict(), copy=False) + cond = cond.fillna(True) # make sure we are boolean fill_value = bool(inplace) From b64b8a735eab52252e5d015ae8b44c0a1b14574a Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Fri, 7 Mar 2025 20:27:14 +0900 Subject: [PATCH 18/23] Correct the unintended deletion --- pandas/core/generic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 5410a4a9b1f0b..51d22c99f6543 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9713,7 +9713,6 @@ def _where( else: if not hasattr(cond, "shape"): cond = np.asanyarray(cond) - cond[isna(cond)] = True if cond.shape != self.shape: raise ValueError("Array conditional must be same shape as self") cond = self._constructor(cond, **self._construct_axes_dict(), copy=False) From c073c0b2c5dc4919eb2f76d89ef005d4faab0dff Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Mon, 24 Mar 2025 20:25:49 +0900 Subject: [PATCH 19/23] Add test for list and ndarray --- pandas/tests/series/indexing/test_mask.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index 38ad2338389e9..c5385f4733770 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -81,7 +81,14 @@ def test_mask_inplace(): def test_mask_na(dtype): # We should not be filling pd.NA. See GH#60729 series = Series([None, 1, 2, None, 3, 4, None], dtype=dtype) - result = series.mask(series <= 2, -99) + cond = series <= 2 expected = Series([None, -99, -99, None, 3, 4, None], dtype=dtype) + result = series.mask(cond, -99) + tm.assert_series_equal(result, expected) + + result = series.mask(cond.to_list(), expected) + tm.assert_series_equal(result, expected) + + result = series.mask(cond.to_numpy(), expected) tm.assert_series_equal(result, expected) From 4eea08e96ef2309bdf5f4582759db6bea15d8cb7 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 27 Mar 2025 19:49:12 +0900 Subject: [PATCH 20/23] Handle list with NA --- pandas/core/generic.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 51d22c99f6543..ad6a85d23a32f 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -28,6 +28,7 @@ from pandas._libs import lib from pandas._libs.lib import is_range_indexer +from pandas._libs.missing import NA from pandas._libs.tslibs import ( Period, Timestamp, @@ -10099,6 +10100,21 @@ def mask( if not hasattr(cond, "__invert__"): cond = np.array(cond) + if isinstance(cond, np.ndarray): + if all( + np.apply_along_axis( + lambda x: x[0] is NA + or isinstance(x[0], (np.bool_, bool)) + or x[0] is np.nan, + axis=1, + arr=cond.flatten().reshape(cond.size, 1), + ) + ): + if not cond.flags.writeable: + cond.setflags(write=1) + cond[isna(cond)] = False + cond = cond.astype(bool) + return self._where( ~cond, other=other, From bbc56120349cfdb8aa34bbf760bcd1a7d3a4b8ae Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 27 Mar 2025 22:21:40 +0900 Subject: [PATCH 21/23] Fix code checks --- pandas/core/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index ad6a85d23a32f..2b5b7a80648a6 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -10111,7 +10111,7 @@ def mask( ) ): if not cond.flags.writeable: - cond.setflags(write=1) + cond.setflags(write=True) cond[isna(cond)] = False cond = cond.astype(bool) From 085159304203ca8a5427cce2176d26d018cc0bc5 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Thu, 27 Mar 2025 23:13:20 +0900 Subject: [PATCH 22/23] Fix type --- pandas/tests/series/indexing/test_mask.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/series/indexing/test_mask.py b/pandas/tests/series/indexing/test_mask.py index c5385f4733770..3bfade287bd05 100644 --- a/pandas/tests/series/indexing/test_mask.py +++ b/pandas/tests/series/indexing/test_mask.py @@ -87,8 +87,8 @@ def test_mask_na(dtype): result = series.mask(cond, -99) tm.assert_series_equal(result, expected) - result = series.mask(cond.to_list(), expected) + result = series.mask(cond.to_list(), -99) tm.assert_series_equal(result, expected) - result = series.mask(cond.to_numpy(), expected) + result = series.mask(cond.to_numpy(), -99) tm.assert_series_equal(result, expected) From 98fb60218471e69edd8a002c98efba793dd183f3 Mon Sep 17 00:00:00 2001 From: sanggon6107 Date: Fri, 28 Mar 2025 20:51:11 +0900 Subject: [PATCH 23/23] Optimize operation --- pandas/core/generic.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 2b5b7a80648a6..f0fc8fa4d695f 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -10102,13 +10102,8 @@ def mask( if isinstance(cond, np.ndarray): if all( - np.apply_along_axis( - lambda x: x[0] is NA - or isinstance(x[0], (np.bool_, bool)) - or x[0] is np.nan, - axis=1, - arr=cond.flatten().reshape(cond.size, 1), - ) + x is NA or isinstance(x, (np.bool_, bool)) or x is np.nan + for x in cond.flatten() ): if not cond.flags.writeable: cond.setflags(write=True)