Skip to content

fix: str.slice(..., length=0) returns empty string on pandas and dask - #3891

Merged
FBruzzesi merged 1 commit into
narwhals-dev:mainfrom
winklemad:fix/str-slice-length-zero
Aug 31, 2026
Merged

FBruzzesi merged 1 commit into
narwhals-dev:mainfrom
winklemad:fix/str-slice-length-zero

Conversation

@winklemad

Copy link
Copy Markdown
Contributor

Description

I noticed str.slice(offset, length=0) gives different results depending on the backend. On pandas and dask it returns the rest of the string, but on Polars, PyArrow and the SQL backends it correctly returns an empty string:

import narwhals as nw, pandas as pd, polars as pl
data = {"s": ["abcdef", "xyz"]}
nw.from_native(pd.DataFrame(data)).select(nw.col("s").str.slice(1, 0)).to_native()["s"].tolist()
# ['bcdef', 'yz']   <- wrong
nw.from_native(pl.DataFrame(data)).select(nw.col("s").str.slice(1, 0)).to_native()["s"].to_list()
# ['', '']          <- correct

The cause is in _pandas_like/series_str.py and _dask/expr_str.py, which compute the stop as offset + length if length else None. A length of 0 is falsy, so it's treated the same as None ("slice to the end"). The Arrow and SQL backends already use length is not None, so this just brings pandas and dask in line with them.

What type of PR is this? (check all applicable)

  • 💾 Refactor
  • ✨ Feature
  • 🐛 Bug Fix
  • 🔧 Optimization
  • 📝 Documentation
  • ✅ Test
  • 🐳 Other

Related issues

Found while reading the string namespace, no existing issue.

AI assistance

  • No AI tools were used for this PR.
  • AI tools were used.

I used Claude Code to help find the divergence and draft the test. I read the code, reproduced it across all backends, and understand and stand behind every line.

Checklist

  • Code follows style guide (ruff)
  • Tests added
  • Documented the changes (behaviour fix, no doc change needed)
  • If this is your first PR to narwhals, attach a screenshot of pytest passing locally (not CI):

This is my first PR here. I can't attach an image in the PR body, so here is the terminal output of the slice tests passing across the backends I have installed locally (pandas, pandas[pyarrow], pyarrow, polars eager+lazy, dask):

$ pytest tests/expr_and_series/str/slice_test.py \
    --constructors=pandas,pandas[pyarrow],pyarrow,polars[eager],polars[lazy],dask

tests/expr_and_series/str/slice_test.py ..............................   [100%]
============================== 30 passed in 0.61s ==============================

The new (1, 0, {"a": ["", ""]}) case fails on main for pandas/dask and passes with this change; happy to attach a screenshot too if you'd prefer.

The pandas-like and dask backends computed the slice stop as
`offset + length if length else None`, so a valid length of 0 is falsy and
treated as None, meaning 'slice to the end' instead of returning an empty
string. str.slice(1, 0) returned the rest of the string on pandas/dask while
Polars, PyArrow and the SQL backends correctly returned ''. Use
`length is not None` to match them.
@FBruzzesi FBruzzesi added fix pandas-like Issue is related to pandas-like backends dask Issue is related to dask backend labels Aug 31, 2026
@FBruzzesi FBruzzesi changed the title fix: str.slice with length=0 returns empty string on pandas and dask fix: `str.slice(..., length=0)´ returns empty string on pandas and dask Aug 31, 2026
@FBruzzesi FBruzzesi changed the title fix: `str.slice(..., length=0)´ returns empty string on pandas and dask fix: str.slice(..., length=0) returns empty string on pandas and dask Aug 31, 2026

@FBruzzesi FBruzzesi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for spotting the issue and fixing it @winklemad 🙏🏼

@FBruzzesi
FBruzzesi merged commit 3fab72a into narwhals-dev:main Aug 31, 2026
39 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dask Issue is related to dask backend fix pandas-like Issue is related to pandas-like backends

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants