Skip to content

Commit

Permalink
fix: Return the truth values of ne_missing and eq_missing operati…
Browse files Browse the repository at this point in the history
…ons for struct instead of `null` (#18930)
  • Loading branch information
barak1412 authored Sep 29, 2024
1 parent 4985576 commit c23266b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
9 changes: 8 additions & 1 deletion crates/polars-core/src/chunked_array/comparison/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ fn struct_helper<F, R>(
op: F,
reduce: R,
value: bool,
is_missing: bool,
) -> BooleanChunked
where
F: Fn(&Series, &Series) -> BooleanChunked,
Expand All @@ -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 {
Expand All @@ -787,6 +789,7 @@ where
}
}
}

out
}
}
Expand All @@ -801,6 +804,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked {
|l, r| l.equal(r).unwrap(),
|a, b| a.bitand(b),
false,
false,
)
}

Expand All @@ -811,6 +815,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked {
|l, r| l.equal_missing(r).unwrap(),
|a, b| a.bitand(b),
false,
true,
)
}

Expand All @@ -821,6 +826,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked {
|l, r| l.not_equal(r).unwrap(),
|a, b| a | b,
true,
false,
)
}

Expand All @@ -831,6 +837,7 @@ impl ChunkCompareEq<&StructChunked> for StructChunked {
|l, r| l.not_equal_missing(r).unwrap(),
|a, b| a | b,
true,
true,
)
}
}
Expand Down
24 changes: 24 additions & 0 deletions py-polars/tests/unit/operations/test_comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down

0 comments on commit c23266b

Please sign in to comment.