Skip to content

Commit

Permalink
fix: Fix DataFrame.__getitem__ when slicing with tuple and null sli…
Browse files Browse the repository at this point in the history
…ce (#1123)

* fix: Fix `DataFrame.__getitem__` when slicing with tuple and null slice

* old polars compat
  • Loading branch information
MarcoGorelli authored Oct 3, 2024
1 parent 09e184f commit 3f8ba38
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 2 deletions.
4 changes: 4 additions & 0 deletions narwhals/_arrow/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ def __getitem__(
elif isinstance(item, tuple) and len(item) == 2:
if isinstance(item[1], slice):
columns = self.columns
if item[1] == slice(None):
if isinstance(item[0], Sequence) and len(item[0]) == 0:
return self._from_native_frame(self._native_frame.slice(0, 0))
return self._from_native_frame(self._native_frame.take(item[0]))
if isinstance(item[1].start, str) or isinstance(item[1].stop, str):
start, stop, step = convert_str_slice_to_int_slice(item[1], columns)
return self._from_native_frame(
Expand Down
2 changes: 2 additions & 0 deletions narwhals/_pandas_like/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ def __getitem__(

elif isinstance(item, tuple) and len(item) == 2 and isinstance(item[1], slice):
columns = self._native_frame.columns
if item[1] == slice(None):
return self._from_native_frame(self._native_frame.iloc[item[0], :])
if isinstance(item[1].start, str) or isinstance(item[1].stop, str):
start, stop, step = convert_str_slice_to_int_slice(item[1], columns)
return self._from_native_frame(
Expand Down
7 changes: 7 additions & 0 deletions narwhals/_polars/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import TYPE_CHECKING
from typing import Any
from typing import Sequence

from narwhals._polars.namespace import PolarsNamespace
from narwhals._polars.utils import convert_str_slice_to_int_slice
Expand Down Expand Up @@ -117,6 +118,12 @@ def __getitem__(self, item: Any) -> Any:

columns = self.columns
if isinstance(item, tuple) and len(item) == 2 and isinstance(item[1], slice):
if item[1] == slice(None):
if isinstance(item[0], Sequence) and not len(item[0]):
return self._from_native_frame(self._native_frame[0:0])
return self._from_native_frame(
self._native_frame.__getitem__(item[0])
)
if isinstance(item[1].start, str) or isinstance(item[1].stop, str):
start, stop, step = convert_str_slice_to_int_slice(item[1], columns)
return self._from_native_frame(
Expand Down
2 changes: 0 additions & 2 deletions narwhals/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,6 @@ def __getitem__(
):
if item[1] == slice(None) and item[0] == slice(None):
return self
if item[1] == slice(None):
return self._from_compliant_dataframe(self._compliant_frame[item[0]])
return self._from_compliant_dataframe(self._compliant_frame[item])
if isinstance(item, str) or (isinstance(item, tuple) and len(item) == 2):
return self._series(
Expand Down
9 changes: 9 additions & 0 deletions tests/frame/getitem_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,15 @@ def test_slice_slice_columns(constructor_eager: Any) -> None: # noqa: PLR0915
result = df["a":"b"] # type: ignore[misc]
expected = {"a": [1, 2, 3], "b": [4, 5, 6]}
compare_dicts(result, expected)
result = df[(0, 1), :]
expected = {"a": [1, 2], "b": [4, 5], "c": [7, 8], "d": [1, 4]}
compare_dicts(result, expected)
result = df[[0, 1], :]
expected = {"a": [1, 2], "b": [4, 5], "c": [7, 8], "d": [1, 4]}
compare_dicts(result, expected)
result = df[[0, 1], df.columns]
expected = {"a": [1, 2], "b": [4, 5], "c": [7, 8], "d": [1, 4]}
compare_dicts(result, expected)


def test_slice_invalid(constructor_eager: Any) -> None:
Expand Down

0 comments on commit 3f8ba38

Please sign in to comment.