From 0ad6935d800a2b3e2b12afef3dff910939b39721 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 13:55:44 +0000 Subject: [PATCH 01/17] Initial plan From fa0422b05191f57d988e6d2eab78b66e97b75529 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:04:18 +0000 Subject: [PATCH 02/17] Rewrite value_counts.html to use interactive playground format Convert from static code blocks to the standard interactive playground template with editable textareas, run/reset buttons, loading overlay, dark theme, and playground-runtime.js integration. All 6 code examples are self-contained with proper imports and console.log() output. The API reference section is kept as a non-interactive reference block. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/index.html | 102 ++++---- playground/value_counts.html | 440 +++++++++++++++++++++++++++-------- 2 files changed, 395 insertions(+), 147 deletions(-) diff --git a/playground/index.html b/playground/index.html index 73ab3f0e..48bfbcb9 100644 --- a/playground/index.html +++ b/playground/index.html @@ -135,133 +135,133 @@

📐 Project Foundation

✅ Complete
-

📊 Series

-

1-D labeled array — Interactive Playground. The core building block of tsb data structures.

+

📊 Series

+

1-D labeled array. The core building block of tsb data structures.

✅ Complete
-

🗃️ DataFrame

-

2-D labeled table — interactive tutorial. Column-oriented storage, full pandas API.

+

🗃️ DataFrame

+

2-D labeled table. Column-oriented storage, full pandas API.

✅ Complete
-

🏷️ Index

-

Immutable labeled axis — Interactive Playground, RangeIndex.

+

🏷️ Index

+

Immutable labeled axis, RangeIndex.

✅ Complete
-

🔢 Dtypes

-

Rich dtype system — Interactive Playground. int/float/bool/string/datetime/category.

+

🔢 Dtypes

+

Rich dtype system. int/float/bool/string/datetime/category.

✅ Complete
-

🔀 GroupBy

-

Split-apply-combine — interactive tutorial. groupby, agg, transform, apply, filter.

+

🔀 GroupBy

+

Split-apply-combine. groupby, agg, transform, apply, filter.

✅ Complete
-

🔗 concat

-

Combine Series and DataFrames — interactive tutorial. axis=0/1, outer/inner join, ignoreIndex.

+

🔗 concat

+

Combine Series and DataFrames. axis=0/1, outer/inner join, ignoreIndex.

✅ Complete
-

🔀 merge

-

SQL-style DataFrame joins — interactive tutorial. inner/left/right/outer, on/left_on/right_on, suffixes.

+

🔀 merge

+

SQL-style DataFrame joins. inner/left/right/outer, on/left_on/right_on, suffixes.

✅ Complete
-

🔡 str accessor

-

Vectorised string operations — interactive tutorial. lower/upper/strip/pad/contains/replace/split/extract & predicates.

+

🔡 str accessor

+

Vectorised string operations. lower/upper/strip/pad/contains/replace/split/extract & predicates.

✅ Complete
-

📅 dt accessor

-

Vectorised datetime operations — interactive tutorial. Calendar components, boolean boundaries, strftime, floor/ceil/round.

+

📅 dt accessor

+

Vectorised datetime operations. Calendar components, boolean boundaries, strftime, floor/ceil/round.

✅ Complete
-

📊 describe

-

Summary statistics — interactive tutorial. count/mean/std/min/percentiles/max for numeric; count/unique/top/freq for categorical. Series.quantile().

+

📊 describe

+

Summary statistics. count/mean/std/min/percentiles/max for numeric; count/unique/top/freq for categorical. Series.quantile().

✅ Complete
-

📥 I/O

-

CSV I/O — interactive tutorial. readCsv / toCsv with dtype inference, NA handling, quoted fields, custom separators.

+

📥 I/O

+

CSV I/O. readCsv / toCsv with dtype inference, NA handling, quoted fields, custom separators.

✅ Complete
-

📥 JSON I/O

-

JSON I/O — interactive tutorial. readJson / toJson with five orient formats: records, split, index, columns, values.

+

📥 JSON I/O

+

JSON I/O. readJson / toJson with five orient formats: records, split, index, columns, values.

✅ Complete
-

📈 corr & cov

-

Pearson correlation & covariance — interactive tutorial. Series.corr(), DataFrame.corr(), DataFrame.cov(), dataFrameCorr(), dataFrameCov() with index alignment, null handling, and configurable ddof/minPeriods.

+

📈 corr & cov

+

Pearson correlation & covariance. Series.corr(), DataFrame.corr(), DataFrame.cov(), dataFrameCorr(), dataFrameCov() with index alignment, null handling, and configurable ddof/minPeriods.

✅ Complete
-

🪟 rolling

-

Sliding-window aggregations — interactive tutorial. Series.rolling() and DataFrame.rolling() with mean, sum, std, var, min, max, count, median, apply. Supports minPeriods and centered windows.

+

🪟 rolling

+

Sliding-window aggregations. Series.rolling() and DataFrame.rolling() with mean, sum, std, var, min, max, count, median, apply. Supports minPeriods and centered windows.

✅ Complete

📈 expanding

-

Growing-window aggregations — Series.expanding() and DataFrame.expanding() with mean, sum, std, var, min, max, count, median, apply. Window grows from start to current position.

+

Growing-window aggregations. Series.expanding() and DataFrame.expanding() with mean, sum, std, var, min, max, count, median, apply. Window grows from start to current position.

✅ Complete
-

🏷️ cat accessor

-

Categorical operations — interactive tutorial. Series.cat with categories, codes, ordered, addCategories, removeCategories, renameCategories, setCategories, reorderCategories, valueCounts.

+

🏷️ cat accessor

+

Categorical operations. Series.cat with categories, codes, ordered, addCategories, removeCategories, renameCategories, setCategories, reorderCategories, valueCounts.

✅ Complete
-

📉 ewm

-

Exponentially Weighted Moving aggregations — interactive tutorial. Series.ewm() and DataFrame.ewm() with mean, std, var, cov, corr, apply. Decay via span, com, halflife, or alpha. Supports adjust and ignoreNa.

+

📉 ewm

+

Exponentially Weighted Moving aggregations. Series.ewm() and DataFrame.ewm() with mean, std, var, cov, corr, apply. Decay via span, com, halflife, or alpha. Supports adjust and ignoreNa.

✅ Complete
-

🔀 melt

-

Wide-to-long reshape — interactive tutorial. Unpivot columns into variable/value pairs with id_vars, value_vars, var_name, value_name.

+

🔀 melt

+

Wide-to-long reshape. Unpivot columns into variable/value pairs with id_vars, value_vars, var_name, value_name.

✅ Complete
-

🔄 pivot & pivotTable

-

Reshape with aggregation — interactive tutorial. pivot() for unique reshaping; pivotTable() for aggregation (mean/sum/count/min/max/first/last) with fill_value and dropna support.

+

🔄 pivot & pivotTable

+

Reshape with aggregation. pivot() for unique reshaping; pivotTable() for aggregation (mean/sum/count/min/max/first/last) with fill_value and dropna support.

✅ Complete
-

📐 stack & unstack

-

Pivot column labels to/from row index — interactive tutorial. stack() rotates columns into a compound-index Series; unstack() recovers the DataFrame. Custom sep, dropna, and fill_value support.

+

📐 stack & unstack

+

Pivot column labels to/from row index. stack() rotates columns into a compound-index Series; unstack() recovers the DataFrame. Custom sep, dropna, and fill_value support.

✅ Complete
-

🏆 rank

-

Assign numerical ranks to values — interactive tutorial. rankSeries() and rankDataFrame() with tie methods (average/min/max/first/dense), NaN handling (keep/top/bottom), percentage ranks, and axis support.

+

🏆 rank

+

Assign numerical ranks to values. rankSeries() and rankDataFrame() with tie methods (average/min/max/first/dense), NaN handling (keep/top/bottom), percentage ranks, and axis support.

✅ Complete
-

🔝 nlargest / nsmallest

-

Return the n largest or smallest values — interactive tutorial. nlargestSeries(), nsmallestSeries(), nlargestDataFrame(), nsmallestDataFrame() with keep='first'/'last'/'all' tie-handling, NaN exclusion, and multi-column DataFrame sorting.

+

🔝 nlargest / nsmallest

+

Return the n largest or smallest values. nlargestSeries(), nsmallestSeries(), nlargestDataFrame(), nsmallestDataFrame() with keep='first'/'last'/'all' tie-handling, NaN exclusion, and multi-column DataFrame sorting.

✅ Complete
-

📈 cumulative operations

-

Compute running totals, products, maxima, and minima — interactive tutorial. cumsum(), cumprod(), cummax(), cummin() for Series and DataFrame with skipna support and axis=0/1.

+

📈 cumulative operations

+

Compute running totals, products, maxima, and minima. cumsum(), cumprod(), cummax(), cummin() for Series and DataFrame with skipna support and axis=0/1.

✅ Complete
-

✂️ element-wise ops

-

Element-wise transformations — interactive tutorial. clip(), seriesAbs(), seriesRound() for Series and DataFrame with min/max bounds, decimal precision, and axis support.

+

✂️ element-wise ops

+

Element-wise transformations. clip(), seriesAbs(), seriesRound() for Series and DataFrame with min/max bounds, decimal precision, and axis support.

✅ Complete
-

🔢 value_counts

-

Count unique values — interactive tutorial. valueCounts() for Series and dataFrameValueCounts() for DataFrame with normalize, sort, ascending, and dropna options.

+

🔢 value_counts

+

Count unique values. valueCounts() for Series and dataFrameValueCounts() for DataFrame with normalize, sort, ascending, and dropna options.

✅ Complete
-

🗂️ MultiIndex

-

Hierarchical indexing — interactive tutorial. MultiIndex for multi-level row and column labels with fromArrays, fromTuples, fromProduct, level access, and swapLevels.

+

🗂️ MultiIndex

+

Hierarchical indexing. MultiIndex for multi-level row and column labels with fromArrays, fromTuples, fromProduct, level access, and swapLevels.

✅ Complete
diff --git a/playground/value_counts.html b/playground/value_counts.html index 35d7abe8..2f9e5a7b 100644 --- a/playground/value_counts.html +++ b/playground/value_counts.html @@ -1,99 +1,317 @@ - + - - - - tsb — value_counts - - - -

tsb — value_counts

-

- Count unique values in a Series or unique row combinations in a - DataFrame. Mirrors - pandas.Series.value_counts() - and - pandas.DataFrame.value_counts(). -

+ + + + tsb — value_counts + + + +
+
+
Initializing playground…
+
+ ← Back to roadmap +

📊 value_counts — Interactive Playground

+

Count unique values in a Series or unique row + combinations in a DataFrame. Mirrors + pandas.Series.value_counts() and + pandas.DataFrame.value_counts().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ +

1 · Basic usage (Series)

-
import { Series } from "tsb";
-import { valueCounts } from "tsb";
+    

Create a Series and count how often each unique value appears. Results are sorted + descending by frequency by default.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +

2 · Normalize — return proportions

-
const pct = valueCounts(s, { normalize: true });
-// values → [0.5, 0.333…, 0.167…]   (must sum to 1)
-
apple=0.50 banana=0.33 cherry=0.17
+

Pass normalize: true to get relative frequencies that sum to 1 + instead of raw counts.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ +

3 · Sort order

-
// Ascending order (least frequent first)
+    

Control sorting: ascending: true for least-frequent first, or + sort: false to preserve insertion order.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ +

4 · Missing-value handling

-
const sWithNull = new Series({ data: ["a", null, "b", null, "a"] });
+    

By default nulls are excluded (dropna: true). Set + dropna: false to include them in the count.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ +

5 · DataFrame value_counts

-
import { DataFrame } from "tsb";
-import { dataFrameValueCounts } from "tsb";
+    

Count unique row combinations across all columns. Each unique + (city, temp) pair becomes an index label.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ +

6 · DataFrame subset

-
// Restrict to a subset of columns
-const vc2 = dataFrameValueCounts(df, { subset: ["city"] });
-// Only counts by city: NYC=3, LA=1
-
NYC=3 LA=1
+

Restrict counting to a subset of columns with the subset option.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

The result Series is indexed by the unique values (or composite + "v1|v2|…" strings for DataFrames). Use .index.values and + .values to inspect the labels and counts respectively.

+
// Series
 valueCounts(series, {
-  normalize?: boolean,   // default false — return proportions instead of counts
+  normalize?: boolean,   // default false — return proportions
   sort?:      boolean,   // default true  — sort by frequency
-  ascending?: boolean,   // default false — highest count first when sort=true
+  ascending?: boolean,   // default false — highest count first
   dropna?:    boolean,   // default true  — exclude missing values
 }): Series<number>
 
@@ -132,13 +379,14 @@ 

7 · API reference

ascending?: boolean, dropna?: boolean, }): Series<number>
+
-
- Note: The result Series is indexed by the unique values (or composite - "v1|v2|…" strings for DataFrames). Use .index.values and - .values to inspect the labels and counts respectively. -
- -

Back to feature list

- + + + From 7403135cba87b9b6a825d672643e7e7c56028120 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:07:50 +0000 Subject: [PATCH 03/17] Rewrite cat_accessor playground to interactive dark-theme format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert all 8 example sections from static
 blocks to
interactive 
with editable +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ -
-

2 — Nulls are encoded as -1

-

Missing values (null) are not counted as categories and get a code of -1.

-
import { Series } from "tsb";
+  
+  
+

2 · Nulls are encoded as -1

+

Missing values (null) are not counted as categories and get a + code of -1.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

3 — Add and remove categories

-

Use addCategories() to register new labels (without needing them in the data yet) - and removeCategories() to drop labels (values become null).

-
import { Series } from "tsb";
+  
+  
+

3 · Add and remove categories

+

Use addCategories() to register new labels (without needing them in the + data yet) and removeCategories() to drop labels (values become null).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · Remove unused categories

+

removeUnusedCategories() drops any categories not present in the data.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

5 — Rename categories

-

Pass an object mapping old names → new names, or an array of replacement names.

-
import { Series } from "tsb";
+  
+  
+

5 · Rename categories

+

Pass an object mapping old names → new names, or an array of replacement names.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

6 · Set and reorder categories

+

setCategories() replaces the entire category list (values not in the new + list become null). reorderCategories() changes the order without adding + or removing.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

7 — Value counts per category

-

valueCounts() returns a Series with count of each category (zero for unused ones).

-
import { Series } from "tsb";
+  
+  
+

7 · Value counts per category

+

valueCounts() returns a Series with the count of each category + (zero for unused ones).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

8 · Ordered categories

+

asOrdered() marks a categorical as ordered (enabling comparisons). + The order is determined by the categories array index.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

The .cat accessor is available on any Series containing string or + categorical data. It provides pandas-compatible category management methods.

+
series.cat.categories    // Index of sorted unique labels
+series.cat.codes         // Series<number> of integer codes (-1 for null)
+series.cat.nCategories   // number of distinct categories
+series.cat.ordered       // boolean — is the categorical ordered?
+
+series.cat.addCategories(newCats: string[]): Series
+series.cat.removeCategories(cats: string[]): Series
+series.cat.removeUnusedCategories(): Series
+series.cat.renameCategories(mapping: Record | string[]): Series
+series.cat.setCategories(cats: string[]): Series
+series.cat.reorderCategories(cats: string[], ordered?: boolean): Series
+series.cat.asOrdered(): Series
+series.cat.asUnordered(): Series
+series.cat.valueCounts(): Series<number>
+
+ + + From a5f0b035cc40f39b1fad4d8111ca1ff113761a12 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:10:27 +0000 Subject: [PATCH 04/17] Rewrite cum_ops.html to use interactive playground format Convert from static pre/code blocks with light theme to the proper interactive playground template matching value_counts.html: - Dark theme with CSS variables - Loading overlay with spinner - playground-block structure with textarea editors - Run/Reset buttons and Ctrl+Enter hint - API reference section - Footer with back link All 8 original example sections preserved with self-contained, runnable code blocks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/cum_ops.html | 502 ++++++++++++++++++++++++++++++---------- 1 file changed, 375 insertions(+), 127 deletions(-) diff --git a/playground/cum_ops.html b/playground/cum_ops.html index 7f5bac20..b9f5e7c5 100644 --- a/playground/cum_ops.html +++ b/playground/cum_ops.html @@ -4,104 +4,304 @@ tsb — cumulative operations - - -

cumulative operations

-

- Compute running totals, products, maxima, and minima — - mirrors pandas.Series.cumsum() / cumprod() / cummax() / cummin(). -

- -
-

1 — cumsum: running total

-

- cumsum(series) returns a new Series where each value is the sum of all preceding - values plus the current one. Mirrors pandas.Series.cumsum(). +

+
+
Initializing playground…
+
+ ← Back to roadmap +

📈 cumulative operations — Interactive Playground

+

Compute running totals, products, maxima, and minima. Mirrors + pandas.Series.cumsum() / cumprod() / + cummax() / cummin().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser.

-
import { Series, cumsum } from "tsb";
+
+  
+  
+

1 · cumsum: running total

+

cumsum(series) returns a new Series where each value is the sum of all + preceding values plus the current one. Mirrors + pandas.Series.cumsum().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · cumprod: running product

+

cumprod(series) returns a new Series where each value is the product of all + values up to and including that position. Mirrors + pandas.Series.cumprod().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · cummax and cummin

+

cummax(series) tracks the running maximum; + cummin(series) tracks the running minimum. Both work on numbers, + strings, and booleans.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · Handling missing values (skipna)

+

By default skipna: true: missing values return + NaN/null in the result but do not + affect the running accumulator. + With skipna: false, any missing value poisons all subsequent results.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

5 · DataFrame: axis=0 (column-wise)

+

dataFrameCumsum(df) applies the operation independently to each column + (axis=0 is the default, same as pandas).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

6 · DataFrame: axis=1 (row-wise)

+

With axis: 1 (or axis: "columns"), the operation is applied + across columns for each row — each cell becomes the cumulative value of all columns + to its left plus itself.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

7 · Real-world example: portfolio tracking

+

Track the running portfolio value and the running drawdown (how far we are from the + all-time high) using cumsum and cummax.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

8 · String series: lexicographic cummax / cummin

+

cummax and cummin work on any comparable type, including + strings (lexicographic ordering).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

All cumulative functions accept a Series (or DataFrame variant) and return a new + Series/DataFrame of the same shape. The skipna option controls + missing-value handling; axis controls direction for DataFrames.

+
// Series cumulative operations
+cumsum(series, { skipna?: boolean }): Series
+cumprod(series, { skipna?: boolean }): Series
+cummax(series, { skipna?: boolean }): Series
+cummin(series, { skipna?: boolean }): Series
+
+// DataFrame cumulative operations
+dataFrameCumsum(df, { axis?: 0 | 1, skipna?: boolean }): DataFrame
+dataFrameCumprod(df, { axis?: 0 | 1, skipna?: boolean }): DataFrame
+dataFrameCummax(df, { axis?: 0 | 1, skipna?: boolean }): DataFrame
+dataFrameCummin(df, { axis?: 0 | 1, skipna?: boolean }): DataFrame
+
+ + From 64f946482d8d8b7d498a94f27976160212f31a9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:13:18 +0000 Subject: [PATCH 05/17] Rewrite elem_ops.html to use interactive playground format Convert from static pre/code blocks to interactive playground-block structure with dark theme, CSS variables, editable textareas, Run/Reset buttons, loading overlay, and proper footer matching the value_counts.html template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/elem_ops.html | 500 ++++++++++++++++++++++++++++----------- 1 file changed, 366 insertions(+), 134 deletions(-) diff --git a/playground/elem_ops.html b/playground/elem_ops.html index 2ee75db7..1ff9d3f8 100644 --- a/playground/elem_ops.html +++ b/playground/elem_ops.html @@ -4,179 +4,411 @@ tsb — element-wise operations - - -

element-wise operations

-

- Scalar transforms applied independently to each element — - mirrors pandas.Series.clip(), .abs(), and .round(). -

- -
-

1 — clip: bound values to a range

-

- clip(series, { lower, upper }) replaces any value below lower - with lower, and any value above upper with upper. - Pass only one bound to clip from one side only. - Mirrors pandas.Series.clip(). +

+
+
Initializing playground…
+
+ ← Back to roadmap +

✂️ element-wise operations — Interactive Playground

+

Scalar transforms applied independently to each element — + mirrors pandas.Series.clip(), .abs(), and + .round().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser.

-
import { Series, clip } from "tsb";
+
+  
+  
+

1 · clip: bound values to a range

+

clip(series, { lower, upper }) replaces any value below + lower with lower, and any value above + upper with upper. Pass only one bound to clip + from one side only. Mirrors pandas.Series.clip().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · clip on a DataFrame

+

dataFrameClip(df, { lower, upper }) applies the same clipping + to every numeric column. Mirrors pandas.DataFrame.clip().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · seriesAbs: absolute value

+

seriesAbs(series) returns a new Series where every element is + replaced by its absolute value. Mirrors + pandas.Series.abs().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · dataFrameAbs: absolute values for all columns

+

dataFrameAbs(df) applies abs() column-by-column. + Mirrors pandas.DataFrame.abs().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

5 · seriesRound: round to N decimal places

+

seriesRound(series, { decimals }) rounds each value to the given + number of decimal places (default 0). Negative decimals rounds + to the left of the decimal point (e.g. -1 rounds to the nearest + 10). Mirrors pandas.Series.round().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

6 · dataFrameRound: round all columns

+

dataFrameRound(df, { decimals }) rounds every numeric column of + a DataFrame. Mirrors pandas.DataFrame.round().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

7 · Missing values pass through

+

All three operations propagate null and NaN + unchanged — consistent with pandas' behaviour.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

All element-wise operations return new Series/DataFrame instances — the + originals are never mutated. Missing values (null, + NaN) pass through unchanged.

+
// Series clip
+clip(series, {
+  lower?: number,   // minimum bound (default: -Infinity)
+  upper?: number,   // maximum bound (default: +Infinity)
+}): Series<number>
+
+// DataFrame clip
+dataFrameClip(df, { lower?, upper? }): DataFrame
+
+// Series absolute value
+seriesAbs(series): Series<number>
+
+// DataFrame absolute value
+dataFrameAbs(df): DataFrame
+
+// Series round
+seriesRound(series, {
+  decimals?: number,  // default 0 — negative rounds left of decimal
+}): Series<number>
+
+// DataFrame round
+dataFrameRound(df, { decimals? }): DataFrame
+
+ + + From b54bbf623969c014a64ca054df59d78bf342dfad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:15:49 +0000 Subject: [PATCH 06/17] Rewrite melt.html playground to interactive dark-theme format Convert static
 blocks to interactive 
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+ + -
-

2 — Preserve identifier columns

-

Use id_vars to keep columns as identifiers that are repeated for each melted row.

-
import { DataFrame, melt } from "tsb";
+  
+  
+

2 · Preserve identifier columns

+

Use id_vars to keep columns as identifiers that are repeated for + each melted row.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

3 — Selective value columns

-

Use value_vars to specify which columns to unpivot.

-
import { DataFrame, melt } from "tsb";
+  
+  
+

3 · Selective value columns

+

Use value_vars to specify which columns to unpivot.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

4 — Multiple id columns

-

Pass an array to id_vars to use multiple identifier columns.

-
import { DataFrame, melt } from "tsb";
+  
+  
+

4 · Multiple id columns

+

Pass an array to id_vars to use multiple identifier columns.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
- + +
+

API Reference

+

Unpivot a DataFrame from wide to long format. Columns not specified as + id_vars or value_vars are melted into + variable / value pairs.

+
melt(df: DataFrame, options?: {
+  id_vars?:    string | string[],   // columns to keep as identifiers
+  value_vars?: string | string[],   // columns to unpivot (default: all non-id)
+  var_name?:   string,              // name for the variable column (default: "variable")
+  value_name?: string,              // name for the value column (default: "value")
+}): DataFrame
+
+ + + From 1100176ec120e1ab5af5daa7afc8de7494020377 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:18:38 +0000 Subject: [PATCH 07/17] Rewrite multi_index.html to interactive playground format Convert from static
 blocks to interactive playground with:
- Dark theme with CSS variables matching other playground pages
- Loading overlay with spinner
- 8 interactive playground-block sections with textarea editors
- Run/Reset buttons and Ctrl+Enter support
- Self-contained code blocks with proper imports
- API reference section
- Footer with project links

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com>
---
 playground/multi_index.html | 512 ++++++++++++++++++++++++++++--------
 1 file changed, 397 insertions(+), 115 deletions(-)

diff --git a/playground/multi_index.html b/playground/multi_index.html
index f5f713c6..861bb326 100644
--- a/playground/multi_index.html
+++ b/playground/multi_index.html
@@ -4,31 +4,200 @@
   
   
   tsb — MultiIndex
-  
   
 
 
-
-

MultiIndex

-

Hierarchical multi-level index — mirrors pandas.MultiIndex.

- -
-

1 — Create from tuples

-

The most common way: pass an array of label-tuples.

-
import { MultiIndex } from "tsb";
+  
+
+
Initializing playground…
+
+ ← Back to roadmap +

🗂️ MultiIndex — Interactive Playground

+

Hierarchical multi-level index — mirrors + pandas.MultiIndex. Build composite keys from tuples, arrays, + or Cartesian products and use them for advanced label-based look-ups.
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ + +
+

1 · Create from tuples

+

The most common way: pass an array of label-tuples.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · Create from arrays

+

Supply one array per level — a column-oriented alternative to + fromTuples.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · Create from Cartesian product

+

fromProduct generates every combination from a list of + iterables — very handy for experiment grids.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · Look-up by label

+

Use getLoc to find the position of a tuple. + contains for a quick existence check.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

5 · Level operations: droplevel & swaplevel

+

Restructure the level hierarchy without touching the data.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

6 · Set operations

+

union, intersection, difference — + same semantics as pandas.MultiIndex.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

7 · Sorting and deduplication

+

Sort tuples lexicographically and detect or remove duplicates.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

8 · Missing values

+

Detect and remove tuples that contain null or + undefined in any level.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

Key static constructors and instance methods on + MultiIndex.

+
// Static constructors
+MultiIndex.fromTuples(tuples, { names? }): MultiIndex
+MultiIndex.fromArrays(arrays, { names? }): MultiIndex
+MultiIndex.fromProduct(iterables, { names? }): MultiIndex
+
+// Properties
+mi.nlevels: number        // number of levels
+mi.size: number           // number of entries
+mi.names: string[]        // level names
+
+// Look-up
+mi.at(i): unknown[]                  // tuple at position
+mi.getLoc(tuple): number | number[]   // position(s) of tuple
+mi.contains(tuple): boolean          // existence check
+
+// Restructure
+mi.droplevel(level): MultiIndex | Index
+mi.swaplevel(i, j): MultiIndex
+
+// Set operations
+mi.union(other): MultiIndex
+mi.intersection(other): MultiIndex
+mi.difference(other): MultiIndex
+
+// Sorting & deduplication
+mi.sortValues(): MultiIndex
+mi.dropDuplicates(): MultiIndex
+mi.duplicated(keep?): boolean[]
+
+// Missing values
+mi.isna(): boolean[]
+mi.dropna(): MultiIndex
+
+ + + From a6861088dba2413bcb994e8557bf0be6b5f4cca0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:21:29 +0000 Subject: [PATCH 08/17] Rewrite nlargest.html to use interactive playground format Convert from static pre/code blocks with light theme to the proper interactive playground template matching value_counts.html: - Dark theme with CSS variables - Loading overlay with spinner - playground-block structure with textarea editors - Run/Reset buttons and Ctrl+Enter hint - Self-contained code examples with console.log output - API reference section and footer Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/nlargest.html | 507 ++++++++++++++++++++++++++++++--------- 1 file changed, 390 insertions(+), 117 deletions(-) diff --git a/playground/nlargest.html b/playground/nlargest.html index dea2753a..ee363892 100644 --- a/playground/nlargest.html +++ b/playground/nlargest.html @@ -4,87 +4,292 @@ tsb — nlargest / nsmallest - - -

nlargest / nsmallest

-

Return the n largest or smallest values — mirrors pandas.Series.nlargest(), Series.nsmallest(), DataFrame.nlargest(), DataFrame.nsmallest().

+
+
+
Initializing playground…
+
+ ← Back to roadmap +

🔢 nlargest / nsmallest — Interactive Playground

+

Return the n largest or smallest values — mirrors + pandas.Series.nlargest(), Series.nsmallest(), + DataFrame.nlargest(), and DataFrame.nsmallest().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

-
-

1 — Series.nlargest basics

-

nlargestSeries(s, n) returns a new Series containing the n largest values, sorted in descending order. NaN / null values are always excluded.

-
import { Series, nlargestSeries } from "tsb";
+  
+  
+

1 · Series.nlargest basics

+

nlargestSeries(s, n) returns a new Series containing the n + largest values, sorted in descending order. NaN / null values are always excluded.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

2 — Series.nsmallest basics

-

nsmallestSeries(s, n) returns the n smallest values sorted in ascending order.

-
import { Series, nsmallestSeries } from "tsb";
+  
+  
+

2 · Series.nsmallest basics

+

nsmallestSeries(s, n) returns the n smallest values sorted + in ascending order.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · The keep parameter

+

When there are ties at the selection boundary, keep controls which + ones survive: first (default), + last, or + all (may return more than n rows).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

4 — Labeled index preservation

-

The result preserves the original labels, not a reset 0-based index.

-
import { Series, nlargestSeries, nsmallestSeries } from "tsb";
+  
+  
+

4 · Labeled index preservation

+

The result preserves the original labels, not a reset 0-based index.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

5 — NaN / null handling

-

Missing values are silently excluded from both the selection and the result.

-
import { Series, nlargestSeries } from "tsb";
+  
+  
+

5 · NaN / null handling

+

Missing values are silently excluded from both the selection and the result.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

6 · DataFrame.nlargest

+

nlargestDataFrame(df, n, { columns }) returns the n rows with + the largest values in the given column(s), sorted descending. Multiple columns + provide a lexicographic tie-breaker.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

7 — DataFrame.nsmallest

-

nsmallestDataFrame(df, n, { columns }) returns the rows with the smallest values, sorted ascending.

-
import { DataFrame, nsmallestDataFrame } from "tsb";
+  
+  
+

7 · DataFrame.nsmallest

+

nsmallestDataFrame(df, n, { columns }) returns the rows with the + smallest values, sorted ascending.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

8 — Edge cases

-
import { Series, nlargestSeries, nsmallestSeries } from "tsb";
+  
+  
+

8 · Edge cases

+

Behavior when n exceeds the series length, n is zero, + all values are NaN, or values are strings.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

Both Series and DataFrame variants accept an options object for tie-breaking + and column selection.

+
// Series
+nlargestSeries(series, n, {
+  keep?: "first" | "last" | "all",  // default "first"
+}): Series
+
+nsmallestSeries(series, n, {
+  keep?: "first" | "last" | "all",  // default "first"
+}): Series
+
+// DataFrame
+nlargestDataFrame(df, n, {
+  columns: string | string[],       // column(s) to sort by
+  keep?:   "first" | "last" | "all",
+}): DataFrame
+
+nsmallestDataFrame(df, n, {
+  columns: string | string[],
+  keep?:   "first" | "last" | "all",
+}): DataFrame
+
+ + + From 998d5bc0659bb743298da8aabf0aa8ecd149aa35 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:24:10 +0000 Subject: [PATCH 09/17] Rewrite pivot.html to use interactive playground format Convert from static pre/code blocks with light theme to the standard dark-themed interactive playground template with: - CSS variables and dark theme matching other playground pages - Loading overlay with spinner - playground-block structure with textarea editors - Run/Reset buttons and Ctrl+Enter hint per block - Self-contained code examples with proper imports - API reference section and footer Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/pivot.html | 387 +++++++++++++++++++++++++++++++++--------- 1 file changed, 303 insertions(+), 84 deletions(-) diff --git a/playground/pivot.html b/playground/pivot.html index 6f7ba59c..1fc7e334 100644 --- a/playground/pivot.html +++ b/playground/pivot.html @@ -4,31 +4,200 @@ tsb — pivot & pivotTable - - -

pivot & pivotTable

-

Reshape DataFrames — mirrors pandas.DataFrame.pivot() and pandas.pivot_table().

+
+
+
Initializing playground…
+
+ ← Back to roadmap +

🔀 pivot & pivotTable — Interactive Playground

+

Reshape DataFrames — mirrors pandas.DataFrame.pivot() and + pandas.pivot_table().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

-
-

1 — pivot: basic reshape

-

pivot reshapes a DataFrame using unique values in one column as the new column headers. Requires one unique value per (row, column) pair.

-
import { DataFrame, pivot } from "tsb";
+  
+  
+

1 · pivot: basic reshape

+

pivot reshapes a DataFrame using unique values in one column as the + new column headers. Requires one unique value per (row, column) pair.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · pivot: multiple value columns

+

When values is omitted, all non-index/non-column columns are used. + Column names become valCol_colHdr.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · pivotTable: mean aggregation

+

pivotTable aggregates values when multiple rows map to the same + (index, column) cell.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

4 — pivotTable: sum with fill_value

-

Use aggfunc: "sum" to total up values per cell, and fill_value to replace missing cells.

-
import { DataFrame, pivotTable } from "tsb";
+  
+  
+

4 · pivotTable: sum with fill_value

+

Use aggfunc: "sum" to total up values per cell, and + fill_value to replace missing cells.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

5 — pivotTable: count

-

Use aggfunc: "count" to count how many rows fall into each cell.

-
import { DataFrame, pivotTable } from "tsb";
+  
+  
+

5 · pivotTable: count

+

Use aggfunc: "count" to count how many rows fall into each cell.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

pivot requires one unique value per (index, column) pair. + pivotTable aggregates when duplicates exist.

+
// Reshape without aggregation
+pivot(df, {
+  index:   string,             // column → row labels
+  columns: string,             // column → new column headers
+  values?: string,             // column → cell values (all remaining if omitted)
+}): DataFrame
+
+// Reshape with aggregation
+pivotTable(df, {
+  index:      string,          // column → row labels
+  columns:    string,          // column → new column headers
+  values:     string,          // column → cell values
+  aggfunc?:   "mean" | "sum" | "count" | "min" | "max",  // default "mean"
+  fill_value?: number,         // replace missing cells
+}): DataFrame
+
+ + + From b3a94e24eaa27529b0a3911471ffa1bfdf306d81 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:26:50 +0000 Subject: [PATCH 10/17] Rewrite playground/rank.html to use interactive playground format Convert from static
 blocks with light theme to the proper
interactive playground format matching value_counts.html:

- Dark theme with CSS variables
- Loading overlay with spinner
- Interactive playground-block with textarea editors
- Run/Reset buttons per code block
- playground-output and hint elements
- API Reference section
- Footer with navigation
- Script loaded as ES module

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com>
---
 playground/rank.html | 503 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 380 insertions(+), 123 deletions(-)

diff --git a/playground/rank.html b/playground/rank.html
index 2a1a99ec..9ac4f5d9 100644
--- a/playground/rank.html
+++ b/playground/rank.html
@@ -4,85 +4,282 @@
   
   
   tsb — rank
-  
   
 
 
-
-

rank

-

Assign numerical ranks to values — mirrors pandas.Series.rank() / pandas.DataFrame.rank().

+
+
+
Initializing playground…
+
+ ← Back to roadmap +

🏅 rank — Interactive Playground

+

Assign numerical ranks to values — mirrors + pandas.Series.rank() and + pandas.DataFrame.rank().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

-
-

1 — Basic ranking

-

By default, rankSeries uses method="average" (tied values share the average of their ranks) and ascending=true (smallest value gets rank 1).

-
import { Series, rankSeries } from "tsb";
+  
+  
+

1 · Basic ranking

+

By default, rankSeries uses method="average" + (tied values share the average of their ranks) and ascending=true + (smallest value gets rank 1).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · Tie-breaking methods

+

Five methods mirror pandas: average (default), + min, max, first, and + dense.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · Descending rank

+

Set ascending: false to give rank 1 to the largest value.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · Handling NaN/null values

+

Three strategies mirror pandas na_option: + keep (default, NaN in result), + top (nulls get lowest ranks), and + bottom (nulls get highest ranks).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

5 — Percentage rank (pct)

-

pct: true returns fractional ranks in (0, 1].

