From c23266b6d152d0d6882807603563c43272530379 Mon Sep 17 00:00:00 2001 From: barak1412 Date: Sun, 29 Sep 2024 20:14:42 +0300 Subject: [PATCH] fix: Return the truth values of `ne_missing` and `eq_missing` operations for struct instead of `null` (#18930) --- .../src/chunked_array/comparison/mod.rs | 9 ++++++- .../tests/unit/operations/test_comparison.py | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/polars-core/src/chunked_array/comparison/mod.rs b/crates/polars-core/src/chunked_array/comparison/mod.rs index 07bd9d24a2bf..13f557d20886 100644 --- a/crates/polars-core/src/chunked_array/comparison/mod.rs +++ b/crates/polars-core/src/chunked_array/comparison/mod.rs @@ -759,6 +759,7 @@ fn struct_helper( op: F, reduce: R, value: bool, + is_missing: bool, ) -> BooleanChunked where F: Fn(&Series, &Series) -> BooleanChunked, @@ -778,7 +779,8 @@ where .map(|(l, r)| op(l, r)) .reduce(reduce) .unwrap(); - if a.null_count() > 0 || b.null_count() > 0 { + + if !is_missing & (a.null_count() > 0 || b.null_count() > 0) { let mut a = a.into_owned(); a.zip_outer_validity(&b); unsafe { @@ -787,6 +789,7 @@ where } } } + out } } @@ -801,6 +804,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked { |l, r| l.equal(r).unwrap(), |a, b| a.bitand(b), false, + false, ) } @@ -811,6 +815,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked { |l, r| l.equal_missing(r).unwrap(), |a, b| a.bitand(b), false, + true, ) } @@ -821,6 +826,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked { |l, r| l.not_equal(r).unwrap(), |a, b| a | b, true, + false, ) } @@ -831,6 +837,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked { |l, r| l.not_equal_missing(r).unwrap(), |a, b| a | b, true, + true, ) } } diff --git a/py-polars/tests/unit/operations/test_comparison.py b/py-polars/tests/unit/operations/test_comparison.py index fbc6e9e439aa..71ddf6157e99 100644 --- a/py-polars/tests/unit/operations/test_comparison.py +++ b/py-polars/tests/unit/operations/test_comparison.py @@ -160,6 +160,30 @@ def test_missing_equality_on_bools() -> None: ] +def test_struct_equality_18870() -> None: + s = pl.Series([{"a": 1}, None]) + + # eq + result = s.eq(s).to_list() + expected = [True, None] + assert result == expected + + # ne + result = s.ne(s).to_list() + expected = [False, None] + assert result == expected + + # eq_missing + result = s.eq_missing(s).to_list() + expected = [True, True] + assert result == expected + + # ne_missing + result = s.ne_missing(s).to_list() + expected = [False, False] + assert result == expected + + def isnan(x: Any) -> bool: return isinstance(x, float) and math.isnan(x)