2 Reference
Alongside the monomorphic, dtype-suffixed bindings (series-new-i32, series-sum-f64, and friends), polars provides a small, "rackety" high-level layer: series and dataframe wrapper values reached through a handful of purpose-named generic operations. The generics dispatch at runtime on the wrapper’s type, or — for the reductions — on the series’ dtype (read via dtype).
2.1 Series
A series wraps a typed column and prints in the REPL the way Polars prints it; series? is its predicate. (The underlying foreign pointer is an implementation detail and not part of the public series API.)
procedure
(series->string s) → string?
s : series?
value
polars-null : any/c
procedure
(polars-null? v) → boolean?
v : any/c
procedure
s : has-dtype?
procedure
x : sized?
procedure
s : has-null-count?
procedure
(sum v ...) → any/c
v : any/c
procedure
(mean v ...) → any/c
v : any/c
procedure
(min v ...) → any/c
v : any/c
procedure
(max v ...) → any/c
v : any/c
procedure
s : series? new-name : string?
procedure
s : series? new-name : string?
procedure
s : series?
procedure
(series-clone s) → series?
s : series?
2.1.1 dtype promotion
Reductions follow a simple, predictable rule. The widening order, narrow to wide, is
'int8 < 'int16 < 'int32 < 'int64
'uint8 < 'uint16 < 'uint32 < 'uint64
any integer < 'float32 < 'float64
sum, min and max preserve the input dtype. mean promotes to 'float64. Use series-cast to change a series’ dtype explicitly.
2.1.2 Low-level Series API
The generic layer is built on monomorphic, dtype-suffixed bindings that operate directly on the foreign series. They remain exported. A series wrapper is accepted anywhere one of them expects a series (the wrapper marshals transparently, and satisfies Series-ptr?), but what they return is the raw foreign pointer, not a wrapper — so the results do not print in Polars’ format and do not answer to series?. Prefer series and the generic operations above; reach for these when you need a specific dtype or a specific typed result.
procedure
(Series-ptr? v) → boolean?
v : any/c
procedure
(series-new-i8 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-i16 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-i32 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-i64 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-u8 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-u16 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-u32 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-u64 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-f32 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-f64 name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-bool name values) → Series-ptr?
name : string? values : list?
procedure
(series-new-str name values) → Series-ptr?
name : string? values : list?
procedure
(series-sum-i32 s) → (or/c exact-integer? #f)
s : Series-ptr?
procedure
(series-min-i32 s) → (or/c exact-integer? #f)
s : Series-ptr?
procedure
(series-max-i32 s) → (or/c exact-integer? #f)
s : Series-ptr?
procedure
(series-mean-i32 s) → (or/c flonum? #f)
s : Series-ptr?
procedure
(series-sum-f64 s) → (or/c flonum? #f)
s : Series-ptr?
procedure
(series-min-f64 s) → (or/c flonum? #f)
s : Series-ptr?
procedure
(series-max-f64 s) → (or/c flonum? #f)
s : Series-ptr?
procedure
(series-mean-f64 s) → (or/c flonum? #f)
s : Series-ptr?
procedure
(series-cast s dtype) → Series-ptr?
s : Series-ptr? dtype : (or/c symbol? pair?)
2.2 DataFrames
A dataframe is a collection of equal-length named series. Like a series it is a wrapper value (dataframe?) carrying the column data; it prints as a Polars table, so display (or ~a, or the REPL) renders it with no separate display call.
procedure
(dataframe? v) → boolean?
v : any/c
procedure
(dataframe columns) → dataframe?
columns : (listof series?)
procedure
(shape x) → (listof exact-nonnegative-integer?)
x : has-shape?
procedure
(shape/values x) →
exact-nonnegative-integer? ... x : has-shape?
procedure
d : dataframe?
procedure
d : dataframe?
procedure
(column-names d) → (listof string?)
d : dataframe?
procedure
(column-name d i) → string?
d : dataframe? i : exact-nonnegative-integer?
procedure
(ref x [key #:columns columns #:rows rows]) → any/c
x : has-ref? key : (or/c exact-nonnegative-integer? string?) = absent
columns :
(or/c exact-nonnegative-integer? string? (listof (or/c exact-nonnegative-integer? string?))) = absent rows : any/c = absent
procedure
(describe x) → dataframe?
x : (or/c series? dataframe?)
2.2.1 Low-level DataFrame API
The generic layer above is built on a set of monomorphic dataframe-* bindings that operate directly on the foreign dataframe. They remain exported and accept the dataframe wrapper (it marshals transparently); the generic operations are simply the preferred surface.
procedure
(dataframe-new columns) → dataframe?
columns : (listof series?)
procedure
(dataframe-shape d) →
exact-nonnegative-integer? exact-nonnegative-integer? d : dataframe?
procedure
d : dataframe?
procedure
d : dataframe?
procedure
(dataframe-column d name) → series?
d : dataframe? name : string?
procedure
(dataframe-column-name d i) → string?
d : dataframe? i : exact-nonnegative-integer?
procedure
(dataframe-column-names d) → (listof string?)
d : dataframe?
procedure
(dataframe-select d names) → dataframe?
d : dataframe? names : (listof string?)
procedure
(display-dataframe d [out]) → void?
d : dataframe? out : output-port? = (current-output-port)
procedure
(DataFrame-ptr? v) → boolean?
v : any/c
procedure
(dataframe-vstack top bottom) → DataFrame-ptr?
top : DataFrame-ptr? bottom : DataFrame-ptr?
2.2.2 Reading & writing
procedure
(dataframe-write-csv d path) → void?
d : dataframe? path : path-string?
procedure
(dataframe-read-csv path) → dataframe?
path : path-string?
procedure
(dataframe-write-parquet d path) → void?
d : dataframe? path : path-string?
procedure
(dataframe-read-parquet path) → dataframe?
path : path-string?
procedure
(dataframe-write-json-lines d path) → void?
d : dataframe? path : path-string?
procedure
(dataframe-read-json-lines path) → dataframe?
path : path-string?
2.3 Expressions
An expression describes a column computation — a column reference, a literal, or an operation over other expressions — without running it. The same expression can be reused across the select, with_columns, filter and group_by/agg contexts, exactly as in Polars, and is evaluated only when a context runs it against a frame. Expressions are foreign values recognised by Expr-ptr?.
The bindings below are the monomorphic expr-* layer. Most of them have a generic counterpart in Fluent pipelines — expr-gt underlies >, expr-sum underlies the expression arm of sum, expr-alias underlies alias — and the generic spelling is the preferred one; the expr-* names are useful when a name would otherwise be shadowed, or when you want to be explicit that an expression is being built.
procedure
name : string?
procedure
v : (or/c boolean? exact-integer? real? string?)
procedure
(expr-alias e name) → Expr-ptr?
e : Expr-ptr? name : string?
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
a : any/c b : any/c
procedure
e : Expr-ptr?
procedure
e : Expr-ptr?
procedure
e : Expr-ptr?
procedure
e : Expr-ptr?
procedure
e : Expr-ptr?
procedure
(expr-median e) → Expr-ptr?
e : Expr-ptr?
procedure
(expr-count e) → Expr-ptr?
e : Expr-ptr?
procedure
(expr-n-unique e) → Expr-ptr?
e : Expr-ptr?
procedure
(expr-first e) → Expr-ptr?
e : Expr-ptr?
procedure
e : Expr-ptr?
procedure
e : Expr-ptr? ddof : exact-nonnegative-integer? = 1
procedure
e : Expr-ptr? ddof : exact-nonnegative-integer? = 1
2.3.1 Eager expression contexts
These run expressions against a dataframe and return a new frame in one step. Each is the eager convenience over the corresponding lazy operation in Lazy frames: it converts with dataframe-lazy, applies the operation, and lazyframe-collects. Like the rest of the low-level layer they accept a dataframe wrapper but return a raw DataFrame-ptr?; the fluent select, with-columns, filter and group-by/agg are the wrapper-returning equivalents.
procedure
(dataframe-select-exprs df exprs) → DataFrame-ptr?
df : DataFrame-ptr? exprs : (listof Expr-ptr?)
procedure
(dataframe-with-columns df exprs) → DataFrame-ptr?
df : DataFrame-ptr? exprs : (listof Expr-ptr?)
procedure
(dataframe-filter-expr df predicate) → DataFrame-ptr?
df : DataFrame-ptr? predicate : Expr-ptr?
procedure
(dataframe-group-by-agg df keys aggs) → DataFrame-ptr?
df : DataFrame-ptr? keys : (listof (or/c string? Expr-ptr?)) aggs : (listof Expr-ptr?)
2.4 Lazy frames
A lazyframe is a query plan: a sequence of operations over a frame that Polars optimises as a whole and runs only when asked to collect. The low-level surface mirrors the eager dataframe-* bindings and, like them, returns raw foreign pointers; the fluent lazy and collect are the wrapper-returning equivalents.
procedure
(LazyFrame-ptr? v) → boolean?
v : any/c
procedure
(lazyframe? v) → boolean?
v : any/c
procedure
(dataframe-lazy df) → LazyFrame-ptr?
df : DataFrame-ptr?
procedure
(lazyframe-collect lf) → DataFrame-ptr?
lf : LazyFrame-ptr?
procedure
(lazyframe-select lf exprs) → LazyFrame-ptr?
lf : LazyFrame-ptr? exprs : (listof Expr-ptr?)
procedure
(lazyframe-with-columns lf exprs) → LazyFrame-ptr?
lf : LazyFrame-ptr? exprs : (listof Expr-ptr?)
procedure
(lazyframe-filter lf predicate) → LazyFrame-ptr?
lf : LazyFrame-ptr? predicate : Expr-ptr?
procedure
(lazyframe-group-by-agg lf keys aggs) → LazyFrame-ptr?
lf : LazyFrame-ptr? keys : (listof (or/c string? Expr-ptr?)) aggs : (listof Expr-ptr?)
procedure
(lazyframe-join left right [ #:on on #:left-on left-on #:right-on right-on #:how how]) → LazyFrame-ptr? left : LazyFrame-ptr? right : LazyFrame-ptr? on : (or/c #f (listof string?)) = #f left-on : (or/c #f (listof string?)) = #f right-on : (or/c #f (listof string?)) = #f how : (or/c 'inner 'left 'outer 'full 'cross) = 'inner
(lazyframe-collect (lazyframe-join (dataframe-lazy users) (dataframe-lazy orders) #:on '("uid") #:how 'inner))
2.5 Fluent pipelines
A data-first layer that mirrors Polars’ Python method chaining. Because each operation takes the frame as its first argument, a pipeline reads as a thread-first ~> chain (re-provided from threading, so (require polars) is enough):
(~> df (filter (> (col "value") 15)) (group-by "group") (agg (alias (sum (col "value")) "sum_value")))
procedure
(> a b ...) → any/c
a : any/c b : any/c
procedure
(< a b ...) → any/c
a : any/c b : any/c
procedure
(>= a b ...) → any/c
a : any/c b : any/c
procedure
(<= a b ...) → any/c
a : any/c b : any/c
procedure
(= a b ...) → any/c
a : any/c b : any/c
procedure
(!= a b ...) → any/c
a : any/c b : any/c
syntax
(and expr ...)
syntax
(or expr ...)
procedure
(not x) → any/c
x : any/c
procedure
(xor a b) → any/c
a : any/c b : any/c
procedure
(+ v ...) → any/c
v : any/c
procedure
(- v ...) → any/c
v : any/c
procedure
(* v ...) → any/c
v : any/c
procedure
(/ v ...) → any/c
v : any/c
procedure
(filter d predicate) → dataframe?
d : dataframe? predicate : any/c
procedure
(sort d names [#:descending descending]) → dataframe?
d : dataframe? names : (or/c string? (listof string?)) descending : (or/c boolean? (listof boolean?)) = #f
procedure
(select d spec ...) → (or/c dataframe? lazyframe?)
d : (or/c dataframe? lazyframe?) spec : any/c
procedure
(with-columns d spec ...) → (or/c dataframe? lazyframe?)
d : (or/c dataframe? lazyframe?) spec : any/c
procedure
(vstack top bottom) → dataframe?
top : dataframe? bottom : dataframe?
procedure
(lazy d) → lazyframe?
d : dataframe?
procedure
(collect lf) → dataframe?
lf : lazyframe?
procedure
d : dataframe? key : (or/c string? any/c)
procedure
(agg g agg-expr ...) → dataframe?
g : grouped? agg-expr : any/c
procedure
v : any/c
procedure
(count x) → any/c
x : any/c
procedure
(n-unique x) → any/c
x : any/c
procedure
(median x) → any/c
x : any/c
procedure
(std x [#:ddof ddof]) → any/c
x : any/c ddof : exact-nonnegative-integer? = 1
procedure
(var x [#:ddof ddof]) → any/c
x : any/c ddof : exact-nonnegative-integer? = 1
procedure
(alias e name) → any/c
e : any/c name : string?
procedure
(first x) → any/c
x : (or/c string? pair? any/c)
procedure
(last x) → any/c
x : (or/c string? pair? any/c)
Name clash. racket/list also exports first and last (along with count and group-by, which polars exports too). Requiring both modules explicitly — (require racket/list polars) — is an error (identifier already required). A plain #lang racket/base program is unaffected, because racket/base does not export these names. See Shadowed bindings for how to take control.
2.5.1 Shadowed bindings
(require polars) re-exports a handful of generic operations whose names also live in racket/base (min, max, sort, filter, >, <, >=, <=, =) and in racket/list (first, last, count, group-by). Under #lang racket/base this is seamless — these names are either not bound (so polars simply provides them) or bound only by the module language (which an explicit require silently shadows), and the polars versions intentionally fall back to the numeric/list behaviour for non-frame arguments.
A conflict arises only when another module providing the same name is also required explicitly — most commonly racket/list. Resolve it with the usual require sub-forms:
; keep polars' first/last/count/group-by, drop racket/list's: (require (except-in racket/list first last count group-by) polars) ; keep racket/list's, reach polars' under a prefix: (require racket/list (prefix-in pl: polars)) ; then (pl:first (col "v")) for the Expr, (first '(1 2 3)) for the list ; keep polars', reach racket/list's under a prefix: (require polars (prefix-in list: racket/list))
2.6 Generic interfaces
The high-level operations are small, purpose-named racket/generic interfaces. A wrapper implements the interface for each capability it has — a series and a dataframe both have a len and a shape, so both implement gen:sized and gen:has-shape; only a series has a dtype. Each interface exports its method(s) and a predicate that recognises values implementing it.
syntax
procedure
v : any/c
syntax
procedure
(has-shape? v) → boolean?
v : any/c
syntax
procedure
(has-dtype? v) → boolean?
v : any/c
syntax
procedure
(has-null-count? v) → boolean?
v : any/c