-
import { Series, rankSeries } from "tsb";
+  
+  
+

5 · Percentage rank (pct)

+

pct: true returns fractional ranks in the range (0, 1].

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

6 — DataFrame rank by column (axis=0)

-

rankDataFrame ranks each column independently by default.

-
import { DataFrame, rankDataFrame } from "tsb";
+  
+  
+

6 · DataFrame rank by column (axis=0)

+

rankDataFrame ranks each column independently by default.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

7 — DataFrame rank by row (axis=1)

-

Set axis: 1 to rank each row's values relative to each other.

-
import { DataFrame, rankDataFrame } from "tsb";
+  
+  
+

7 · DataFrame rank by row (axis=1)

+

Set axis: 1 to rank each row's values relative to each other.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

8 · Dense rank for competition rankings

+

Dense rank is useful when you want no gaps — e.g., + "1st, 2nd, 2nd, 3rd" instead of "1st, 2nd, 2nd, 4th".

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

Rank values along an axis. Use rankSeries for a single Series + and rankDataFrame for an entire DataFrame.

+
// Series
+rankSeries(series, {
+  method?:    "average" | "min" | "max" | "first" | "dense",
+  ascending?: boolean,   // default true  — smallest gets rank 1
+  naOption?:  "keep" | "top" | "bottom",
+  pct?:       boolean,   // default false — return fractional ranks
+}): Series<number>
+
+// DataFrame
+rankDataFrame(df, {
+  method?:    "average" | "min" | "max" | "first" | "dense",
+  ascending?: boolean,
+  naOption?:  "keep" | "top" | "bottom",
+  pct?:       boolean,
+  axis?:      0 | 1,    // 0 = rank each column, 1 = rank each row
+}): DataFrame
+
+ + + From 92b8f56cd15eb5566944e1c1efb3605a8c455c1c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:29:39 +0000 Subject: [PATCH 11/17] Rewrite rolling.html to interactive playground format Convert from static light-theme pre/code blocks to the standard dark-theme interactive playground template with: - CSS variables and dark theme matching other playground pages - Loading overlay with spinner - playground-block structure with textarea editors - Run/Reset buttons per code block - playground-runtime.js loaded as module - API reference section and footer Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/rolling.html | 548 +++++++++++++++++++++++++++------------- 1 file changed, 373 insertions(+), 175 deletions(-) diff --git a/playground/rolling.html b/playground/rolling.html index 51bc9395..24a8bb36 100644 --- a/playground/rolling.html +++ b/playground/rolling.html @@ -4,31 +4,201 @@ tsb — Rolling Windows - - -

Rolling Windows

-

Sliding-window aggregations — mirrors pandas.Series.rolling() and pandas.DataFrame.rolling().

- -
-

1 — Basic rolling mean

-

Call series.rolling(window) to get a Rolling object, then call .mean().

-
import { Series } from "tsb";
+  
+
+
Initializing playground…
+
+ ← Back to roadmap +

🎢 Rolling Windows — Interactive Playground

+

Sliding-window aggregations — mirrors + pandas.Series.rolling() and + pandas.DataFrame.rolling().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ + +
+

1 · Basic rolling mean

+

Call series.rolling(window) to get a Rolling object, + then call .mean(). The first positions are null (not enough data).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · minPeriods — allow partial windows

+

By default minPeriods = window. Set it lower to get results for + the initial positions too.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · Rolling sum, std, min, max

+

The Rolling object exposes several built-in aggregation methods.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · Rolling count (handles nulls)

+

count() counts valid (non-null / non-NaN) observations in each + window. It ignores minPeriods.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

5 · Rolling median

+

Useful for robust estimation — less sensitive to outliers than the mean.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

6 · Custom aggregation with apply()

+

Pass any function (values: readonly number[]) => number to + apply().

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

7 · Centered window

+

Set center: true to centre the window label, giving a symmetric + look-ahead/look-behind view.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

8 · DataFrame.rolling()

+

Aggregations are applied column-by-column, returning a new DataFrame with the + same shape.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

The Rolling object provides sliding-window aggregations. Use + series.rolling(window, opts?) or + df.rolling(window, opts?) to create one, then chain an aggregation + method.

+
series.rolling(window: number, {
+  minPeriods?: number,  // default = window
+  center?:    boolean,  // default false — trailing window
+}): Rolling
+
+// Aggregation methods
+rolling.mean():    Series
+rolling.sum():     Series
+rolling.std():     Series
+rolling.var():     Series
+rolling.min():     Series
+rolling.max():     Series
+rolling.count():   Series
+rolling.median():  Series
+rolling.apply(fn): Series
+
+// DataFrame — aggregations applied column-by-column
+df.rolling(window, opts?).mean(): DataFrame
+
+ + + From 0f786c094ac396e2fee4feca5c05019c5aaaa995 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:32:04 +0000 Subject: [PATCH 12/17] Rewrite stack_unstack playground to interactive dark-theme format Convert all 6 code examples from static
 blocks to interactive
with +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

2 · stack drops null by default

+

Like pandas, stack() silently omits cells whose value is + null or NaN. Pass { dropna: false } + to keep them.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

3 · unstack: recover the original DataFrame

+

unstack(s) is the inverse of stack(df, { dropna: false }). + It parses the compound index labels and reconstructs the grid.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · unstack fills missing cells

+

When stack was called with dropna=true (the default), + some (row, col) combinations are absent. unstack fills + them with null by default; pass fill_value to use a + different filler.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

5 · Custom separator

+

If your row-index labels or column names contain "|", choose a + different separator for both stack and unstack.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
-
-

6 — Reshape workflow: stack → filter → unstack

-

A common pattern: stack to long format, filter rows, then unstack back to wide.

-
import { DataFrame, stack, unstack } from "tsb";
+  
+  
+

6 · Reshape workflow: stack → filter → unstack

+

A common pattern: stack to long format, filter rows, then unstack back to wide.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

API Reference

+

The compound index uses a separator (default "|") to join row labels + and column names. Use .index.values and .values to inspect + the stacked Series.

+
// Stack — DataFrame → Series
+stack(df, {
+  dropna?: boolean,  // default true  — omit null/NaN cells
+  sep?:    string,   // default "|"   — row|col separator
+}): Series
+
+// Unstack — Series → DataFrame
+unstack(series, {
+  fill_value?: unknown,  // default null — fill missing cells
+  sep?:        string,   // default "|"  — separator to split index
+}): DataFrame
+
+ + + From b156b975766f09b9d0a51e8dfa7cfef299ee3d27 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:35:53 +0000 Subject: [PATCH 13/17] Rewrite playground/ewm.html to interactive playground format Convert static pre/code blocks to interactive playground-block sections with textarea editors, run/reset buttons, and output panels. Add loading overlay, CSS variables, playground-runtime.js script tag, and footer matching the standard playground template (value_counts.html). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/ewm.html | 764 +++++++++++++++++++++++++++----------------- 1 file changed, 479 insertions(+), 285 deletions(-) diff --git a/playground/ewm.html b/playground/ewm.html index 4190fffa..8e2c5d98 100644 --- a/playground/ewm.html +++ b/playground/ewm.html @@ -1,314 +1,508 @@ - + - - - - tsb — EWM (Exponentially Weighted Moving) - - - -

← tsb playground index

- -

📉 EWM — Exponentially Weighted Moving

- -

- Series.ewm() and DataFrame.ewm() provide - Exponentially Weighted Moving aggregations, mirroring - pandas.Series.ewm(). Unlike rolling windows (fixed size) or - expanding windows (all past data equally), EWM weights recent observations - more heavily using an exponential decay. -

- -

1. Decay Parameters

- -

- Specify the decay via exactly one of - span, com, - halflife, or alpha: -

- + + + + tsb — EWM (Exponentially Weighted Moving) + + + +
+
+
Initializing playground…
+
+ ← Back to roadmap +

📉 EWM — Interactive Playground

+

Series.ewm() and + DataFrame.ewm() provide + Exponentially Weighted Moving aggregations, + mirroring pandas.Series.ewm(). Unlike rolling windows (fixed size) + or expanding windows (all past data equally), EWM weights recent observations more + heavily using an exponential decay.
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ + +
+

1 · Decay Parameters

+

Specify the decay via exactly one of span, com, + halflife, or alpha:

- span → alpha = 2 / (span + 1)
- com → alpha = 1 / (1 + com)
- halflife → alpha = 1 − exp(−ln(2) / halflife)
+ span → alpha = 2 / (span + 1)
+ com → alpha = 1 / (1 + com)
+ halflife → alpha = 1 − exp(−ln(2) / halflife)
alpha → used directly (must be in (0, 1])
- -
import { Series, EWM } from "tsb";
-
-const s = new Series({ data: [1, 2, 3, 4, 5] });
-
-// All four are equivalent (alpha ≈ 0.5):
-s.ewm({ span: 3 }).mean()        // alpha = 2/(3+1) = 0.5
-s.ewm({ com: 1 }).mean()         // alpha = 1/(1+1) = 0.5
-s.ewm({ halflife: 1 }).mean()    // alpha = 1 − 2^(−1/1) = 0.5
-s.ewm({ alpha: 0.5 }).mean()     // alpha = 0.5 directly
- -

2. EWM Mean

- -

