From 904f3cc1553bcbade67997a482019abfb8f5f4fd Mon Sep 17 00:00:00 2001 From: LandonB5 Date: Thu, 2 Oct 2025 14:12:33 -0400 Subject: [PATCH 1/2] BUG: treat missing sentinels as equal across dtypes when check_dtype=False; add test (GH#61473) --- pandas/_testing/asserters.py | 28 ++++++++++++++++++++ pandas/tests/util/test_assert_frame_equal.py | 9 +++++++ 2 files changed, 37 insertions(+) diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 2e5f8c372f7ef..56e451fd781f5 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -1105,6 +1105,33 @@ def assert_series_equal( index_values=left.index, obj=str(obj), ) + elif not check_dtype: + + left_na = left.isna().to_numpy(dtype=bool, copy=False) + right_na = right.isna().to_numpy(dtype=bool, copy=False) + assert_numpy_array_equal( + left_na, right_na, obj=f"{obj} NA mask", index_values=left.index + ) + + + def _normalize(arr): + + return [ + (None if pd.isna(x) else x) + for x in arr.to_numpy(dtype=object) + ] + left_valid = _normalize(left[~left_na]) + right_valid = _normalize(right[~right_na]) + + _testing.assert_almost_equal( + left_valid, + right_valid, + check_dtype=False, + rtol=rtol, + atol=atol, + obj=str(obj), + index_values=left.index, + ) else: _testing.assert_almost_equal( left._values, @@ -1488,3 +1515,4 @@ def assert_metadata_equivalent( assert val is None else: assert val == getattr(right, attr, None) + diff --git a/pandas/tests/util/test_assert_frame_equal.py b/pandas/tests/util/test_assert_frame_equal.py index 8711365a19214..c3e416c4a2112 100644 --- a/pandas/tests/util/test_assert_frame_equal.py +++ b/pandas/tests/util/test_assert_frame_equal.py @@ -5,6 +5,7 @@ import pandas as pd from pandas import DataFrame import pandas._testing as tm +from pandas.testing import assert_frame_equal @pytest.fixture(params=[True, False]) @@ -399,6 +400,7 @@ def test_assert_frame_equal_set_mismatch(): tm.assert_frame_equal(df1, df2) + def test_datetimelike_compat_deprecated(): # GH#55638 df = DataFrame({"a": [1]}) @@ -413,3 +415,10 @@ def test_datetimelike_compat_deprecated(): tm.assert_series_equal(df["a"], df["a"], check_datetimelike_compat=True) with tm.assert_produces_warning(Pandas4Warning, match=msg): tm.assert_series_equal(df["a"], df["a"], check_datetimelike_compat=False) + + +def test_assert_frame_equal_na_object_vs_int32_check_dtype_false(): + + df1 = pd.DataFrame({"x": pd.Series([pd.NA], dtype="Int32")}) + df2 = pd.DataFrame({"x": pd.Series([pd.NA], dtype="object")}) + assert_frame_equal(df1, df2, check_dtype=False) From 94cefbf28f91d8052b4a9e7ede46a23724eb4388 Mon Sep 17 00:00:00 2001 From: LandonB5 Date: Thu, 2 Oct 2025 14:46:40 -0400 Subject: [PATCH 2/2] BUG: normalize pd.NA and np.nan when check_dtype=False (GH#61473) --- pandas/_testing/asserters.py | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 56e451fd781f5..1548030696a7d 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -1106,32 +1106,30 @@ def assert_series_equal( obj=str(obj), ) elif not check_dtype: - + left_na = left.isna().to_numpy(dtype=bool, copy=False) right_na = right.isna().to_numpy(dtype=bool, copy=False) assert_numpy_array_equal( left_na, right_na, obj=f"{obj} NA mask", index_values=left.index - ) + ) - - def _normalize(arr): - - return [ - (None if pd.isna(x) else x) - for x in arr.to_numpy(dtype=object) - ] - left_valid = _normalize(left[~left_na]) - right_valid = _normalize(right[~right_na]) + + def _normalize(s): + arr = s.to_numpy(dtype=object) + return [(None if pd.isna(x) else x) for x in arr] + + left_norm = _normalize(left) + right_norm = _normalize(right) _testing.assert_almost_equal( - left_valid, - right_valid, - check_dtype=False, - rtol=rtol, - atol=atol, - obj=str(obj), - index_values=left.index, - ) + left_norm, + right_norm, + check_dtype=False, + rtol=rtol, + atol=atol, + obj=str(obj), + index_values=left.index, + ) else: _testing.assert_almost_equal( left._values,