๐ข Turtle Island
July 24, 2025 ยท View on GitHub
๐ข Turtle Island
Turtle Island is a lightweight utility library that provides helper functions to reduce boilerplate when writing Polars expressions. It aims to simplify common expression patterns and improve developer productivity when working with the Polars API.
โ ๏ธ Disclaimer: This project is in early development. The API is still evolving and may change without notice. Use with caution in production environments.
๐ Installation
Turtle Island is not yet published on PyPI. The recommended way to install it is using uv add:
uv add git+https://github.com/jrycw/turtle-island.git
๐ฆ Recommended Import
To keep your code clean and idiomatic, it's recommended to import Turtle Island as a top-level module:
import turtle_island as ti
โ๏ธ Core Spirit
The core spirit of Turtle Island is to embrace expressions over columns.
When wrangling data, it's common to create temporary helper columns as part of the transformation process. However, many of these columns are just intermediate artifacts โ not part of the final output we actually want. They exist solely to assist with intermediate steps.
Polars offers a powerful distinction between contexts and expressions, allowing us to focus on expression-based transformations without needing to materialize every intermediate result as a column. Turtle Island builds on this principle, encouraging users to rely more on expressions โ flexible, composable, and context-aware โ rather than temporary columns.
โจ Selected Functions
case_when()
A more ergonomic way to write chained when-then-otherwise logic in Polars:
df = pl.DataFrame({"x": [1, 2, 3, 4]})
expr_ti = ti.case_when(
case_list=[(pl.col("x") < 2, pl.lit("small")),
(pl.col("x") < 4, pl.lit("medium"))],
otherwise=pl.lit("large"),
).alias("size_ti")
expr_pl = (
pl.when(pl.col("x") < 2)
.then(pl.lit("small"))
.when(pl.col("x") < 4)
.then(pl.lit("medium"))
.otherwise(pl.lit("large"))
.alias("size_pl")
)
df.with_columns(expr_ti, expr_pl)
shape: (4, 3)
โโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโ
โ x โ size_ti โ size_pl โ
โ --- โ --- โ --- โ
โ i64 โ str โ str โ
โโโโโโโชโโโโโโโโโโชโโโโโโโโโโก
โ 1 โ small โ small โ
โ 2 โ medium โ medium โ
โ 3 โ medium โ medium โ
โ 4 โ large โ large โ
โโโโโโโดโโโโโโโโโโดโโโโโโโโโโ
make_index()
Adds a sequential index column to the DataFrame:
df = pl.DataFrame({"a": [1, 3, 5], "b": [2, 4, 6]})
df.select(ti.make_index(), pl.all())
shape: (3, 3)
โโโโโโโโโฌโโโโโโฌโโโโโโ
โ index โ a โ b โ
โ --- โ --- โ --- โ
โ u32 โ i64 โ i64 โ
โโโโโโโโโชโโโโโโชโโโโโโก
โ 0 โ 1 โ 2 โ
โ 1 โ 3 โ 4 โ
โ 2 โ 5 โ 6 โ
โโโโโโโโโดโโโโโโดโโโโโโ
bucketize()
Assign values to rows in a round-robin pattern using Polars expressions:
df = pl.DataFrame({"x": [1, 2, 3, 4, 5]})
df.with_columns(
ti.bucketize(pl.col("x"), pl.col("x").add(100)).alias("bucketized")
)
shape: (5, 2)
โโโโโโโฌโโโโโโโโโโโโโ
โ x โ bucketized โ
โ --- โ --- โ
โ i64 โ i64 โ
โโโโโโโชโโโโโโโโโโโโโก
โ 1 โ 1 โ
โ 2 โ 102 โ
โ 3 โ 3 โ
โ 4 โ 104 โ
โ 5 โ 5 โ
โโโโโโโดโโโโโโโโโโโโโ
bucketize_lit()
Assign values to rows in a round-robin pattern using literal values:
df = pl.DataFrame({"x": [1, 2, 3, 4, 5]})
df.with_columns(ti.bucketize_lit(True, False).alias("bucketized"))
shape: (5, 2)
โโโโโโโฌโโโโโโโโโโโโโ
โ x โ bucketized โ
โ --- โ --- โ
โ i64 โ bool โ
โโโโโโโชโโโโโโโโโโโโโก
โ 1 โ true โ
โ 2 โ false โ
โ 3 โ true โ
โ 4 โ false โ
โ 5 โ true โ
โโโโโโโดโโโโโโโโโโโโโ
is_every_nth_row()
Mark every second row:
df = pl.DataFrame({"x": [1, 2, 3, 4, 5]})
df.with_columns(ti.is_every_nth_row(2))
shape: (5, 2)
โโโโโโโฌโโโโโโโโโโโโโโโ
โ x โ bool_nth_row โ
โ --- โ --- โ
โ i64 โ bool โ
โโโโโโโชโโโโโโโโโโโโโโโก
โ 1 โ true โ
โ 2 โ false โ
โ 3 โ true โ
โ 4 โ false โ
โ 5 โ true โ
โโโโโโโดโโโโโโโโโโโโโโโ
To invert the result:
df.with_columns(~ti.is_every_nth_row(2))
shape: (5, 2)
โโโโโโโฌโโโโโโโโโโโโโโโ
โ x โ bool_nth_row โ
โ --- โ --- โ
โ i64 โ bool โ
โโโโโโโชโโโโโโโโโโโโโโโก
โ 1 โ false โ
โ 2 โ true โ
โ 3 โ false โ
โ 4 โ true โ
โ 5 โ false โ
โโโโโโโดโโโโโโโโโโโโโโโ
move_cols_to_start()
Reorder columns so that selected columns appear first:
df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [4.4, 5.5, 6.6]})
df.select(ti.move_cols_to_start(["b", "c"]))
Or by data type:
df.select(ti.move_cols_to_start([pl.Float64, pl.String]))
shape: (3, 3)
โโโโโโโฌโโโโโโฌโโโโโโ
โ b โ c โ a โ
โ --- โ --- โ --- โ
โ str โ f64 โ i64 โ
โโโโโโโชโโโโโโชโโโโโโก
โ x โ 4.4 โ 1 โ
โ y โ 5.5 โ 2 โ
โ z โ 6.6 โ 3 โ
โโโโโโโดโโโโโโดโโโโโโ
move_cols_to_end()
Reorder columns so that selected columns appear last:
df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [4.4, 5.5, 6.6]})
df.select(ti.move_cols_to_end(["a", "b"]))
Or by data type:
df.select(ti.move_cols_to_end([pl.String, pl.Int64]))
shape: (3, 3)
โโโโโโโฌโโโโโโฌโโโโโโ
โ c โ a โ b โ
โ --- โ --- โ --- โ
โ f64 โ i64 โ str โ
โโโโโโโชโโโโโโชโโโโโโก
โ 4.4 โ 1 โ x โ
โ 5.5 โ 2 โ y โ
โ 6.6 โ 3 โ z โ
โโโโโโโดโโโโโโดโโโโโโ
make_hyperlink()
Create an HTML anchor tag (<a>) from two columns โ link text and URL:
df = pl.DataFrame({"name": ["GitHub"], "url": ["https://github.com/"]})
df.select(ti.make_hyperlink("name", "url").alias("link"))
shape: (1, 1)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ link โ
โ --- โ
โ str โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโก
โ <a href="https://github.com/" target="_blank">GitHub</a> โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