- With adjust=true (default), the mean at position t - is the weighted average of all past values, where weight for - xi is (1−α)t−i: -

- +
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · EWM Mean

+

With adjust=true (default), the mean at position t + is the weighted average of all past values, where the weight for + xi is (1−α)t−i.

- St = xt + (1−α)·St−1
- Wt = 1 + (1−α)·Wt−1
+ St = xt + (1−α)·St−1
+ Wt = 1 + (1−α)·Wt−1
meant = St / Wt
- -
const s = new Series({ data: [10, 20, 15, 30, 25] });
-
-// EWM mean with span=3 (alpha=0.5)
-const ewmMean = s.ewm({ span: 3 }).mean();
-console.log(ewmMean.toArray());
-// [10, 16.667, 15.714, 23.636, 24.324]
- -
[ 10, 16.666..., 15.714..., 23.636..., 24.324... ]
- -

3. adjust=false: Simple IIR Filter

- -

- With adjust=false, EWM uses a simple Infinite Impulse - Response formula — the same as an exponential smoothing filter: -

- -
yt = α · xt + (1−α) · yt−1
- -
const s = new Series({ data: [1, 2, 3, 4, 5] });
-
-// Simple exponential smoothing (alpha=0.3)
-const smooth = s.ewm({ alpha: 0.3, adjust: false }).mean();
-console.log(smooth.toArray());
-// [1, 1.3, 1.91, 2.737, 3.616]
- -
[ 1, 1.3, 1.91, 2.737, 3.616... ]
- -

4. EWM Variance and Standard Deviation

- -

- EWM variance uses reliability-weights Bessel correction (bias=false by - default, matching pandas): -

- -
const prices = new Series({ data: [100, 102, 98, 105, 103, 99] });
-
-// EWM standard deviation (span=5)
-const ewmStd = prices.ewm({ span: 5 }).std();
-console.log(ewmStd.toArray().map(v => v?.toFixed(3)));
-// [null, "1.414", "2.530", "2.927", "2.510", "2.736"]
-
-// Biased (population) variance
-const ewmVarBiased = prices.ewm({ span: 5 }).var(true);
-console.log(ewmVarBiased.toArray().map(v => v?.toFixed(3)));
-// [0.000, ...]
- -
std: [null, "1.414", "2.530", "2.927", "2.510", "2.736"]
- -

5. EWM Covariance

- -

Compute pairwise exponentially weighted covariance between two Series:

- -
const x = new Series({ data: [1, 2, 3, 4, 5] });
-const y = new Series({ data: [5, 4, 3, 2, 1] });
-
-const ewmCov = x.ewm({ alpha: 0.4 }).cov(y);
-console.log(ewmCov.toArray().map(v => v?.toFixed(4)));
-// [null, "-0.5", "-1.1429", ...]  (negative: x and y move opposite)
- -
[null, "-0.5000", "-1.1429", "-1.8000", "-2.2500"]
- -

6. EWM Correlation

- -
const s1 = new Series({ data: [1, 2, 3, 4, 5] });
-const s2 = new Series({ data: [2, 4, 6, 8, 10] }); // perfect linear
-
-const ewmCorr = s1.ewm({ span: 3 }).corr(s2);
-console.log(ewmCorr.toArray().map(v => v?.toFixed(4)));
-// [null, "1.0000", "1.0000", "1.0000", "1.0000"]  (perfect +1)
- -
[null, "1.0000", "1.0000", "1.0000", "1.0000"]
- -

7. Missing Values (ignoreNa)

- -

- The ignoreNa option controls how missing values affect the - exponential weights: -

- -
const s = new Series({ data: [1, null, 3, null, 5] });
-
-// ignoreNa=false (default): NaN positions advance time (decay occurs)
-const r1 = s.ewm({ alpha: 0.5, ignoreNa: false }).mean();
-console.log(r1.toArray());
-// [1, null, 2.6, null, 4.314...]
-// x[2]=3 has extra decay: w[0]=0.25, w[2]=1 → mean = (0.25+3)/1.25 = 2.6
-
-// ignoreNa=true: missing values completely skipped
-const r2 = s.ewm({ alpha: 0.5, ignoreNa: true }).mean();
-console.log(r2.toArray());
-// [1, null, 1.667, null, 3.286]
-// x[2]=3 treated as adjacent to x[0]: w[0]=0.5, w[2]=1
- -
-ignoreNa=false: [1, null, 2.6, null, 4.314...] -ignoreNa=true: [1, null, 1.667, null, 3.286...] +
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
- -

8. DataFrame EWM

