Series
Series is an eagerly-evaluated, single-typed column. It is the building block of DataFrame and can also be returned from main() (converted to a single-column result set).
Unlike the lazy Expr, operations on Series are computed immediately.
Construction
Series(name, values=None, dtype=None, *, strict=True, nan_to_null=False)
# or omit the name
Series(values, name=None, dtype=None)
Series("value", [10, 20, 30])
Series([1.0, 2.0, 3.0], name="price")
Properties
| Property | Type | Description |
|---|---|---|
name | str | Column name (defaults to "series" when not given) |
dtype | DataType | Logical data type |
Conversion & Cleaning
| Method | Description |
|---|---|
s.to_list() | Convert to Python list (null → None) |
s.cast(dtype) | Cast to another dtype (strict — raises on failure) |
s.abs() | Element-wise absolute value |
s.round(ndigits=0) | Round to ndigits decimal places |
s.fill_null(value) | Replace null with scalar value (None is a no-op) |
s.is_null() / s.is_not_null() | Return boolean Series marking null / non-null |
s.filter(mask) | Keep elements where boolean mask is true |
s.alias(name) / s.rename(name) | Return a renamed copy |
Aggregation
The following methods return a single scalar value:
| Method | Description |
|---|---|
s.sum() | Sum of all non-null values |
s.mean() | Arithmetic mean |
s.min() / s.max() | Minimum / maximum non-null value |
s.median() | Median |
s.std() / s.var() | Sample standard deviation / variance |
s.count() | Count of non-null values |
s.n_unique() | Count of distinct values (null counts as one distinct value) |
s.first() / s.last() | First / last value |
s.skew(bias=True) | Sample skewness (bias=True gives population moment estimator) |
s.kurtosis(fisher=True, bias=True) | Kurtosis (fisher=True gives excess kurtosis) |
s.mode() | Most frequently occurring value(s), returns Series (may be multiple) |
s.quantile(q, interpolation="nearest") | Value at the given quantile (0..1); only "nearest" interpolation |
Rolling Windows
Sliding window calculations over a fixed-size window, returning Series:
| Method | Description |
|---|---|
s.rolling_min(window_size, *, min_samples, center) | Rolling minimum |
s.rolling_max(window_size, *, min_samples, center) | Rolling maximum |
s.rolling_sum(window_size, *, min_samples, center) | Rolling sum |
s.rolling_mean(window_size, *, min_samples, center) | Rolling arithmetic mean |
s.rolling_median(window_size, *, min_samples, center) | Rolling median |
s.rolling_std(window_size, *, min_samples, center, ddof=1) | Rolling sample std |
s.rolling_var(window_size, *, min_samples, center, ddof=1) | Rolling sample variance |
s.rolling_skew(window_size, *, bias, min_samples, center) | Rolling skewness |
s.rolling_kurtosis(window_size, *, fisher, bias, min_samples, center) | Rolling kurtosis |
s.rolling_quantile(q, window_size=2, *, min_samples, center) | Rolling quantile ("nearest" only) |
s.rolling_map(function, window_size, *, min_samples, center) | Apply function(Series) to each window, taking its scalar return |
# 7-day rolling mean
s.rolling_mean(7)
# With minimum samples
s.rolling_sum(7, min_samples=3)
Rolling By (Indexed Windows)
Variable-length windows based on another Series (typically a time column, assumed sorted ascending). Windows are defined by duration strings (e.g. "2d", "1h"):
| Method | Description |
|---|---|
s.rolling_min_by(by, window, *, min_samples, closed) | Rolling minimum by index |
s.rolling_max_by(by, window, *, min_samples, closed) | Rolling maximum by index |
s.rolling_sum_by(by, window, *, min_samples, closed) | Rolling sum by index |
s.rolling_mean_by(by, window, *, min_samples, closed) | Rolling mean by index |
s.rolling_median_by(by, window, *, min_samples, closed) | Rolling median by index |
s.rolling_std_by(by, window, *, min_samples, closed, ddof=1) | Rolling std by index |
s.rolling_var_by(by, window, *, min_samples, closed, ddof=1) | Rolling variance by index |
closed controls window boundary: "left" / "right" / "both" / "none", default "right".
# 2-day rolling mean based on time column
s.rolling_mean_by(time_series, "2d")
Exponentially Weighted Moving (EWM)
Provide exactly one of com / span / half_life / alpha to specify the decay parameter:
| Method | Description |
|---|---|
s.ewm_mean(*, com/span/half_life/alpha, adjust, min_samples, ignore_nulls) | EWM average |
s.ewm_sum(*, com/span/half_life/alpha, adjust, min_samples, ignore_nulls) | EWM sum |
s.ewm_var(*, com/span/half_life/alpha, adjust, min_samples, ignore_nulls, bias) | EWM variance |
s.ewm_std(*, com/span/half_life/alpha, adjust, min_samples, ignore_nulls, bias) | EWM std |
s.ewm_mean(span=7)
s.ewm_std(half_life=3)
Transformations & Sorting
| Method | Description |
|---|---|
s.diff(n=1) | Difference from the value n positions before |
s.cum_sum(*, reverse=False) | Cumulative sum (reverse=True accumulates from the end) |
s.cum_prod(*, reverse=False) | Cumulative product |
s.pct_change(n=1) | Percentage change from n positions before, returns Float64 |
s.sort(*, descending=False, nulls_last=False) | Sort by value (stable), nulls first by default |
s.forward_fill(limit=None) | Fill nulls with the previous non-null value (limit caps consecutive fills) |
s.backward_fill(limit=None) | Fill nulls with the next non-null value |
s.unique(*, maintain_order=False) | Distinct values after deduplication |
s.shift(n=1, *, fill_value) | Shift by n positions (positive = down), vacated positions become fill_value (default null) |
s.interpolate(method="linear") | Linear interpolation for nulls ("linear" only) |
Selection
| Method | Description |
|---|---|
s.head(n=5) | First n rows (negative n drops the last |n| rows) |
s.tail(n=5) | Last n rows (negative n drops the first |n| rows) |
s.slice(offset, length=None) | Rows from offset (can be negative) for length rows (None = to end) |
s.gather_every(n, offset=0) | Every n-th row, starting at offset |
s.sample(n=None, *, fraction, with_replacement, shuffle, seed) | Random sample (n or fraction, not both) |
s.top_k(k=5) | k largest values |
s.bottom_k(k=5) | k smallest values |
Mapping
| Method | Description |
|---|---|
s.replace_strict(old, new, *, default, return_dtype) | Strict replace: values in old → corresponding new; unmatched → default |
s.value_counts(*, sort, name, normalize) | Value frequency counts, returns two-column DataFrame (value column + "count" column) |
s.map_elements(function, return_dtype=None, skip_nulls=True) | Apply a Python callback to each element, returning a new Series |
# Element-wise mapping
s.map_elements(lambda x: x * 2 if isinstance(x, (int, float)) else x)
# Value counts
s.value_counts(sort=True)
Indexing & Length
len(s) # Number of elements
s[0] # Value at the given index (supports negative indices)
Operators
Series overloads the full set of arithmetic, comparison, and logical operators, all returning new Series:
- Arithmetic:
+-*///%** - Comparison:
==!=<<=>>=(return boolean Series) - Logical:
&|~
def main():
s = Series("value", [1, -2, 3, -4])
positive = s.filter(s > 0) # comparison produces boolean mask, then filter
return positive # Series([1, 3])