Skip to content

Commit

Permalink
feat: add Series.drop nulls for pyarrow (narwhals-dev#542)
Browse files Browse the repository at this point in the history
  • Loading branch information
mfonekpo authored Jul 22, 2024
1 parent 59fce21 commit d0e8dc0
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 16 deletions.
3 changes: 3 additions & 0 deletions narwhals/_arrow/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ def all(self) -> Self:
def sum(self) -> Self:
return reuse_series_implementation(self, "sum", returns_scalar=True)

def drop_nulls(self) -> Self:
return reuse_series_implementation(self, "drop_nulls")

def alias(self, name: str) -> Self:
# Define this one manually, so that we can
# override `output_names` and not increase depth
Expand Down
4 changes: 4 additions & 0 deletions narwhals/_arrow/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ def sum(self) -> int:
pc = get_pyarrow_compute()
return pc.sum(self._native_series) # type: ignore[no-any-return]

def drop_nulls(self) -> ArrowSeries:
pc = get_pyarrow_compute()
return self._from_native_series(pc.drop_null(self._native_series))

def std(self, ddof: int = 1) -> int:
pc = get_pyarrow_compute()
return pc.stddev(self._native_series, ddof=ddof) # type: ignore[no-any-return]
Expand Down
31 changes: 31 additions & 0 deletions tests/expr_and_series/drop_nulls_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from __future__ import annotations

from typing import Any

import narwhals as nw
from tests.utils import compare_dicts


def test_drop_nulls(constructor: Any) -> None:
data = {
"A": [1, 2, None, 4],
"B": [5, 6, 7, 8],
"C": [None, None, None, None],
"D": [9, 10, 11, 12],
}

df = nw.from_native(constructor(data), eager_only=True)

result_a = df.select(nw.col("A").drop_nulls())
result_b = df.select(df["B"].drop_nulls())
result_c = df.select(nw.col("C").drop_nulls())
result_d = df.select(nw.col("D").drop_nulls())
expected_a = {"A": [1.0, 2.0, 4.0]}
expected_b = {"B": [5, 6, 7, 8]}
expected_c = {"C": []} # type: ignore[var-annotated]
expected_d = {"D": [9, 10, 11, 12]}

compare_dicts(result_a, expected_a)
compare_dicts(result_b, expected_b)
compare_dicts(result_c, expected_c)
compare_dicts(result_d, expected_d)
15 changes: 0 additions & 15 deletions tests/frame/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,21 +159,6 @@ def test_expr_na(constructor_with_lazy: Any) -> None:
compare_dicts(result_nna, expected)


def test_drop_nulls(request: Any, constructor_with_lazy: Any) -> None:
if "pyarrow_table" in str(constructor_with_lazy):
request.applymarker(pytest.mark.xfail)

df = nw.from_native(constructor_with_lazy(data_na)).lazy()

result = df.select(nw.col("a").drop_nulls())
expected = {"a": [3, 2]}
compare_dicts(result, expected)

result = df.select(df.collect()["a"].drop_nulls())
expected = {"a": [3, 2]}
compare_dicts(result, expected)


@pytest.mark.parametrize(
("drop", "left"),
[
Expand Down
1 change: 0 additions & 1 deletion utils/check_backend_completeness.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
MISSING = [
"DataFrame.iter_rows",
"DataFrame.pipe",
"Series.drop_nulls",
"Series.from_iterable",
"Series.is_between",
"Series.quantile",
Expand Down

0 comments on commit d0e8dc0

Please sign in to comment.