- -
import { DataFrame } from "tsb";
-
-const df = DataFrame.fromColumns({
-  open:  [10, 11, 10.5, 12, 11.8],
-  close: [11, 10.5, 12, 11.8, 13],
+  
+ + +
+

3 · adjust=false: Simple IIR Filter

+

With adjust=false, EWM uses a simple Infinite Impulse Response + formula — the same as an exponential smoothing filter: + yt = α·xt + (1−α)·yt−1

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

4 · EWM Variance and Standard Deviation

+

EWM variance uses reliability-weights Bessel correction + (bias=false by default, matching pandas).

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

5 · EWM Covariance

+

Compute pairwise exponentially weighted covariance between two Series. + Negative covariance means the series move in opposite directions.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

6 · EWM Correlation

+

EWM Pearson correlation between two Series. Perfectly correlated series + produce values of +1 or −1.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

7 · Missing Values (ignoreNa)

+

The ignoreNa option controls how missing values affect the + exponential weights. With ignoreNa=false (default), null + positions still advance time and cause extra decay. With + ignoreNa=true, nulls are completely skipped.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

8 · DataFrame EWM

+

Apply EWM to every numeric column of a DataFrame independently.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

9 · Custom apply

+

Use apply(fn) to implement custom EWM aggregations. The + function receives the accumulated values and their EW weights.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ +

API Reference

+

Specify exactly one decay parameter. All methods return Series-like objects + with .values for inspection.

+
// Series.ewm(options) → EWM
+// DataFrame.ewm(options) → DataFrameEwm
 
-    
// Series.ewm(options) → EWM
-// DataFrame.ewm(options) → DataFrameEwm
-
-// EwmOptions (exactly one decay parameter required):
+// EwmOptions (exactly one decay parameter required):
 {
-  span?: number,      // ≥ 1, alpha = 2/(span+1)
-  com?: number,       // ≥ 0, alpha = 1/(1+com)
-  halflife?: number,  // > 0, alpha = 1 − exp(−ln2/halflife)
-  alpha?: number,     // (0, 1]
-  adjust?: boolean,   // default: true
-  ignoreNa?: boolean, // default: false
-  minPeriods?: number // default: 0
+  span?: number,      // ≥ 1, alpha = 2/(span+1)
+  com?: number,       // ≥ 0, alpha = 1/(1+com)
+  halflife?: number,  // > 0, alpha = 1 − exp(−ln2/halflife)
+  alpha?: number,     // (0, 1]
+  adjust?: boolean,   // default: true
+  ignoreNa?: boolean, // default: false
+  minPeriods?: number // default: 0
 }
 
-// EWM methods:
+// EWM methods:
 ewm.mean()              → Series (EwmSeriesLike)
 ewm.std(bias?)          → Series
 ewm.var(bias?)          → Series
 ewm.cov(other, bias?)   → Series
 ewm.corr(other)         → Series
-ewm.apply(fn)           → Series   // fn: (values, weights) => number
+ewm.apply(fn)           → Series   // fn: (values, weights) => number
 
-// DataFrameEwm methods:
+// DataFrameEwm methods:
 dfEwm.mean()     → DataFrame
 dfEwm.std(bias?) → DataFrame
 dfEwm.var(bias?) → DataFrame
- +
+ + + + From ab8565d0cd73deb413613b6c0668edd024400b65 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:39:10 +0000 Subject: [PATCH 14/17] Rewrite datetime_accessor playground to interactive template format Convert all static
 blocks to interactive playground-block
structure with textarea editors, matching the standard playground
template (CSS variables, loading overlay, playground-runtime.js).

Removed inline 
-  
+console.log("Day of week    :", dow.toArray());
+
+// Month names via strftime
+const monthNames = dates.dt.strftime("%B");
+console.log("Month names    :", monthNames.toArray());
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

API Reference

+

Access via series.dt on any Series<Date>. + All methods return a new Series and propagate nulls.

+
// Calendar components
+series.dt.year()         → Series<number>
+series.dt.month()        → Series<number>  // 1–12
+series.dt.day()          → Series<number>  // 1–31
+series.dt.hour()         → Series<number>  // 0–23
+series.dt.minute()       → Series<number>  // 0–59
+series.dt.second()       → Series<number>  // 0–59
+
+// Derived fields
+series.dt.dayofweek()    → Series<number>  // Mon=0, Sun=6
+series.dt.dayofyear()    → Series<number>  // 1–366
+series.dt.quarter()      → Series<number>  // 1–4
+
+// Boolean properties
+series.dt.is_month_start()   → Series<boolean>
+series.dt.is_month_end()     → Series<boolean>
+series.dt.is_quarter_start() → Series<boolean>
+series.dt.is_quarter_end()   → Series<boolean>
+series.dt.is_year_start()    → Series<boolean>
+series.dt.is_year_end()      → Series<boolean>
+series.dt.is_leap_year()     → Series<boolean>
+series.dt.days_in_month()    → Series<number>
+
+// Formatting & conversion
+series.dt.strftime(fmt)      → Series<string>
+series.dt.normalize()        → Series<Date>
+series.dt.date()             → Series<Date>
+series.dt.total_seconds()    → Series<number>
+
+// Rounding (freq: "D" | "H" | "T" | "S" | "L")
+series.dt.floor(freq)   → Series<Date>
+series.dt.ceil(freq)    → Series<Date>
+series.dt.round(freq)   → Series<Date>
+
+ + + + From bb65a48cf108c00f3db3d3e856ca9b8227394b30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:41:51 +0000 Subject: [PATCH 15/17] Rewrite playground/csv.html to use proper interactive playground format Convert from old style.css/contenteditable structure to the standard dark-theme template with CSS variables, loading overlay, playground-block structure with textarea editors, Run/Reset buttons, and proper import { ... } from 'tsb' statements in all code blocks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/csv.html | 512 ++++++++++++++++++++++++++++++++------------ 1 file changed, 376 insertions(+), 136 deletions(-) diff --git a/playground/csv.html b/playground/csv.html index 2d4bbc14..e25df347 100644 --- a/playground/csv.html +++ b/playground/csv.html @@ -1,206 +1,446 @@ - - - - tsb — readCsv & toCsv - - - - - -

readCsv & toCsv — CSV I/O

-

- readCsv() and toCsv() mirror - pandas read_csv() - and - pandas DataFrame.to_csv(). - Parse CSV text into a DataFrame with automatic dtype inference, - and serialize any DataFrame back to CSV with full formatting control. -

+ + + + tsb — readCsv & toCsv + + + +
+
+
Initializing playground…
+
+ ← Back to roadmap +

📄 readCsv & toCsv — Interactive Playground

+

Parse CSV text into a DataFrame with automatic + dtype inference, and serialize any DataFrame back + to CSV with full formatting control. Mirrors + pandas.read_csv() and + pandas.DataFrame.to_csv().
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ + +
+

1 · Parse a CSV string

+

The simplest call is readCsv(text). The first row is the header, + subsequent rows are data. Column dtypes are inferred automatically.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · Missing values (NA)

+

Empty fields, NA, NaN, null, None, + and several other sentinel strings are automatically converted to null. + Pass extra strings via naValues.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

2 — Missing values (NA)

-

- Empty fields, NA, NaN, null, None, - and several other sentinel strings are automatically converted to null. - Pass extra strings via naValues. -

-
-
const csv = `x,y
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

3 · Quoted fields & custom separator

+

Fields containing the separator, quotes, or newlines can be wrapped in double-quotes. + Use sep to change the delimiter (tab, semicolon, pipe, etc.).

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

3 — Quoted fields & custom separator

-

- Fields containing the separator, quotes, or newlines can be wrapped in double-quotes. - Use sep to change the delimiter (tab, semicolon, pipe, etc.). -

-
-
const csv = `name;note
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

4 · Index column

+

Set indexCol to a column name or position to use that column + as the row index instead of the default RangeIndex.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

4 — Index column

-

- Set indexCol to a column name or position to use that column - as the row index instead of the default RangeIndex. -

-
-
const csv = `id,city,pop
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

5 · Limiting rows

+

Use nRows to read only the first N data rows, and + skipRows to skip rows at the start.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

5 — Limiting rows

-

- Use nRows to read only the first N data rows, and - skipRows to skip rows at the start. -

-
-
const csv = `val
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

6 · Serialize with toCsv

+

toCsv(df) converts a DataFrame back to a CSV string. + Control index inclusion, header, separator, and NA representation.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

6 — Serialize with toCsv

-

- toCsv(df) converts a DataFrame back to a CSV string. - Control index inclusion, header, separator, and NA representation. -

-
-
const df = tsb.DataFrame.fromColumns({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

7 · Round-trip

+

A DataFrame serialized with toCsv can be + reconstructed with readCsv without data loss.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

7 — Round-trip

-

- A DataFrame serialized with toCsv can be - reconstructed with readCsv without data loss. -

-
-
const original = tsb.DataFrame.fromColumns({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

API Reference

+

Parse CSV text into a DataFrame or serialize a DataFrame back to CSV. All options + are optional — sensible defaults are provided.

+
// Parse CSV text → DataFrame
+readCsv(text: string, opts?: {
+  sep?:       string,            // default ","
+  naValues?:  readonly string[], // extra NA sentinel strings
+  indexCol?:  string | number,   // column to use as row index
+  nRows?:     number,            // max data rows to read
+  skipRows?:  number,            // rows to skip at start
+}): DataFrame
 
-    
-  
+// Serialize DataFrame → CSV text
+toCsv(df: DataFrame, opts?: {
+  sep?:    string,   // default ","
+  index?:  boolean,  // default true — include index
+  header?: boolean,  // default true — include header row
+  naRep?:  string,   // default "" — NA representation
+}): string
+
+ + + + From 698b6b694df2efb79cd201188572d6c9d322cd2d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:44:01 +0000 Subject: [PATCH 16/17] Rewrite playground/json.html to use interactive playground template format Convert from legacy style.css/contenteditable structure to the standard dark-theme playground format with CSS variables, loading overlay, playground-block/textarea structure, Run/Reset buttons, and proper import statements. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/json.html | 515 +++++++++++++++++++++++++++++++------------ 1 file changed, 376 insertions(+), 139 deletions(-) diff --git a/playground/json.html b/playground/json.html index 3ac6d4a9..ee6ab127 100644 --- a/playground/json.html +++ b/playground/json.html @@ -1,199 +1,436 @@ - - - - tsb — readJson & toJson - - - - - -

readJson & toJson — JSON I/O

-

- readJson() and toJson() mirror - pandas read_json() - and - pandas DataFrame.to_json(). - Parse JSON text into a DataFrame and serialize any - DataFrame back to JSON, supporting five orient formats. -

+ + + + tsb — readJson & toJson + + + +
+
+
Initializing playground…
+
+ ← Back to roadmap +

📄 readJson & toJson — Interactive Playground

+

Parse JSON text into a DataFrame with + readJson() and serialize back with toJson(). Mirrors + pandas + read_json() and + pandas + DataFrame.to_json(), supporting five orient formats.
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ + +
+

1 · Parse records JSON (default)

+

The "records" orient is an array of row objects — the most + natural JSON format for tabular data. Auto-detected when the input is a + JSON array.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · Split orient

+

The "split" orient stores columns, index, and data + separately — compact and lossless. Auto-detected when the root object + contains "columns" and "data" keys.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

2 — Split orient

-

- The "split" orient stores columns, index, and data - separately — compact and lossless. It is auto-detected when the root - object contains "columns" and "data" keys. -

-
-
const json = JSON.stringify({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

3 · Index orient

+

The "index" orient uses row-index labels as keys, each + mapping to a record of column values.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

3 — Index orient

-

- The "index" orient uses row-index labels as keys, each - mapping to a record of column values. -

-
-
const json = JSON.stringify({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

4 · Columns orient

+

The "columns" orient uses column names as keys, each + mapping to an object of index-label → value pairs. Useful for + column-major storage.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

4 — Columns orient

-

- The "columns" orient uses column names as keys, each - mapping to an object of index-label → value pairs. Useful for - column-major storage. -

-
-
const json = JSON.stringify({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

5 · Values orient

+

The "values" orient is a plain 2-D array — no index or + column labels. Columns are auto-named "0", + "1", etc.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

5 — Values orient

-

- The "values" orient is a plain 2-D array — no index or - column labels. Columns are auto-named "0", - "1", etc. -

-
-
const json = "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]";
-
-const df = tsb.readJson(json, { orient: "values" });
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

6 · Serialize with toJson()

+

toJson(df, options) serializes a DataFrame + to a JSON string. Choose any orient and optionally pretty-print with + indent.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

6 — Serialize with toJson()

-

- toJson(df, options) serializes a DataFrame - to a JSON string. Choose any orient and optionally pretty-print with - indent. -

-
-
const df = tsb.DataFrame.fromColumns({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

7 · Round-trip

+

A DataFrame serialized with toJson can be + reconstructed with readJson without data loss.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

7 — Round-trip

-

- A DataFrame serialized with toJson can be - reconstructed with readJson without data loss. -

-
-
const original = tsb.DataFrame.fromColumns({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

API Reference

+

Parse JSON into a DataFrame or serialize a DataFrame back to JSON. + Five orient formats are supported: records, + split, index, columns, and + values.

+
// Parse JSON → DataFrame
+readJson(json: string, options?: {
+  orient?: "records" | "split" | "index" | "columns" | "values",
+}): DataFrame
 
-    
-  
+// Serialize DataFrame → JSON
+toJson(df: DataFrame, options?: {
+  orient?: "records" | "split" | "index" | "columns" | "values",
+  indent?: number,
+}): string
+
+ + + + From f4ea0f6341c1cd4f6a11a0115e025e14c31dbfa6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:48:45 +0000 Subject: [PATCH 17/17] Fix playground inconsistencies: update index.html links, convert broken pages to interactive format Agent-Logs-Url: https://github.com/githubnext/tsessebe/sessions/6e45fe33-bdb3-45cd-a0c8-647b5aa3a99f Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com> --- playground/describe.html | 515 ++++++++++++++++++++++--------- playground/string_accessor.html | 522 ++++++++++++++++++++------------ 2 files changed, 703 insertions(+), 334 deletions(-) diff --git a/playground/describe.html b/playground/describe.html index a15142e5..30b4d1a9 100644 --- a/playground/describe.html +++ b/playground/describe.html @@ -1,40 +1,212 @@ - - - - tsb — describe & quantile - - - - - -

describe & quantile — Summary Statistics

-

- describe() and Series.quantile() give you the - same concise statistical summary that - pandas DataFrame.describe() - produces. For numeric data you get count, mean, - std, min, user-defined percentiles, and max. - For categorical / string data you get count, unique, - top, and freq. -

+ + + + tsb — describe & quantile + + + +
+
+
Initializing playground…
+
+ ← Back to roadmap +

📈 describe & quantile — Interactive Playground

+

describe() and Series.quantile() give you the + same concise statistical summary that + pandas.DataFrame.describe() produces. For numeric data you get + count, mean, std, min, percentiles, and + max. For categorical data you get count, unique, + top, and freq.
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ + +
+

1 · Describe a numeric Series

+

Pass any Series with numeric data and get back a labeled + Series of statistics. Percentiles default to 25%, 50%, and + 75% — just like pandas.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ + +
+

2 · Custom percentiles

+

Override the default percentile set with the percentiles + option. Pass any array of values in [0, 1].

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

2 — Custom percentiles

-

- Override the default percentile set with the percentiles - option. Pass any array of values in [0, 1]. -

-
-
const prices = new tsb.Series({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

3 · Describe a categorical Series

+

For non-numeric Series, describe() switches to categorical + mode: count, unique, top (most frequent + value), and freq (its count). Nulls are silently excluded.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

3 — Describe a categorical Series

-

- For non-numeric Series, describe() switches to categorical - mode: count, unique, top (most frequent - value), and freq (its count). Nulls are silently excluded. -

-
-
const dept = new tsb.Series({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

4 · Describe a DataFrame

+

When passed a DataFrame, describe() returns a + new DataFrame where each column is a stat Series. By default + only numeric columns are included (include: "number").

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

4 — Describe a DataFrame

-

- When passed a DataFrame, describe() returns a - new DataFrame where each column is a stat Series. By - default only numeric columns are included (include: "number"). -

-
-
const df = tsb.DataFrame.fromColumns({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

5 · include="all" for mixed DataFrames

+

Set include: "all" to describe both numeric and categorical + columns in a single call. Numeric stats get null for + categorical-only rows and vice-versa.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

5 — include="all" for mixed DataFrames

-

- Set include: "all" to describe both numeric and - categorical columns in a single call. Numeric stats get - null for categorical-only rows and vice-versa. -

-
-
const df = tsb.DataFrame.fromColumns({
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

6 · Series.quantile()

+

Series.quantile(q) computes a single quantile via linear + interpolation — the same algorithm pandas uses as its default + (method="linear"). q=0.5 is the median.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

6 — Series.quantile()

-

- Series.quantile(q) computes a single quantile via linear - interpolation — the same algorithm pandas uses as its default - (method="linear"). q=0.5 is the median. -

-
-
const s = new tsb.Series({ data: [3, 7, 1, 9, 5, 11, 2, 8, 4, 6] });
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

7 · Standalone quantile() utility

+

The low-level quantile(sorted, q) function works on any + sorted plain array and is useful when you have pre-filtered data.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

7 — Standalone quantile() utility

-

- The low-level quantile(sorted, q) function works on any - sorted plain array and is useful when you have pre-filtered data. -

-
-
// Pre-sorted exam scores
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + +
+

API Reference

+

describe() returns a summary Series (for Series + input) or DataFrame (for DataFrame input). quantile() + computes a single quantile from a sorted array or Series.

+
// Series describe
+describe(series, {
+  percentiles?: number[],  // default [0.25, 0.5, 0.75]
+}): Series
+
+// DataFrame describe
+describe(df, {
+  percentiles?: number[],
+  include?: "number" | "all",  // default "number"
+}): DataFrame
 
-    
-  
+// Series quantile
+series.quantile(q: number): number
+
+// Standalone quantile
+quantile(sorted: number[], q: number): number
+
+ + + + diff --git a/playground/string_accessor.html b/playground/string_accessor.html index bf3ad94d..0fc19aae 100644 --- a/playground/string_accessor.html +++ b/playground/string_accessor.html @@ -1,238 +1,364 @@ - - - - tsb — Series.str Accessor - - - - - -

Series.str — Vectorised String Operations

-

- Series.str gives you element-wise string operations on a - Series, mirroring - pandas StringMethods. Every method propagates null / NaN unchanged. -

+ + + + tsb — Series.str Accessor + + + + +
+
+
Initializing playground…
+
+ + ← Back to roadmap +

🔡 Series.str — Interactive Playground

+

+ Series.str gives you element-wise string operations on a + Series, mirroring pandas StringMethods. + Every method propagates null / NaN unchanged.
+ Edit any code block below and press ▶ Run + (or Ctrl+Enter) to execute it live in your browser. +

+ +
+

Case Operations

+

Convert strings to lower, upper, title, or capitalized form.

+
+
+ TypeScript +
+ + +
+
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+
+ +
+

Length & Slicing

+

Get string length, extract substrings with slice(), or access individual characters with get().

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

2 — Length & slicing

-

- Get string length, extract substrings with slice(), or - access individual characters with get(). -

-
-
const s = new tsb.Series({ data: ["hello", "world", "pandas"] });
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + +
+

Strip & Pad

+

Remove whitespace (or specific characters) with strip(). Pad strings with ljust(), rjust(), center(), or zfill().

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

3 — Strip & pad

-

- Remove whitespace (or specific characters) with strip(), - lstrip(), rstrip(). Pad strings with - pad(), ljust(), rjust(), - center(), or zfill(). -

-
-
const s = new tsb.Series({ data: ["  hello  ", "***world***", "42"] });
-
-console.log("strip()        :", s.str.strip().toArray());
-console.log("strip('*')     :", s.str.strip("*").toArray());
-console.log("ljust(10)      :", s.str.ljust(10).toArray());
-console.log("rjust(10)      :", s.str.rjust(10).toArray());
-console.log("center(10)     :", s.str.center(10).toArray());
-console.log("zfill(5)       :",
-  new tsb.Series({ data: ["42", "-7", "3"] }).str.zfill(5).toArray());
-
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + +
+

Search & Match

+

Test membership with contains(), startswith(), endswith(). Use match() or fullmatch() for regex matching.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

4 — Search & match

-

- Test membership with contains(), startswith(), - endswith(). Use match() for anchored-start - matching or fullmatch() for whole-string matching. -

-
-
const s = new tsb.Series({ data: ["foo123", "bar456", "foo_bar", null] });
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + +
+

Count, Find & Replace

+

Count pattern occurrences, find positions, and replace substrings.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

5 — Count, find & replace

-

- Count pattern occurrences with count(), find positions with - find() / rfind(), and replace with - replace(). -

-
-
const s = new tsb.Series({ data: ["banana", "apple", "abracadabra"] });
-
-console.log("count('a')     :", s.str.count("a").toArray());
-console.log("find('a')      :", s.str.find("a").toArray()); // first index
-console.log("rfind('a')     :", s.str.rfind("a").toArray()); // last index
-console.log("replace('a','X'):", s.str.replace("a", "X").toArray()); // all
-console.log("replace n=1   :", s.str.replace("a", "X", 1).toArray()); // first only
-
+ +
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + +
+

Extract

+

Extract the first regex capture group with extract(). Returns null when there is no match.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

6 — Extract

-

- Extract the first regex capture group with extract(). - Returns null when there is no match. -

-
-
const s = new tsb.Series({ data: ["price: 42", "cost: 99.5", "free"] });
-
-// Extract numeric part after ": "
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + +
+

Split & Join

+

Split strings with split() and reassemble with join(). Use cat() to concatenate element-wise.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

7 — Split & join

-

- Split strings with split() (returns JSON array or the nth - segment), and reassemble with join(). Use - cat() to concatenate element-wise. -

-
-
const s = new tsb.Series({ data: ["a,b,c", "x,y,z"] });
-
-// Get the nth segment (0-based)
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + +
+

Predicates

+

Test character classes with isalpha(), isdigit(), isalnum(), islower(), isupper(), istitle(), isspace().

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

8 — Predicates

-

- Test character classes with isalpha(), - isdigit(), isalnum(), islower(), - isupper(), istitle(), isspace(). -

-
-
const s = new tsb.Series({ data: ["abc", "123", "abc123", "ABC", "Hello World", "   "] });
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + +
+

Null Propagation

+

All methods pass null / NaN through unchanged, just like pandas.

+
+
+ TypeScript +
+ + +
- -

-    
- -
-

9 — Null propagation

-

- All methods pass null / NaN through unchanged, - just like pandas. -

-
-
const s = new tsb.Series({ data: ["hello", null, "world"] });
+      
+      
Click ▶ Run to execute
+
Ctrl+Enter to run · Tab to indent
+
+ + + + + +