-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add Series.__contains__
#1480
Changes from 6 commits
e36d4ed
e6d9419
9a90632
3aa5b75
c653e48
3f66045
c9f0b36
b2b005a
38c5833
634c262
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -851,6 +851,11 @@ def rolling_mean( | |
def __iter__(self: Self) -> Iterator[Any]: | ||
yield from self._native_series.__iter__() | ||
|
||
def __contains__(self: Self, other: Any) -> bool: | ||
if other is None: | ||
return self._native_series.isna().any() # type: ignore[no-any-return] | ||
FBruzzesi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return self._native_series.isin({other}).any() # type: ignore[no-any-return] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why this over There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No strong feelings π I guess I went for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "fell for" π love that from a quick test, it looks a lot faster In [13]: s = pd.Series(rng.integers(0, 10, size=1_000_000))
In [14]: %timeit s.isin({0}).any()
6.58 ms Β± 687 ΞΌs per loop (mean Β± std. dev. of 7 runs, 100 loops each)
In [15]: %timeit (s == 0).any()
326 ΞΌs Β± 45.8 ΞΌs per loop (mean Β± std. dev. of 7 runs, 1,000 loops each) |
||
|
||
def is_finite(self: Self) -> Self: | ||
s = self._native_series | ||
return self._from_native_series((s > float("-inf")) & (s < float("inf"))) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING | ||
|
||
import pytest | ||
|
||
import narwhals.stable.v1 as nw | ||
|
||
if TYPE_CHECKING: | ||
from tests.utils import ConstructorEager | ||
|
||
data = [100, 200, None] | ||
|
||
|
||
@pytest.mark.parametrize(("other", "expected"), [(100, True), (None, True), (3, False)]) | ||
def test_contains( | ||
constructor_eager: ConstructorEager, | ||
other: int | None, | ||
expected: bool, # noqa: FBT001 | ||
) -> None: | ||
s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] | ||
|
||
assert (other in s) == expected |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ | |
"value_counts", | ||
"zip_with", | ||
"__iter__", | ||
"__contains__", | ||
} | ||
BASE_DTYPES = { | ||
"NumericType", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if
other
is of a type not convertible tonative_series.type
, will this raise? I'm wondering if we should returnFalse
in such a case?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like polars would also raise here:
probably ok to just follow them here then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still, probably good to have a test to check it raises? we can leave the expression unification for a separate topic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add a test and make sure that same exception is raised π
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok this is definitly wrong behaviour for arrow as the casting would convert from float to int, leading to the following:
On the Exception side, I would not be sure how to catch the error for pandas as:
In a way, I find polars behaviour more surprising
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tbh we could just dispatch to
(s._compliant_series == other).any()
for all backends π that would still be better than the status quo