From 52c0ce2102a26ec3237fc907ce6b79754a047ea3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Apr 2026 06:19:07 +0000
Subject: [PATCH 1/2] Initial plan
From 66fce5d23652249d3b51e13d843eae2d5a49d082 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Apr 2026 06:30:11 +0000
Subject: [PATCH 2/2] Add console.log() to playground TypeScript blocks so they
actually produce output
Agent-Logs-Url: https://github.com/githubnext/tsessebe/sessions/30790671-f2ec-4398-bf84-3d33cc6afc47
Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com>
---
playground/add_sub_mul_div.html | 26 +++---
playground/align.html | 42 ++++-----
playground/api_types.html | 88 +++++++++----------
playground/assign.html | 12 ++-
playground/at_iat.html | 16 ++--
playground/attrs.html | 56 ++++++------
playground/between.html | 12 +--
playground/clip_advanced.html | 14 +--
playground/clip_with_bounds.html | 15 ++--
playground/combine.html | 6 +-
playground/combine_first.html | 12 ++-
playground/compare.html | 31 +++----
playground/corrwith.html | 21 ++---
playground/cut_bins_to_frame.html | 3 +-
playground/cut_qcut.html | 9 +-
playground/date-offset.html | 34 +++----
playground/dot_matmul.html | 14 +--
playground/dropna.html | 18 ++--
playground/duplicated.html | 16 ++--
playground/eval_query.html | 20 ++---
playground/excel.html | 6 +-
playground/fillna.html | 36 ++++----
playground/filter.html | 10 +--
playground/format_ops.html | 12 +--
playground/infer_dtype.html | 40 ++++-----
playground/infer_objects.html | 34 +++----
playground/insert_pop.html | 23 +++--
playground/interpolate.html | 26 +++---
playground/join.html | 16 ++--
playground/json_normalize.html | 8 +-
playground/math_ops.html | 16 ++--
playground/memory_usage.html | 16 ++--
playground/merge_asof.html | 13 +--
playground/merge_ordered.html | 15 ++--
playground/mode.html | 12 +--
playground/named_agg.html | 6 +-
playground/nancumops.html | 22 ++---
playground/natsort.html | 20 ++---
playground/notna.html | 34 +++----
playground/notna_boolean.html | 8 +-
playground/notna_isna.html | 48 +++++-----
playground/numeric_extended.html | 31 +++----
playground/nunique.html | 30 +++----
playground/pipe_apply.html | 21 +++--
playground/pivot_table.html | 12 ++-
playground/quantile.html | 31 +++----
playground/reduce_ops.html | 26 +++---
playground/reindex.html | 28 +++---
playground/rename_ops.html | 26 +++---
playground/rolling_apply.html | 17 ++--
playground/scalar_extract.html | 34 +++----
playground/select_dtypes.html | 3 +-
playground/sem_var.html | 13 +--
playground/skew_kurt.html | 14 +--
playground/sort_ops.html | 20 ++---
.../str_findall_and_json_denormalize.html | 35 ++++----
playground/style.html | 53 ++++++-----
playground/swaplevel.html | 12 ++-
playground/testing.html | 16 ++--
playground/to_datetime.html | 16 ++--
playground/to_from_dict.html | 12 +--
playground/to_numeric.html | 6 +-
playground/to_timedelta.html | 28 +++---
playground/transform_agg.html | 26 +++---
playground/truncate.html | 14 +--
playground/update.html | 10 +--
playground/value_counts_full.html | 12 ++-
playground/wide_to_long.html | 7 +-
playground/window_extended.html | 13 +--
playground/xs.html | 8 +-
70 files changed, 771 insertions(+), 689 deletions(-)
diff --git a/playground/add_sub_mul_div.html b/playground/add_sub_mul_div.html
index 07fb093c..9f43f48c 100644
--- a/playground/add_sub_mul_div.html
+++ b/playground/add_sub_mul_div.html
@@ -192,7 +192,7 @@
2 — add: Series + Series (positional)
const a = new Series({ data: [1, 2, 3] });
const b = new Series({ data: [4, 5, 6] });
-seriesAdd(a, b).values; // [5, 7, 9]
+console.log(seriesAdd(a, b).values); // [5, 7, 9]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -213,8 +213,8 @@ 3 — sub / rsub
+console.log(seriesSub(s, 5).values); // [5, 15, 25]
+console.log(seriesRsub(s, 100).values); // [90, 80, 70]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -235,10 +235,10 @@ 4 — mul: multiply
+console.log(seriesMul(s, weights).values); // [0.5, 2, 6, null]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -261,8 +261,8 @@ 5 — div / rdiv (true division)
+console.log(seriesDiv(s, 2).values); // [2, 4.5, Infinity, null]
+console.log(seriesRdiv(s, 36).values); // [9, 4, Infinity, null]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -285,13 +285,13 @@ 6 — DataFrame arithmetic
const df = DataFrame.fromColumns({ price: [10, 20, 30], qty: [3, 5, 2] });
// Add a discount
-dataFrameAdd(df, 5).col("price").values; // [15, 25, 35]
+console.log(dataFrameAdd(df, 5).col("price").values); // [15, 25, 35]
// Scale everything by 2
-dataFrameMul(df, 2).col("qty").values; // [6, 10, 4]
+console.log(dataFrameMul(df, 2).col("qty").values); // [6, 10, 4]
// Revenue per item / some constant
-dataFrameDiv(df, 10).col("price").values; // [1, 2, 3]
+console.log(dataFrameDiv(df, 10).col("price").values); // [1, 2, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -312,9 +312,9 @@ 7 — Missing value propagation
+console.log(seriesAdd(s, 10).values); // [11, null, NaN, 14]
+console.log(seriesMul(s, 2).values); // [2, null, NaN, 8]
+console.log(seriesDiv(s, 2).values); // [0.5, null, NaN, 2]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/align.html b/playground/align.html
index aa8da364..2699b1e7 100644
--- a/playground/align.html
+++ b/playground/align.html
@@ -168,8 +168,8 @@ 1 · alignSeries — outer (default)
// Default join="outer" → union of indices
const [la, ra] = alignSeries(a, b);
-la.toArray(); // → [1, 2, 3] (index: a, b, c)
-ra.toArray(); // → [null, 10, 20] (index: a, b, c)
+console.log(la.toArray()); // → [1, 2, 3] (index: a, b, c)
+console.log(ra.toArray()); // → [null, 10, 20] (index: a, b, c)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -186,8 +186,8 @@ 2 · alignSeries — inner join
+console.log(li.toArray()); // → [2, 3] (only shared labels: b, c)
+console.log(ri.toArray()); // → [10, 20]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -208,13 +208,13 @@ 3 · alignSeries — left / right join + fillValue
// join="left": result index = x's index
const [ll, rl] = alignSeries(x, y, { join: "left", fillValue: 0 });
-ll.toArray(); // → [1, 2, 3]
-rl.toArray(); // → [0, 10, 0] ("d" is outside x's index → dropped)
+console.log(ll.toArray()); // → [1, 2, 3]
+console.log(rl.toArray()); // → [0, 10, 0] ("d" is outside x's index → dropped)
// join="right": result index = y's index
const [lr, rr] = alignSeries(x, y, { join: "right", fillValue: 0 });
-lr.toArray(); // → [2, 0] ("b" matches, "d" is new)
-rr.toArray(); // → [10, 30]
+console.log(lr.toArray()); // → [2, 0] ("b" matches, "d" is new)
+console.log(rr.toArray()); // → [10, 30]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -247,13 +247,13 @@ 4 · alignDataFrame — outer, both axes
// la → shape [2, 3] columns: x, y, z
// row r0: x=1, y=3, z=null
// row r1: x=2, y=4, z=null
-la.col("z").toArray(); // → [null, null]
+console.log(la.col("z").toArray()); // → [null, null]
// ra → shape [2, 3] columns: x, y, z
// row r0: x=null, y=null, z=null
// row r1: x=null, y=10, z=20
-ra.col("x").toArray(); // → [null, null]
-ra.col("y").toArray(); // → [null, 10]
+console.log(ra.col("x").toArray()); // → [null, null]
+console.log(ra.col("y").toArray()); // → [null, 10]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -271,10 +271,10 @@ 5 · alignDataFrame — axis=0 (rows only)
+console.log(la5.columns.toArray()); // → ["x", "y"] (unchanged)
+console.log(ra5.columns.toArray()); // → ["y", "z"] (unchanged)
+console.log(la5.index.toArray()); // → ["r0", "r1"] (outer union)
+console.log(ra5.index.toArray()); // → ["r0", "r1"] (outer union)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -292,10 +292,10 @@ 6 · alignDataFrame — axis=1 (columns only)
+console.log(la6.index.toArray()); // → ["r0", "r1"] (unchanged)
+console.log(ra6.index.toArray()); // → ["r1"] (unchanged)
+console.log(la6.columns.toArray().sort()); // → ["x", "y", "z"]
+console.log(ra6.columns.toArray().sort()); // → ["x", "y", "z"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -318,8 +318,8 @@ 7 · Arithmetic after alignment
const [ap, aq] = alignSeries(p, q, { fillValue: 0 });
// Now same shape — do element-wise addition
const sum = ap.add(aq);
-sum.toArray(); // → [100, 201, 302]
-sum.index.toArray(); // → ["a", "b", "c"]
+console.log(sum.toArray()); // → [100, 201, 302]
+console.log(sum.index.toArray()); // → ["a", "b", "c"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/api_types.html b/playground/api_types.html
index c91b3478..8a12cbd7 100644
--- a/playground/api_types.html
+++ b/playground/api_types.html
@@ -167,12 +167,12 @@ isScalar(val)
+console.log(isScalar(42)); // true
+console.log(isScalar("hello")); // true
+console.log(isScalar(null)); // true
+console.log(isScalar(new Date())); // true
+console.log(isScalar([1, 2])); // false
+console.log(isScalar({ a: 1 })); // false
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -189,10 +189,10 @@ isListLike(val)
↺ Reset
-
+
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -209,9 +209,9 @@ isArrayLike(val)
↺ Reset
-
+
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -228,9 +228,9 @@ isDictLike(val)
↺ Reset
-
+
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -246,14 +246,14 @@ isNumber / isBool / isStringValue / isFloat / isInteger
↺ Reset
-
+
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -270,10 +270,10 @@ isMissing(val)
↺ Reset
-
+
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -290,9 +290,9 @@ isHashable(val)
↺ Reset
-
+
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -312,20 +312,20 @@ Dtype-Level Predicates
+console.log(isFloatDtype("float32")); // true
+console.log(isIntegerDtype("int64")); // true
+console.log(isUnsignedIntegerDtype("uint8")); // true
+console.log(isSignedIntegerDtype("int8")); // true
+console.log(isStringDtype("string")); // true
+console.log(isDatetimeDtype("datetime")); // true
+console.log(isCategoricalDtype("category")); // true
+console.log(isObjectDtype("object")); // true
+console.log(isExtensionArrayDtype("category")); // true
+console.log(isExtensionArrayDtype("int32")); // false
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/assign.html b/playground/assign.html
index 9cdf746e..99327e6b 100644
--- a/playground/assign.html
+++ b/playground/assign.html
@@ -172,7 +172,8 @@ Example 1 — Array and Series
// df2.columns.values → ["a", "b", "c", "d"]
// df2.col("c").values → [7, 8, 9]
-// df2.col("d").values → [4, 5, 6]
+// df2.col("d").values → [4, 5, 6]
+console.log(df2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -198,7 +199,8 @@ Example 2 — Callable (chained derivations)
});
// df3.col("total").values → [11, 22, 33]
-// df3.col("tax").values → [1.1, 2.2, 3.3]
+// df3.col("tax").values → [1.1, 2.2, 3.3]
+console.log(df3);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -218,7 +220,8 @@ Example 3 — Instance method
const df4 = df.assign({
squared_a: (d: DataFrame) => d.col("a").values.map((v) => (v as number) ** 2),
});
-// df4.col("squared_a").values → [1, 4, 9]
+// df4.col("squared_a").values → [1, 4, 9]
+console.log(df4);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -238,7 +241,8 @@ Example 4 — Replace an existing column
const df5 = dataFrameAssign(df, { b: [100, 200, 300] });
// df5.columns.values → ["a", "b"] (order unchanged)
-// df5.col("b").values → [100, 200, 300]
+// df5.col("b").values → [100, 200, 300]
+console.log(df5);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/at_iat.html b/playground/at_iat.html
index 5d4d782b..d7029e21 100644
--- a/playground/at_iat.html
+++ b/playground/at_iat.html
@@ -186,8 +186,8 @@ seriesAt — access by label
+console.log(seriesAt(s, "b")); // 20
+console.log(seriesAt(s, "a")); // 10
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -224,8 +224,8 @@ seriesIat — access by integer position
+console.log(seriesIat(s, 2)); // 30
+console.log(seriesIat(s, -1)); // 30
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -266,8 +266,8 @@ dataFrameAt — access by row label and column name
{ x: [1, 2], y: [3, 4] },
{ index: ["r0", "r1"] },
);
-dataFrameAt(df, "r1", "x"); // 2
-dataFrameAt(df, "r0", "y"); // 3
+console.log(dataFrameAt(df, "r1", "x")); // 2
+console.log(dataFrameAt(df, "r0", "y")); // 3
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -304,8 +304,8 @@ dataFrameIat — access by integer row and column position
+console.log(dataFrameIat(df, 0, 1)); // 3 (row 0, column index 1 = "y")
+console.log(dataFrameIat(df, 1, -1)); // 4 (last column, row 1)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/attrs.html b/playground/attrs.html
index 9e747813..52aab333 100644
--- a/playground/attrs.html
+++ b/playground/attrs.html
@@ -180,14 +180,14 @@ Basic usage
notes: "Morning readings",
});
-getAttrs(df);
+console.log(getAttrs(df));
// → { source: "weather_station_42", unit: "Celsius", notes: "Morning readings" }
-getAttr(df, "unit"); // → "Celsius"
-getAttr(df, "missing"); // → undefined
-attrsCount(df); // → 3
-attrsKeys(df); // → ["source", "unit", "notes"]
-hasAttrs(df); // → true
+console.log(getAttr(df, "unit")); // → "Celsius"
+console.log(getAttr(df, "missing")); // → undefined
+console.log(attrsCount(df)); // → 3
+console.log(attrsKeys(df)); // → ["source", "unit", "notes"]
+console.log(hasAttrs(df)); // → true
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -204,14 +204,14 @@ Merging and updating
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -230,17 +230,17 @@ Propagating metadata to derived objects
+console.log(setAttr(derived, "unit", "Fahrenheit"));
+console.log(getAttrs(derived)); // → { unit: "Fahrenheit", source: "sensor_A" }
+console.log(getAttrs(s)); // → { unit: "Celsius", source: "sensor_A" } ← unchanged
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -264,7 +264,7 @@ Fluent helper — withAttrs
);
annotated === annotated; // true — same reference, not a copy
-getAttrs(annotated);
+console.log(getAttrs(annotated));
// → { source: "lab_experiment", date: "2026-04-09" }
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -284,13 +284,13 @@ Merging from multiple sources
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -307,13 +307,13 @@ Clearing metadata
↺ Reset
-
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/between.html b/playground/between.html
index 42d725c0..eec2cda7 100644
--- a/playground/between.html
+++ b/playground/between.html
@@ -192,7 +192,7 @@ seriesBetween — inclusive="both" (default)
import { Series, seriesBetween } from "tsb";
const s = new Series({ data: [1, 2, 3, 4, 5] });
-seriesBetween(s, 2, 4).values;
+console.log(seriesBetween(s, 2, 4).values);
// [false, true, true, true, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -242,13 +242,13 @@ Inclusive options
const s = new Series({ data: [1, 2, 3, 4, 5] });
-seriesBetween(s, 2, 4, { inclusive: "left" }).values;
+console.log(seriesBetween(s, 2, 4, { inclusive: "left" }).values);
// [false, true, true, false, false]
-seriesBetween(s, 2, 4, { inclusive: "right" }).values;
+console.log(seriesBetween(s, 2, 4, { inclusive: "right" }).values);
// [false, false, true, true, false]
-seriesBetween(s, 2, 4, { inclusive: "neither" }).values;
+console.log(seriesBetween(s, 2, 4, { inclusive: "neither" }).values);
// [false, false, true, false, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -291,7 +291,7 @@ Missing values
import { Series, seriesBetween } from "tsb";
const s = new Series({ data: [1, null, NaN, 4] });
-seriesBetween(s, 0, 5).values;
+console.log(seriesBetween(s, 0, 5).values);
// [true, false, false, true]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -333,7 +333,7 @@ String comparison
import { Series, seriesBetween } from "tsb";
const s = new Series({ data: ["apple", "banana", "cherry", "date"] });
-seriesBetween(s, "banana", "cherry").values;
+console.log(seriesBetween(s, "banana", "cherry").values);
// [false, true, true, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/clip_advanced.html b/playground/clip_advanced.html
index a4f5ac8d..8798874a 100644
--- a/playground/clip_advanced.html
+++ b/playground/clip_advanced.html
@@ -194,7 +194,7 @@ Demo 1 — clipAdvancedSeries with scalar bounds
const s = new Series({ data: [-3, 1, 5, 10] });
-clipAdvancedSeries(s, { lower: 0, upper: 6 }).values;
+console.log(clipAdvancedSeries(s, { lower: 0, upper: 6 }).values);
// → [0, 1, 5, 6]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -214,7 +214,7 @@ Demo 2 — clipAdvancedSeries with per-element array bounds
const s = new Series({ data: [-1, 0, 5, 12] });
const lo = [2, -1, 4, 10];
const hi = [5, 3, 8, 11];
-clipAdvancedSeries(s, { lower: lo, upper: hi }).values;
+console.log(clipAdvancedSeries(s, { lower: lo, upper: hi }).values);
// → [2, 0, 5, 11]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -234,7 +234,7 @@ Demo 3 — clipAdvancedSeries with Series bounds
const s = new Series({ data: [0, 5, 10, 15] });
const loBound = new Series({ data: [1, 3, 8, 12] });
const hiBound = new Series({ data: [2, 7, 9, 20] });
-clipAdvancedSeries(s, { lower: loBound, upper: hiBound }).values;
+console.log(clipAdvancedSeries(s, { lower: loBound, upper: hiBound }).values);
// → [1, 5, 9, 15]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -255,8 +255,8 @@ Demo 4 — clipAdvancedDataFrame with DataFrame bounds
const lo = DataFrame.fromColumns({ a: [2, 3, 4], b: [1, 4, 8] });
const hi = DataFrame.fromColumns({ a: [3, 7, 8], b: [5, 9, 12] });
const result = clipAdvancedDataFrame(df, { lower: lo, upper: hi });
-result.col("a").values; // → [2, 5, 8]
-result.col("b").values; // → [2, 6, 10]
+console.log(result.col("a").values); // → [2, 5, 8]
+console.log(result.col("b").values); // → [2, 6, 10]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -276,8 +276,8 @@ Demo 5 — clipAdvancedDataFrame with Series broadcast (axis=1)
const df = DataFrame.fromColumns({ a: [1, 5, 9], b: [2, 6, 10] });
const loPerRow = new Series({ data: [0, 4, 10] });
const result = clipAdvancedDataFrame(df, { lower: loPerRow, axis: 1 });
-result.col("a").values; // → [1, 5, 10]
-result.col("b").values; // → [2, 6, 10]
+console.log(result.col("a").values); // → [1, 5, 10]
+console.log(result.col("b").values); // → [2, 6, 10]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/clip_with_bounds.html b/playground/clip_with_bounds.html
index 27bfd394..f3df881e 100644
--- a/playground/clip_with_bounds.html
+++ b/playground/clip_with_bounds.html
@@ -165,7 +165,7 @@ Example 1 — Series with scalar bounds
const s = new Series({ data: [-5, 1, 7, 12] });
-clipSeriesWithBounds(s, { lower: 0, upper: 8 }).values;
+console.log(clipSeriesWithBounds(s, { lower: 0, upper: 8 }).values);
// [0, 1, 7, 8]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -196,7 +196,7 @@ Example 2 — Series bounds (label-aligned)
index: new Index(["AAPL", "MSFT", "GOOG"]),
});
-clipSeriesWithBounds(prices, { lower: floors }).values;
+console.log(clipSeriesWithBounds(prices, { lower: floors }).values);
// AAPL: max(90, 95)=95 GOOG: max(110, 100)=110 MSFT: max(85, 80)=85 AMZN: 120 (no bound)
// [95, 110, 85, 120]
Click ▶ Run to execute
@@ -227,7 +227,8 @@ Example 3 — DataFrame clip with per-column bounds (axis=1)
const result = clipDataFrameWithBounds(df, { lower: lo, upper: hi, axis: 1 });
// col "a": [1, 5, 10] (lower=1, upper=10)
-// col "b": [4, 8, 9] (lower=4, upper=9)
+// col "b": [4, 8, 9] (lower=4, upper=9)
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -255,7 +256,8 @@ Example 4 — DataFrame clip with per-row bounds (axis=0, default)
const upperBound = new Series({ data: [12, 12, 20, 20] }); // row-specific caps
const result = clipDataFrameWithBounds(df, { lower: lowerBound, upper: upperBound, axis: 0 });
-// min_temp: [0, 0, 1, 4] max_temp: [10, 12, 18, 20]
+// min_temp: [0, 0, 1, 4] max_temp: [10, 12, 18, 20]
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -278,7 +280,8 @@ Example 5 — Element-wise DataFrame bounds
const hi = DataFrame.fromColumns({ a: [8, 8, 8], b: [5, 5, 5] });
const result = clipDataFrameWithBounds(df, { lower: lo, upper: hi });
-// col "a": [3, 5, 8] col "b": [2, 5, 3]
+// col "a": [3, 5, 8] col "b": [2, 5, 3]
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -297,7 +300,7 @@ Null / NaN propagation
import { Series, clipSeriesWithBounds } from "tsb";
const s = new Series({ data: [null, -5, NaN, 10] });
-clipSeriesWithBounds(s, { lower: 0, upper: 8 }).values;
+console.log(clipSeriesWithBounds(s, { lower: 0, upper: 8 }).values);
// [null, 0, NaN, 8]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/combine.html b/playground/combine.html
index 617a8e08..b3114782 100644
--- a/playground/combine.html
+++ b/playground/combine.html
@@ -172,12 +172,12 @@ Code Examples
const b = new Series({ data: [10, 2, 30], index: [0, 1, 2] });
// Element-wise max
-combineSeries(a, b, (x, y) => Math.max(x, y)).values; // [10, 5, 30]
+console.log(combineSeries(a, b, (x, y) => Math.max(x, y)).values); // [10, 5, 30]
// Union index with fillValue=0
const c = new Series({ data: [1, 2], index: ["x", "y"] });
const d = new Series({ data: [10, 30], index: ["x", "z"] });
-combineSeries(c, d, (x, y) => (x ?? 0) + (y ?? 0), 0).values;
+console.log(combineSeries(c, d, (x, y) => (x ?? 0) + (y ?? 0), 0).values);
// x:11, y:2, z:30
// ── DataFrame ───────────────────────────────────────────────────────────────
@@ -185,7 +185,7 @@ Code Examples
const df2 = DataFrame.fromColumns({ a: [10, 2], c: [1000, 2000] });
// Shared column "a": element-wise min; unshared columns processed with fillValue
-combineDataFrame(df1, df2, (p, q) => Math.min(p ?? Infinity, q ?? Infinity));
+console.log(combineDataFrame(df1, df2, (p, q) => Math.min(p ?? Infinity, q ?? Infinity)));
// overwrite: false — unshared columns preserved as-is
combineDataFrame(df1, df2, (p, q) => Math.min(p ?? Infinity, q ?? Infinity),
diff --git a/playground/combine_first.html b/playground/combine_first.html
index 0c664c8d..5ba8f393 100644
--- a/playground/combine_first.html
+++ b/playground/combine_first.html
@@ -173,7 +173,8 @@ Example 1 — Series: fill gaps with values from another Series
// - "x": a has 1 (non-null) → keeps 1
// - "y": a has null → filled from b → 20
// - "z": a has 3 (non-null) → keeps 3
-// - "w": a has no entry → comes from b → 40
+// - "w": a has no entry → comes from b → 40
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -212,7 +213,8 @@ Example 2 — DataFrame: patch missing cells across row/column union
// result["r2"]["y"] = null (no r2 in a, no y in b)
// result["r0"]["z"] = 30 (b only)
// result["r1"]["z"] = null (b has no r1)
-// result["r2"]["z"] = 40 (b only)
+// result["r2"]["z"] = 40 (b only)
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -243,7 +245,8 @@ Example 3 — NaN is treated as missing
const merged = combineFirstSeries(sensor1, sensor2);
// values: [21.0, 22.5, 23.1, 24.0]
-// Gaps in sensor1 filled from sensor2
+// Gaps in sensor1 filled from sensor2
+console.log(merged);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -275,7 +278,8 @@ Example 4 — Temporal data backfill
const complete = combineFirstSeries(primary, backup);
// index: 2024-01, 2024-02, 2024-03, 2024-04, 2024-05, 2024-06
-// values: 100, 101, 102, 103, 104, 106
+// values: 100, 101, 102, 103, 104, 106
+console.log(complete);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/compare.html b/playground/compare.html
index 7978f62d..dfd3fc32 100644
--- a/playground/compare.html
+++ b/playground/compare.html
@@ -170,7 +170,8 @@ 1 — seriesEq with a scalar
// → [false, true, false, true, false]
// Use this as a boolean mask for filtering:
-// s.values.filter((_, i) => result.values[i]) → [2, 2]
+// s.values.filter((_, i) => result.values[i]) → [2, 2]
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -191,7 +192,7 @@ 2 — seriesNe: inequality
const s = new Series({ data: ["apple", "banana", "apple", "cherry"] });
-seriesNe(s, "apple").values;
+console.log(seriesNe(s, "apple").values);
// → [false, true, false, true]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -213,8 +214,8 @@ 3 — Ordering comparisons: lt, gt, le, ge
const scores = new Series({ data: [45, 72, 88, 60, 95] });
-seriesLt(scores, 60).values; // [true, false, false, false, false]
-seriesGe(scores, 60).values; // [false, true, true, true, true]
+console.log(seriesLt(scores, 60).values); // [true, false, false, false, false]
+console.log(seriesGe(scores, 60).values); // [false, true, true, true, true]
// lt and ge are always complementary for finite, non-null values:
// lt[i] !== ge[i] for every i
@@ -239,8 +240,8 @@ 4 — Comparing two Series element-by-element
const actual = new Series({ data: [1, 2, 3, 4] });
const expected = new Series({ data: [1, 3, 3, 2] });
-seriesEq(actual, expected).values; // [true, false, true, false]
-seriesLt(actual, expected).values; // [false, true, false, false]
+console.log(seriesEq(actual, expected).values); // [true, false, true, false]
+console.log(seriesLt(actual, expected).values); // [false, true, false, false]
// Throws RangeError if lengths differ
Click ▶ Run to execute
@@ -264,12 +265,12 @@ 5 — Missing value behaviour
const s = new Series({ data: [1, null, NaN, 3] });
-seriesEq(s, 1).values; // [true, false, false, false]
-seriesNe(s, 1).values; // [false, false, false, true ]
-seriesLt(s, 2).values; // [true, false, false, false]
+console.log(seriesEq(s, 1).values); // [true, false, false, false]
+console.log(seriesNe(s, 1).values); // [false, false, false, true ]
+console.log(seriesLt(s, 2).values); // [true, false, false, false]
// null eq null → false (NaN != NaN convention)
-seriesEq(s, null).values; // [false, false, false, false]
+console.log(seriesEq(s, null).values); // [false, false, false, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -293,10 +294,10 @@ 6 — DataFrame comparison with a scalar
science: [60, 45, 91],
});
-dataFrameGt(df, 60).col("math").values;
+console.log(dataFrameGt(df, 60).col("math").values);
// → [false, true, true]
-dataFrameLe(df, 60).col("science").values;
+console.log(dataFrameLe(df, 60).col("science").values);
// → [true, true, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -319,8 +320,8 @@ 7 — DataFrame compared against another DataFrame
const df1 = DataFrame.fromColumns({ a: [1, 2], b: [3, 4] });
const df2 = DataFrame.fromColumns({ a: [1, 0], b: [3, 5] });
-dataFrameEq(df1, df2).col("a").values; // [true, false]
-dataFrameEq(df1, df2).col("b").values; // [true, false]
+console.log(dataFrameEq(df1, df2).col("a").values); // [true, false]
+console.log(dataFrameEq(df1, df2).col("b").values); // [true, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -345,7 +346,7 @@ 8 — Combining with whereSeries for conditional selection
const isWarm = seriesGe(temps, 20); // [false, true, true, false, true]
const warmOnly = whereSeries(temps, isWarm);
-warmOnly.values; // [null, 22, 30, null, 27]
+console.log(warmOnly.values); // [null, 22, 30, null, 27]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/corrwith.html b/playground/corrwith.html
index eb19c248..507460d4 100644
--- a/playground/corrwith.html
+++ b/playground/corrwith.html
@@ -197,15 +197,15 @@ autoCorr — lag-N autocorrelation
import { Series, autoCorr } from "tsb";
const s = new Series({ data: [1, 2, 3, 4, 5] });
-autoCorr(s); // lag=1 → 1.0
-autoCorr(s, 0); // lag=0 → 1.0 (always)
-autoCorr(s, 2); // lag=2 → 1.0
+console.log(autoCorr(s)); // lag=1 → 1.0
+console.log(autoCorr(s, 0)); // lag=0 → 1.0 (always)
+console.log(autoCorr(s, 2)); // lag=2 → 1.0
const alt = new Series({ data: [1, -1, 1, -1, 1, -1] });
-autoCorr(alt, 1); // -1.0
+console.log(autoCorr(alt, 1)); // -1.0
const flat = new Series({ data: [5, 5, 5, 5] });
-autoCorr(flat, 1); // NaN
+console.log(autoCorr(flat, 1)); // NaN
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -258,7 +258,8 @@ corrWith — DataFrame correlated with a Series
const s = new Series({ data: [1, 2, 3, 4, 5] });
const result = corrWith(df, s);
-// Series(A=1.0, B=-1.0) indexed by column names
+// Series(A=1.0, B=-1.0) indexed by column names
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -316,11 +317,11 @@ corrWith — DataFrame correlated with another DataFrame
const df1 = DataFrame.fromColumns({ A: [1, 2, 3], B: [4, 5, 6] });
const df2 = DataFrame.fromColumns({ A: [1, 2, 3], B: [6, 5, 4] });
-corrWith(df1, df2); // A=1.0, B=-1.0
+console.log(corrWith(df1, df2)); // A=1.0, B=-1.0
const df3 = DataFrame.fromColumns({ A: [1, 2, 3], C: [7, 8, 9] });
-corrWith(df1, df3); // A=1.0, B=NaN, C=NaN
-corrWith(df1, df3, { drop: true }); // A=1.0
+console.log(corrWith(df1, df3)); // A=1.0, B=NaN, C=NaN
+console.log(corrWith(df1, df3, { drop: true })); // A=1.0
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -371,7 +372,7 @@ corrWith — axis=1 (row-wise correlation)
const df = DataFrame.fromColumns({ A: [1, 2], B: [2, 4], C: [3, 6] });
const s = new Series({ data: [1, 2, 3] });
-corrWith(df, s, { axis: 1 });
+console.log(corrWith(df, s, { axis: 1 }));
// Series([1.0, 1.0]) indexed by row labels [0, 1]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/cut_bins_to_frame.html b/playground/cut_bins_to_frame.html
index 4a89d55e..2f7e3a46 100644
--- a/playground/cut_bins_to_frame.html
+++ b/playground/cut_bins_to_frame.html
@@ -177,7 +177,8 @@ What it does
// { "(0.0, 25.0]": 5, "(25.0, 50.0]": 6, ... }
// Just edges indexed by label
-const edges = binEdges(result);
+const edges = binEdges(result);
+console.log(edges);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/cut_qcut.html b/playground/cut_qcut.html
index a3ac8533..b500e7e3 100644
--- a/playground/cut_qcut.html
+++ b/playground/cut_qcut.html
@@ -173,7 +173,8 @@ Integer bins
// labels: ["(5.0, 26.7]", "(26.7, 48.3]", "(48.3, 70.0]"]
// bins: [4.935, 26.667, 48.333, 70]
// codes: [0, 0, 0, 1, 1, 2]
-console.table(ages.map((a, i) => ({ age: a, bin: labels[codes[i]!] })));
+console.table(ages.map((a, i) => ({ age: a, bin: labels[codes[i]!] })));
+console.log(ages);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -196,7 +197,8 @@ Explicit bin edges
});
// codes: [0, 1, 2, 3, 4, 4]
// labels[codes[0]] → "F"
-// labels[codes[5]] → "A"
+// labels[codes[5]] → "A"
+console.log(scores);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -218,7 +220,8 @@ Quartile split
const { codes, labels, bins } = qcut(values, 4);
// labels: ["[1, 3.25]", "(3.25, 5.5]", "(5.5, 7.75]", "(7.75, 10]"]
-// Every bin has ~2-3 elements
+// Every bin has ~2-3 elements
+console.log(values);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/date-offset.html b/playground/date-offset.html
index a779f47e..5136589b 100644
--- a/playground/date-offset.html
+++ b/playground/date-offset.html
@@ -173,7 +173,8 @@ 2 — Fixed-time offsets (Day, Hour, Minute, Second, Milli)
new Hour(2).apply(d).toISOString(); // "2024-01-01T02:00:00.000Z"
new Minute(90).apply(d).toISOString(); // "2024-01-01T01:30:00.000Z"
new Second(30).apply(d).toISOString(); // "2024-01-01T00:00:30.000Z"
-new Milli(500).apply(d).getTime() - d.getTime(); // 500
+new Milli(500).apply(d).getTime() - d.getTime(); // 500
+console.log(d);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -202,16 +203,16 @@ 3 — Week offset
// Weekday-aligned (weekday=0 → Monday)
const wk = new Week(1, { weekday: 0 });
-wk.apply(wed).toISOString().slice(0, 10); // "2024-01-22" (next Mon)
-wk.apply(mon).toISOString().slice(0, 10); // "2024-01-22" (Mon → next Mon)
+console.log(wk.apply(wed).toISOString().slice(0, 10)); // "2024-01-22" (next Mon)
+console.log(wk.apply(mon).toISOString().slice(0, 10)); // "2024-01-22" (Mon → next Mon)
// Rollforward / rollback
-wk.rollforward(wed).toISOString().slice(0, 10); // "2024-01-22"
-wk.rollback(wed).toISOString().slice(0, 10); // "2024-01-15"
+console.log(wk.rollforward(wed).toISOString().slice(0, 10)); // "2024-01-22"
+console.log(wk.rollback(wed).toISOString().slice(0, 10)); // "2024-01-15"
// onOffset
-wk.onOffset(mon); // true
-wk.onOffset(wed); // false
+console.log(wk.onOffset(mon)); // true
+console.log(wk.onOffset(wed)); // false
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -248,7 +249,8 @@ 4 — MonthEnd & MonthBegin
new MonthBegin(-1).apply(mid).toISOString().slice(0, 10); // "2024-01-01"
new MonthBegin(0).rollforward(mid).toISOString().slice(0, 10); // "2024-02-01"
-new MonthBegin(0).rollback(mid).toISOString().slice(0, 10); // "2024-01-01"
+new MonthBegin(0).rollback(mid).toISOString().slice(0, 10); // "2024-01-01"
+console.log(end);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -279,7 +281,8 @@ 5 — YearEnd & YearBegin
const yr2024 = new Date(Date.UTC(2024, 11, 31));
new YearEnd(0).rollforward(yr2024).toISOString().slice(0, 10); // "2024-12-31"
-new YearEnd(0).rollback(d).toISOString().slice(0, 10); // "2023-12-31"
+new YearEnd(0).rollback(d).toISOString().slice(0, 10); // "2023-12-31"
+console.log(yr2024);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -316,7 +319,8 @@ 6 — BusinessDay
new BusinessDay(0).rollback(sat).toISOString().slice(0, 10); // "2024-01-12"
new BusinessDay(0).onOffset(fri); // true
-new BusinessDay(0).onOffset(sat); // false
+new BusinessDay(0).onOffset(sat); // false
+console.log(sat);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -344,7 +348,7 @@ 7 — multiply & negate
const bday = new BusinessDay(3);
const fri = new Date(Date.UTC(2024, 0, 12));
-bday.negate().apply(bday.apply(fri)).toISOString().slice(0, 10); // "2024-01-12"
+console.log(bday.negate().apply(bday.apply(fri)).toISOString().slice(0, 10)); // "2024-01-12"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -365,10 +369,10 @@ 8 — Static factory methods
const d = new Date(Date.UTC(2024, 0, 15));
-Day.of(5).apply(d).toISOString().slice(0, 10); // "2024-01-20"
-MonthEnd.of(1).apply(d).toISOString().slice(0, 10); // "2024-01-31"
-Week.of(1, { weekday: 0 }).apply(d).toISOString().slice(0, 10); // "2024-01-22"
-BusinessDay.of(2).apply(d).toISOString().slice(0, 10); // "2024-01-17"
+console.log(Day.of(5).apply(d).toISOString().slice(0, 10)); // "2024-01-20"
+console.log(MonthEnd.of(1).apply(d).toISOString().slice(0, 10)); // "2024-01-31"
+console.log(Week.of(1, { weekday: 0 }).apply(d).toISOString().slice(0, 10)); // "2024-01-22"
+console.log(BusinessDay.of(2).apply(d).toISOString().slice(0, 10)); // "2024-01-17"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/dot_matmul.html b/playground/dot_matmul.html
index 9f53494f..fa74a324 100644
--- a/playground/dot_matmul.html
+++ b/playground/dot_matmul.html
@@ -167,16 +167,16 @@ API
import { seriesDotSeries, seriesDotDataFrame, dataFrameDotSeries, dataFrameDotDataFrame } from "tsb";
// Series · Series → scalar
-seriesDotSeries(a, b);
+console.log(seriesDotSeries(a, b));
// Series · DataFrame → Series
-seriesDotDataFrame(s, df);
+console.log(seriesDotDataFrame(s, df));
// DataFrame · Series → Series
-dataFrameDotSeries(df, s);
+console.log(dataFrameDotSeries(df, s));
// DataFrame · DataFrame → DataFrame
-dataFrameDotDataFrame(A, B);
+console.log(dataFrameDotDataFrame(A, B));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -196,17 +196,17 @@ Examples
// Series dot product
const a = new Series({ data: [1, 2, 3], index: ["x","y","z"] });
const b = new Series({ data: [4, 5, 6], index: ["x","y","z"] });
-seriesDotSeries(a, b); // 1*4 + 2*5 + 3*6 = 32
+console.log(seriesDotSeries(a, b)); // 1*4 + 2*5 + 3*6 = 32
// DataFrame · vector
const df = DataFrame.fromColumns({ a: [1, 2], b: [3, 4] });
const v = new Series({ data: [1, 1], index: ["a", "b"] });
-dataFrameDotSeries(df, v).values; // [4, 6] (row sums)
+console.log(dataFrameDotSeries(df, v).values); // [4, 6] (row sums)
// Matrix multiply
const A = DataFrame.fromColumns({ k: [1, 2] }); // 2×1
// ... B with row index ["k"] ...
-dataFrameDotDataFrame(A, B).col("r").values; // [3, 6]
+console.log(dataFrameDotDataFrame(A, B).col("r").values); // [3, 6]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/dropna.html b/playground/dropna.html
index 73aa6480..b8d57d92 100644
--- a/playground/dropna.html
+++ b/playground/dropna.html
@@ -166,8 +166,8 @@ Example 1 — Series: drop missing elements
const s = new Series({ data: [1, null, NaN, 4, undefined, 6] });
const clean = dropna(s);
-clean.values; // [1, 4, 6]
-clean.size; // 3
+console.log(clean.values); // [1, 4, 6]
+console.log(clean.size); // 3
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -193,7 +193,7 @@ Example 2 — DataFrame: drop rows with any missing value (default)
// Drop any row that has at least one null
const clean = dropna(df);
-clean.shape; // [1, 3] — only "Alice" row survives (score=95, grade="A")
+console.log(clean.shape); // [1, 3] — only "Alice" row survives (score=95, grade="A")
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -219,7 +219,7 @@ Example 3 — how = "all": only drop fully-null rows
// Row 1: both null → dropped
// Row 0 and Row 2: at least one non-null → kept
const clean = dropna(df, { how: "all" });
-clean.shape; // [2, 2]
+console.log(clean.shape); // [2, 2]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -248,7 +248,7 @@ Example 4 — thresh: require at least N non-null values
// Row 1: 0 present → drop
// Row 2: 2 present → keep
const clean = dropna(df, { thresh: 2 });
-clean.shape; // [2, 3]
+console.log(clean.shape); // [2, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -275,7 +275,7 @@ Example 5 — subset: only check specific columns
// Only check the "score" column for nulls — ignore "notes"
const clean = dropna(df, { subset: ["score"] });
// Row 1 (score=null) is dropped; Row 2 (notes=null but score=88) is kept.
-clean.shape; // [2, 3]
+console.log(clean.shape); // [2, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -300,8 +300,8 @@ Example 6 — axis = 1: drop columns with missing values
});
const clean = dropna(df, { axis: 1 });
-clean.columns.toArray(); // ["b"]
-clean.shape; // [3, 1]
+console.log(clean.columns.toArray()); // ["b"]
+console.log(clean.shape); // [3, 1]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -326,7 +326,7 @@ Example 7 — axis = 1, how = "all": only drop all-null columns
});
const clean = dropna(df, { axis: 1, how: "all" });
-clean.columns.toArray(); // ["b", "c"]
+console.log(clean.columns.toArray()); // ["b", "c"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/duplicated.html b/playground/duplicated.html
index 21b3fffd..0f03a116 100644
--- a/playground/duplicated.html
+++ b/playground/duplicated.html
@@ -170,7 +170,7 @@ Example 1 — Basic: find duplicate rows
// Row 2 ("Alice", 90) is a duplicate of Row 0
const mask = duplicatedDataFrame(df);
-mask.values; // [false, false, true, false]
+console.log(mask.values); // [false, false, true, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -194,7 +194,7 @@ Example 2 — Drop duplicate rows
});
const deduped = dropDuplicatesDataFrame(df);
-deduped.shape; // [3, 2] — "Alice" row 2 removed
+console.log(deduped.shape); // [3, 2] — "Alice" row 2 removed
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -219,7 +219,7 @@ Example 3 — subset: only check specific columns
// Drop based on "id" only — row 2 (id=1) is dup even though value differs
const deduped = dropDuplicatesDataFrame(df, { subset: ["id"] });
-deduped.shape; // [3, 2]
+console.log(deduped.shape); // [3, 2]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -242,11 +242,11 @@ Example 4 — keep="last": keep the last occurrence
});
// keep="last" → mark the FIRST occurrence of each dup, keep the last
-duplicatedDataFrame(df, { keep: "last" }).values;
+console.log(duplicatedDataFrame(df, { keep: "last" }).values);
// [true, false, false, false]
// keep=false → mark ALL occurrences of any duplicate
-duplicatedDataFrame(df, { keep: false }).values;
+console.log(duplicatedDataFrame(df, { keep: false }).values);
// [true, false, true, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -267,11 +267,11 @@ Example 5 — Series: deduplicate values
const s = new Series({ data: [1, 2, 1, 3, 2, 4] });
-duplicatedSeries(s).values; // [false, false, true, false, true, false]
-dropDuplicatesSeries(s).values; // [1, 2, 3, 4]
+console.log(duplicatedSeries(s).values); // [false, false, true, false, true, false]
+console.log(dropDuplicatesSeries(s).values); // [1, 2, 3, 4]
// keep=false → mark all duplicate values
-duplicatedSeries(s, { keep: false }).values;
+console.log(duplicatedSeries(s, { keep: false }).values);
// [true, true, true, false, true, false]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/eval_query.html b/playground/eval_query.html
index 9e2bdedb..f0e5d47a 100644
--- a/playground/eval_query.html
+++ b/playground/eval_query.html
@@ -186,26 +186,26 @@ queryDataFrame(df, expr)
});
// Simple comparison
-queryDataFrame(df, "age > 28");
+console.log(queryDataFrame(df, "age > 28"));
// name: ["Bob", "Dave"] age: [32, 45] score: [72, 60]
// Combined conditions
-queryDataFrame(df, "age < 35 and score >= 85");
+console.log(queryDataFrame(df, "age < 35 and score >= 85"));
// name: ["Alice", "Carol"]
// String equality
-queryDataFrame(df, "name == 'Alice'");
+console.log(queryDataFrame(df, "name == 'Alice'"));
// single row
// 'in' operator
-queryDataFrame(df, "name in ['Alice', 'Carol']");
+console.log(queryDataFrame(df, "name in ['Alice', 'Carol']"));
// 'not in' operator
-queryDataFrame(df, "age not in [25, 45]");
+console.log(queryDataFrame(df, "age not in [25, 45]"));
// Backtick-quoted column (for names with spaces)
const df2 = DataFrame.fromArrays({ "first name": ["Alice", "Bob"] });
-queryDataFrame(df2, "`first name` == 'Alice'");
+console.log(queryDataFrame(df2, "`first name` == 'Alice'"));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -228,20 +228,20 @@ evalDataFrame(df, expr)
});
// Arithmetic expression → new Series
-evalDataFrame(sales, "price * qty");
+console.log(evalDataFrame(sales, "price * qty"));
// Series [1000, 1250, 1000, 400]
// Boolean expression (useful as a mask)
-evalDataFrame(sales, "price > 10");
+console.log(evalDataFrame(sales, "price > 10"));
// Series [false, true, false, true]
// Function calls
-evalDataFrame(sales, "round(price * qty / 100, 1)");
+console.log(evalDataFrame(sales, "round(price * qty / 100, 1)"));
// Series [10.0, 12.5, 10.0, 4.0]
// String operations
const df3 = DataFrame.fromArrays({ tag: ["Foo", "Bar", "Baz"] });
-evalDataFrame(df3, "lower(tag)");
+console.log(evalDataFrame(df3, "lower(tag)"));
// Series ["foo", "bar", "baz"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/excel.html b/playground/excel.html
index 17450425..20468164 100644
--- a/playground/excel.html
+++ b/playground/excel.html
@@ -221,9 +221,9 @@ Advanced example
const df3 = readExcel(buffer, { naValues: ["N/A", "MISSING", "-"] });
// DataFrame operations work immediately
-df.describe();
-df.col("revenue").sum();
-df.groupby("region").mean();
+console.log(df.describe());
+console.log(df.col("revenue").sum());
+console.log(df.groupby("region").mean());
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/fillna.html b/playground/fillna.html
index 503664b4..4f04fdeb 100644
--- a/playground/fillna.html
+++ b/playground/fillna.html
@@ -167,11 +167,11 @@ 1 · Scalar fill
import { Series, fillnaSeries } from "tsb";
const s = new Series({ data: [1, null, null, 4] });
-fillnaSeries(s, { value: 0 }).values;
+console.log(fillnaSeries(s, { value: 0 }).values);
// → [1, 0, 0, 4]
const t = new Series({ data: [NaN, 2, NaN] });
-fillnaSeries(t, { value: 99 }).values;
+console.log(fillnaSeries(t, { value: 99 }).values);
// → [99, 2, 99]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -194,12 +194,12 @@ 2 · Forward fill (ffill / pad)
import { Series, fillnaSeries } from "tsb";
const s = new Series({ data: [null, 1, null, null, 4] });
-fillnaSeries(s, { method: "ffill" }).values;
+console.log(fillnaSeries(s, { method: "ffill" }).values);
// → [null, 1, 1, 1, 4]
// Trailing nulls are filled too
const t = new Series({ data: [1, null, null] });
-fillnaSeries(t, { method: "ffill" }).values;
+console.log(fillnaSeries(t, { method: "ffill" }).values);
// → [1, 1, 1]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -222,12 +222,12 @@ 3 · Backward fill (bfill / backfill)
import { Series, fillnaSeries } from "tsb";
const s = new Series({ data: [null, null, 3, null, 5] });
-fillnaSeries(s, { method: "bfill" }).values;
+console.log(fillnaSeries(s, { method: "bfill" }).values);
// → [3, 3, 3, 5, 5]
// Leading nulls are filled from the first known value
const t = new Series({ data: [null, null, 10] });
-fillnaSeries(t, { method: "bfill" }).values;
+console.log(fillnaSeries(t, { method: "bfill" }).values);
// → [10, 10, 10]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -250,11 +250,11 @@ 4 · Limiting the fill — limit
// Only fill up to 1 consecutive missing value
const s = new Series({ data: [1, null, null, null, 5] });
-fillnaSeries(s, { method: "ffill", limit: 1 }).values;
+console.log(fillnaSeries(s, { method: "ffill", limit: 1 }).values);
// → [1, 1, null, null, 5]
// bfill with limit=2
-fillnaSeries(s, { method: "bfill", limit: 2 }).values;
+console.log(fillnaSeries(s, { method: "bfill", limit: 2 }).values);
// → [null, null, 5, 5, 5]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -281,8 +281,8 @@ 5 · DataFrame — scalar fill
});
const result = fillnaDataFrame(df, { value: 0 });
-result.col("a").values; // [1, 0, 3]
-result.col("b").values; // [0, 2, 0]
+console.log(result.col("a").values); // [1, 0, 3]
+console.log(result.col("b").values); // [0, 2, 0]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -309,9 +309,9 @@ 6 · DataFrame — per-column fill map
});
const result = fillnaDataFrame(df, { value: { a: -1, b: 99 } });
-result.col("a").values; // [-1, 2, -1]
-result.col("b").values; // [1, 99, 3]
-result.col("c").values; // [null, null, null] ← untouched
+console.log(result.col("a").values); // [-1, 2, -1]
+console.log(result.col("b").values); // [1, 99, 3]
+console.log(result.col("c").values); // [null, null, null] ← untouched
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -340,9 +340,9 @@ 7 · DataFrame — method fill (axis=0 / axis=1)
// axis=0 (default): ffill down each column
const byCol = fillnaDataFrame(df, { method: "ffill" });
-byCol.col("a").values; // [1, 1, 1]
-byCol.col("b").values; // [null, 2, 2]
-byCol.col("c").values; // [null, null, 3]
+console.log(byCol.col("a").values); // [1, 1, 1]
+console.log(byCol.col("b").values); // [null, 2, 2]
+console.log(byCol.col("c").values); // [null, null, 3]
// axis=1: bfill across each row
const byRow = fillnaDataFrame(df, { method: "bfill", axis: 1 });
@@ -381,8 +381,8 @@ 8 · DataFrame — fill values from a Series
});
const result = fillnaDataFrame(df, { value: fills });
-result.col("price").values; // [10, 0, 30]
-result.col("volume").values; // [0, 200, 0]
+console.log(result.col("price").values); // [10, 0, 30]
+console.log(result.col("volume").values); // [0, 200, 0]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/filter.html b/playground/filter.html
index 55522997..df7fce5d 100644
--- a/playground/filter.html
+++ b/playground/filter.html
@@ -187,7 +187,7 @@ filterDataFrame — by items (column names)
import { DataFrame, filterDataFrame } from "tsb";
const df = DataFrame.fromColumns({ one: [1, 2], two: [3, 4], three: [5, 6] });
-filterDataFrame(df, { items: ["one", "three"] }).columns.values;
+console.log(filterDataFrame(df, { items: ["one", "three"] }).columns.values);
// ["one", "three"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -229,7 +229,7 @@ filterDataFrame — by like (substring)
import { DataFrame, filterDataFrame } from "tsb";
const df = DataFrame.fromColumns({ apple: [1], apricot: [2], banana: [3] });
-filterDataFrame(df, { like: "ap" }).columns.values;
+console.log(filterDataFrame(df, { like: "ap" }).columns.values);
// ["apple", "apricot"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -271,7 +271,7 @@ filterDataFrame — by regex
import { DataFrame, filterDataFrame } from "tsb";
const df = DataFrame.fromColumns({ a1: [1], a2: [2], b1: [3], b2: [4] });
-filterDataFrame(df, { regex: "^a" }).columns.values;
+console.log(filterDataFrame(df, { regex: "^a" }).columns.values);
// ["a1", "a2"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -316,7 +316,7 @@ filterDataFrame — filter rows (axis=0)
import { DataFrame, filterDataFrame } from "tsb";
const df = DataFrame.fromColumns({ x: [10, 20, 30] }, { index: ["foo", "bar", "baz"] });
-filterDataFrame(df, { like: "ba", axis: 0 }).index.values;
+console.log(filterDataFrame(df, { like: "ba", axis: 0 }).index.values);
// ["bar", "baz"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -358,7 +358,7 @@ filterSeries — by label
import { Series, filterSeries } from "tsb";
const s = new Series({ data: [1, 2, 3, 4], index: ["alpha", "beta", "gamma", "aleph"] });
-filterSeries(s, { like: "al" }).index.values;
+console.log(filterSeries(s, { like: "al" }).index.values);
// ["alpha", "aleph"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/format_ops.html b/playground/format_ops.html
index 9865ec42..d8ce6c3d 100644
--- a/playground/format_ops.html
+++ b/playground/format_ops.html
@@ -173,9 +173,9 @@ Formatter factories
const fmtPct = makePercentFormatter(1); // (v) => formatPercent(v, 1)
const fmtDollar = makeCurrencyFormatter("$"); // (v) => formatCurrency(v, "$", 2)
-fmtFloat(3.14159); // "3.142"
-fmtPct(0.0825); // "8.3%"
-fmtDollar(9999.99); // "$9,999.99"
+console.log(fmtFloat(3.14159)); // "3.142"
+console.log(fmtPct(0.0825)); // "8.3%"
+console.log(fmtDollar(9999.99)); // "$9,999.99"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -196,7 +196,8 @@ Apply to a Series
const returns = new Series({ data: [0.05, -0.02, 0.134, 0.007], name: "returns" });
const formatted = applySeriesFormatter(returns, makePercentFormatter(1));
-// Series<string> ["5.0%", "-2.0%", "13.4%", "0.7%"]
+// Series<string> ["5.0%", "-2.0%", "13.4%", "0.7%"]
+console.log(formatted);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -229,7 +230,8 @@ Apply to a DataFrame
// price: ["$1,299.99", "$899.50", "$45.00"],
// change: ["2.50%", "-3.10%", "10.20%"],
// volume: ["15000", "8200", "230000"], // no formatter → String(v)
-// }
+// }
+console.log(formatted);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/infer_dtype.html b/playground/infer_dtype.html
index c49c0d17..b7d94f53 100644
--- a/playground/infer_dtype.html
+++ b/playground/infer_dtype.html
@@ -163,14 +163,14 @@ Example 1 — basic scalar types
import { inferDtype } from "tsb";
-inferDtype([1, 2, 3]); // "integer"
-inferDtype([1.1, 2.2, 3.3]); // "floating"
-inferDtype([1, 2.5, 3]); // "mixed-integer-float"
-inferDtype([true, false, true]); // "boolean"
-inferDtype(["a", "b", "c"]); // "string"
-inferDtype([]); // "empty"
-inferDtype([null, null]); // "empty" (skipna=true by default)
-inferDtype([null, null], { skipna: false }); // "mixed"
+console.log(inferDtype([1, 2, 3])); // "integer"
+console.log(inferDtype([1.1, 2.2, 3.3])); // "floating"
+console.log(inferDtype([1, 2.5, 3])); // "mixed-integer-float"
+console.log(inferDtype([true, false, true])); // "boolean"
+console.log(inferDtype(["a", "b", "c"])); // "string"
+console.log(inferDtype([])); // "empty"
+console.log(inferDtype([null, null])); // "empty" (skipna=true by default)
+console.log(inferDtype([null, null], { skipna: false })); // "mixed"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -189,13 +189,13 @@ Example 2 — working with Series
import { Series, inferDtype } from "tsb";
const s1 = new Series({ data: [10, 20, 30] });
-inferDtype(s1); // "integer"
+console.log(inferDtype(s1)); // "integer"
const s2 = new Series({ data: ["hello", "world"] });
-inferDtype(s2); // "string"
+console.log(inferDtype(s2)); // "string"
const s3 = new Series({ data: [1, null, 2, null, 3] });
-inferDtype(s3); // "integer" (nulls skipped by default)
+console.log(inferDtype(s3)); // "integer" (nulls skipped by default)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -213,16 +213,16 @@ Example 3 — specialised tsb types
import { inferDtype, Timestamp, Timedelta, Period, Interval } from "tsb";
-inferDtype([Timestamp.fromtimestamp(0), Timestamp.fromtimestamp(1)]);
+console.log(inferDtype([Timestamp.fromtimestamp(0), Timestamp.fromtimestamp(1)]));
// "datetime"
-inferDtype([Timedelta.fromComponents({ days: 1 }), Timedelta.fromComponents({ hours: 2 })]);
+console.log(inferDtype([Timedelta.fromComponents({ days: 1 }), Timedelta.fromComponents({ hours: 2 })]));
// "timedelta"
-inferDtype([Period.fromDate(new Date("2024-01-01T00:00:00Z"), "M")]);
+console.log(inferDtype([Period.fromDate(new Date("2024-01-01T00:00:00Z"), "M")]));
// "period"
-inferDtype([new Interval(0, 1), new Interval(1, 2)]);
+console.log(inferDtype([new Interval(0, 1), new Interval(1, 2)]));
// "interval"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -241,11 +241,11 @@ Example 4 — mixed types
import { inferDtype } from "tsb";
-inferDtype([1, "a", 2]); // "mixed-integer" (int + non-numeric non-float)
-inferDtype(["a", true, null]); // "mixed" (string + bool)
-inferDtype([1n, 2n, 3n]); // "integer" (bigint only)
-inferDtype([1n, 2]); // "decimal" (bigint + integer)
-inferDtype([1n, 2.5]); // "mixed-integer-float"
+console.log(inferDtype([1, "a", 2])); // "mixed-integer" (int + non-numeric non-float)
+console.log(inferDtype(["a", true, null])); // "mixed" (string + bool)
+console.log(inferDtype([1n, 2n, 3n])); // "integer" (bigint only)
+console.log(inferDtype([1n, 2])); // "decimal" (bigint + integer)
+console.log(inferDtype([1n, 2.5])); // "mixed-integer-float"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/infer_objects.html b/playground/infer_objects.html
index 2a0e6d1d..4b697337 100644
--- a/playground/infer_objects.html
+++ b/playground/infer_objects.html
@@ -166,19 +166,19 @@ inferObjectsSeries — promote object → typed
// Object series holding integers
const s = new Series({ data: [1, 2, 3], dtype: Dtype.object });
-s.dtype.kind; // "object"
+console.log(s.dtype.kind); // "object"
const better = inferObjectsSeries(s);
-better.dtype.kind; // "int"
-better.values; // [1, 2, 3]
+console.log(better.dtype.kind); // "int"
+console.log(better.values); // [1, 2, 3]
// Mixed types — cannot infer, returns original
const mixed = new Series({ data: [1, "a", true], dtype: Dtype.object });
-inferObjectsSeries(mixed).dtype.kind; // "object"
+console.log(inferObjectsSeries(mixed).dtype.kind); // "object"
// All null — no inference possible
const nulls = new Series({ data: [null, null], dtype: Dtype.object });
-inferObjectsSeries(nulls).dtype.kind; // "object"
+console.log(inferObjectsSeries(nulls).dtype.kind); // "object"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -204,10 +204,10 @@ inferObjectsDataFrame — all columns at once
});
const inferred = inferObjectsDataFrame(df);
-inferred.col("ints").dtype.kind; // "int"
-inferred.col("floats").dtype.kind; // "float"
-inferred.col("strs").dtype.kind; // "string"
-inferred.col("bools").dtype.kind; // "bool"
+console.log(inferred.col("ints").dtype.kind); // "int"
+console.log(inferred.col("floats").dtype.kind); // "float"
+console.log(inferred.col("strs").dtype.kind); // "string"
+console.log(inferred.col("bools").dtype.kind); // "bool"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -228,21 +228,21 @@ convertDtypesSeries — also parses numeric strings
// String values that look like integers
const ints = new Series({ data: ["1", "2", "3"] });
const result = convertDtypesSeries(ints);
-result.dtype.kind; // "int"
-result.values; // [1, 2, 3]
+console.log(result.dtype.kind); // "int"
+console.log(result.values); // [1, 2, 3]
// String values that look like floats
const floats = new Series({ data: ["1.5", "2.5", "3.5"] });
-convertDtypesSeries(floats).dtype.kind; // "float"
+console.log(convertDtypesSeries(floats).dtype.kind); // "float"
// Non-numeric strings: unchanged
const text = new Series({ data: ["apple", "banana"] });
-convertDtypesSeries(text); // same Series, dtype "string"
+console.log(convertDtypesSeries(text)); // same Series, dtype "string"
// Int series with nulls → can convert to float for NA safety
import { Dtype } from "tsb";
const withNull = new Series({ data: [1, null, 3], dtype: Dtype.int64 });
-convertDtypesSeries(withNull, { convertIntegerToFloat: true }).dtype.kind;
+console.log(convertDtypesSeries(withNull, { convertIntegerToFloat: true }).dtype.kind);
// "float" (null becomes NaN-compatible)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -269,9 +269,9 @@ convertDtypesDataFrame — per-column conversion
});
const typed = convertDtypesDataFrame(raw);
-typed.col("age").dtype.kind; // "int"
-typed.col("score").dtype.kind; // "float"
-typed.col("name").dtype.kind; // "string" (unchanged — not numeric)
+console.log(typed.col("age").dtype.kind); // "int"
+console.log(typed.col("score").dtype.kind); // "float"
+console.log(typed.col("name").dtype.kind); // "string" (unchanged — not numeric)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/insert_pop.html b/playground/insert_pop.html
index 5cdfcfb5..ca7b4eb6 100644
--- a/playground/insert_pop.html
+++ b/playground/insert_pop.html
@@ -175,7 +175,8 @@ Example 1 — insertColumn
// df2.col("city").values → ["NY", "LA", "SF"]
// Original is unchanged
-// df.columns.values → ["name", "age"]
+// df.columns.values → ["name", "age"]
+console.log(df2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -197,7 +198,8 @@ Example 2 — Insert with a Series
const salary = new Series({ data: [100_000, 90_000, 120_000], name: "salary" });
const df2 = insertColumn(df, 0, "salary", salary);
-// df2.columns.values → ["salary", "a", "b"]
+// df2.columns.values → ["salary", "a", "b"]
+console.log(df2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -225,7 +227,8 @@ Example 3 — popColumn
const { series: ageSeries, df: df2 } = popColumn(df, "age");
// ageSeries.values → [30, 25, 35]
// df2.columns.values → ["id", "name"]
-// df.columns.values → ["id", "name", "age"] ← original unchanged
+// df.columns.values → ["id", "name", "age"] ← original unchanged
+console.log(df);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -251,7 +254,8 @@ Example 4 — reorderColumns
// Select a subset (drops columns not listed)
const df3 = reorderColumns(df, ["a", "c"]);
-// df3.columns.values → ["a", "c"] (b and d are dropped)
+// df3.columns.values → ["a", "c"] (b and d are dropped)
+console.log(df3);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -278,7 +282,8 @@ Example 5 — moveColumn
// Move "label" to the front
const df2 = moveColumn(df, "label", 0);
-// df2.columns.values → ["label", "year", "value"]
+// df2.columns.values → ["label", "year", "value"]
+console.log(df2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -295,19 +300,19 @@ Error cases
// Duplicate column name (default: not allowed)
-insertColumn(df, 1, "a", [1, 2, 3]);
+console.log(insertColumn(df, 1, "a", [1, 2, 3]));
// → RangeError: Column "a" already exists. Use allowDuplicates=true to permit...
// Out-of-range loc
-insertColumn(df, 99, "x", [1, 2, 3]);
+console.log(insertColumn(df, 99, "x", [1, 2, 3]));
// → RangeError: loc=99 is out of range [0, 2].
// Wrong number of values
-insertColumn(df, 0, "x", [1]); // df has 3 rows
+console.log(insertColumn(df, 0, "x", [1])); // df has 3 rows
// → RangeError: values length 1 does not match DataFrame row count 3.
// Column not found
-popColumn(df, "missing");
+console.log(popColumn(df, "missing"));
// → RangeError: Column "missing" not found in DataFrame.
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/interpolate.html b/playground/interpolate.html
index e5d2d744..8302847f 100644
--- a/playground/interpolate.html
+++ b/playground/interpolate.html
@@ -172,7 +172,7 @@ 1 · Linear interpolation (default)
// 0 1 2 3
const filled = interpolateSeries(s);
-filled.values;
+console.log(filled.values);
// → [1, 2, 3, 4]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -194,7 +194,7 @@ 1 · Linear interpolation (default)
const t = new Series({ data: [null, 1, null, 3, null] });
-interpolateSeries(t).values;
+console.log(interpolateSeries(t).values);
// → [null, 1, 2, 3, null]
// ^^^^ ^^^^
// leading trailing
@@ -220,7 +220,7 @@ 2 · Forward fill (ffill / pad / zero)
const s = new Series({ data: [1, null, null, 4, null] });
-interpolateSeries(s, { method: "ffill" }).values;
+console.log(interpolateSeries(s, { method: "ffill" }).values);
// → [1, 1, 1, 4, 4]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -243,7 +243,7 @@ 3 · Backward fill (bfill / backfill)
const s = new Series({ data: [null, 2, null, null, 5] });
-interpolateSeries(s, { method: "bfill" }).values;
+console.log(interpolateSeries(s, { method: "bfill" }).values);
// → [2, 2, 5, 5, 5]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -270,7 +270,7 @@ 4 · Nearest-neighbor
// pos 2: dist-left=2, dist-right=1 → right wins → 4
const s = new Series({ data: [1, null, null, 4] });
-interpolateSeries(s, { method: "nearest" }).values;
+console.log(interpolateSeries(s, { method: "nearest" }).values);
// → [1, 1, 4, 4]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -292,7 +292,7 @@ 4 · Nearest-neighbor
// Tie at equidistance: right wins
const t = new Series({ data: [10, null, 30] });
-interpolateSeries(t, { method: "nearest" }).values;
+console.log(interpolateSeries(t, { method: "nearest" }).values);
// → [10, 30, 30] (pos 1 equidistant; right value 30 chosen)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -318,15 +318,15 @@ 5 · Limiting how many values are filled
const s = new Series({ data: [0, null, null, null, 4] });
// limit=1, forward: fill only the first NaN from the left
-interpolateSeries(s, { limit: 1 }).values;
+console.log(interpolateSeries(s, { limit: 1 }).values);
// → [0, 1, null, null, 4]
// limit=1, backward: fill only the last NaN from the right
-interpolateSeries(s, { limit: 1, limitDirection: "backward" }).values;
+console.log(interpolateSeries(s, { limit: 1, limitDirection: "backward" }).values);
// → [0, null, null, 3, 4]
// limit=1, both: fill one from each end
-interpolateSeries(s, { limit: 1, limitDirection: "both" }).values;
+console.log(interpolateSeries(s, { limit: 1, limitDirection: "both" }).values);
// → [0, 1, null, 3, 4]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -353,8 +353,8 @@ 6 · DataFrame — column-wise (axis=0, default)
});
const filled = dataFrameInterpolate(df);
-filled.col("temperature").values; // [20, 21, 22, 23]
-filled.col("humidity").values; // [60, 65, 70, null] ← trailing not filled
+console.log(filled.col("temperature").values); // [20, 21, 22, 23]
+console.log(filled.col("humidity").values); // [60, 65, 70, null] ← trailing not filled
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -384,8 +384,8 @@ 7 · DataFrame — row-wise (axis=1)
// Row 0 interpolates 0 → 6 (linear, 4 steps)
// Row 1 interpolates 10 → 22
const filled = dataFrameInterpolate(df, { axis: 1 });
-filled.col("t1").values; // [2, 14]
-filled.col("t2").values; // [4, 18]
+console.log(filled.col("t1").values); // [2, 14]
+console.log(filled.col("t2").values); // [4, 18]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/join.html b/playground/join.html
index 8ee935dc..143352d5 100644
--- a/playground/join.html
+++ b/playground/join.html
@@ -175,7 +175,7 @@ Left join (default)
{ index: ["alice", "charlie"] },
);
-join(employees, salaries);
+console.log(join(employees, salaries));
// dept salary
// alice Engineering 90000
// bob Marketing null ← no salary for bob
@@ -195,13 +195,13 @@ Inner / outer / right join
↺ Reset
- join(employees, salaries, { how: "inner" });
+ console.log(join(employees, salaries, { how: "inner" }));
// Only alice and charlie (keys in BOTH DataFrames)
-join(employees, salaries, { how: "outer" });
+console.log(join(employees, salaries, { how: "outer" }));
// All keys from either DataFrame (nulls where absent)
-join(employees, salaries, { how: "right" });
+console.log(join(employees, salaries, { how: "right" }));
// All keys from salaries: alice and charlie
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -224,7 +224,7 @@ Overlapping columns — use lsuffix / rsuffix
// This would throw — 'score' exists in both without suffix disambiguation:
// join(a, b);
-join(a, b, { lsuffix: "_a", rsuffix: "_b" });
+console.log(join(a, b, { lsuffix: "_a", rsuffix: "_b" }));
// score_a score_b
// x 10 15
// y 20 25
@@ -253,7 +253,7 @@ Join on a column key
);
// Join orders.customerId against customers index
-join(orders, customers, { on: "customerId", how: "left" });
+console.log(join(orders, customers, { on: "customerId", how: "left" }));
// customerId amount name
// C1 100 Alice
// C2 200 Bob
@@ -279,7 +279,7 @@ joinAll — chain multiple joins
const b1 = DataFrame.fromColumns({ B: [10,20,30] }, { index: ["K0","K1","K2"] });
const b2 = DataFrame.fromColumns({ C: [100,200,300] }, { index: ["K0","K1","K2"] });
-joinAll(base, [b1, b2]);
+console.log(joinAll(base, [b1, b2]));
// A B C
// 1 10 100
// 2 20 200
@@ -304,7 +304,7 @@ crossJoin — Cartesian product
const colors = DataFrame.fromColumns({ color: ["red", "blue"] });
const sizes = DataFrame.fromColumns({ size: ["S", "M", "L"] });
-crossJoin(colors, sizes);
+console.log(crossJoin(colors, sizes));
// color size
// red S
// red M
diff --git a/playground/json_normalize.html b/playground/json_normalize.html
index 5820aa06..ccc9a158 100644
--- a/playground/json_normalize.html
+++ b/playground/json_normalize.html
@@ -172,7 +172,8 @@ Example 1 — flatten nested dicts
const df = jsonNormalize(data);
// id info.name info.city
// 1 Alice NY
-// 2 Bob LA
+// 2 Bob LA
+console.log(df);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -200,7 +201,8 @@ Example 2 — recordPath + meta
// sku qty orderId customer
// X 2 A1 Alice
// Y 1 A1 Alice
-// Z 5 B2 Bob
+// Z 5 B2 Bob
+console.log(df);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -218,7 +220,7 @@ Example 3 — maxLevel
const data = [{ a: { b: { c: { d: 99 } } } }];
-jsonNormalize(data, { maxLevel: 1 });
+console.log(jsonNormalize(data, { maxLevel: 1 }));
// a.b → {"c":{"d":99}} (depth 2 is not expanded)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/math_ops.html b/playground/math_ops.html
index ba3f3726..232d571d 100644
--- a/playground/math_ops.html
+++ b/playground/math_ops.html
@@ -168,23 +168,23 @@ Code Examples
// ── absSeries ────────────────────────────────────────────────────────────────
const s = new Series({ data: [-1, 2, -3, null] });
-absSeries(s).values; // [1, 2, 3, null]
+console.log(absSeries(s).values); // [1, 2, 3, null]
// ── absDataFrame ─────────────────────────────────────────────────────────────
const df = DataFrame.fromColumns({ a: [-1, 2], b: [3, -4] });
-absDataFrame(df).col("a").values; // [1, 2]
-absDataFrame(df).col("b").values; // [3, 4]
+console.log(absDataFrame(df).col("a").values); // [1, 2]
+console.log(absDataFrame(df).col("b").values); // [3, 4]
// ── roundSeries ──────────────────────────────────────────────────────────────
const prices = new Series({ data: [1.234, 5.678, null] });
-roundSeries(prices, 2).values; // [1.23, 5.68, null]
-roundSeries(prices, 0).values; // [1, 6, null]
-roundSeries(prices, -1).values; // nearest 10: [0, 10, null]
+console.log(roundSeries(prices, 2).values); // [1.23, 5.68, null]
+console.log(roundSeries(prices, 0).values); // [1, 6, null]
+console.log(roundSeries(prices, -1).values); // nearest 10: [0, 10, null]
// ── roundDataFrame ────────────────────────────────────────────────────────────
const data = DataFrame.fromColumns({ price: [1.111, 2.222], qty: [3.7, 4.4] });
-roundDataFrame(data, 2).col("price").values; // [1.11, 2.22]
-roundDataFrame(data, { price: 1, qty: 0 }).col("qty").values; // [4, 4]
+console.log(roundDataFrame(data, 2).col("price").values); // [1.11, 2.22]
+console.log(roundDataFrame(data, { price: 1, qty: 0 }).col("qty").values); // [4, 4]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/memory_usage.html b/playground/memory_usage.html
index 2956fb1d..faa9e18d 100644
--- a/playground/memory_usage.html
+++ b/playground/memory_usage.html
@@ -167,8 +167,8 @@ 1 · Series memory_usage — fixed-width dtype
const s = new Series({ data: [1, 2, 3, 4], dtype: Dtype.int32 });
// int32 → 4 bytes/element × 4 = 16 bytes of data
// RangeIndex → 3 × 8 = 24 bytes (only start/stop/step stored)
-seriesMemoryUsage(s); // 40 (data + index)
-seriesMemoryUsage(s, { index: false }); // 16 (data only)
+console.log(seriesMemoryUsage(s)); // 40 (data + index)
+console.log(seriesMemoryUsage(s, { index: false })); // 16 (data only)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -186,9 +186,9 @@ 2 · Series memory_usage — string dtype (shallow vs deep)
const s = new Series({ data: ["hello", "world", "tsb"], dtype: Dtype.string });
// shallow: 3 × 8 bytes (one pointer per element)
-seriesMemoryUsage(s, { index: false }); // 24
+console.log(seriesMemoryUsage(s, { index: false })); // 24
// deep: actual char data — each string = length*2 + 56 bytes overhead
-seriesMemoryUsage(s, { index: false, deep: true }); // "hello"=66, "world"=66, "tsb"=62 → 194
+console.log(seriesMemoryUsage(s, { index: false, deep: true })); // "hello"=66, "world"=66, "tsb"=62 → 194
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -214,7 +214,8 @@ 3 · DataFrame memory_usage — per-column breakdown
// Index (RangeIndex) → 24 bytes
// id (int32 × 3) → 12 bytes
// score (float64 × 3)→ 24 bytes
-// name (string × 3, shallow) → 24 bytes
+// name (string × 3, shallow) → 24 bytes
+console.log(mu);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -235,7 +236,8 @@ 4 · DataFrame memory_usage — deep=true for string columns
});
dataFrameMemoryUsage(df, { deep: true, index: false })
// "short" → 5*2+56 = 66
-// "a slightly longer string" → 24*2+56 = 104
+// "a slightly longer string" → 24*2+56 = 104
+console.log(df);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -256,7 +258,7 @@ 5 · Total memory across all columns
b: new Series({ data: Array.from({length: 1000}, (_,i) => i * 0.1), dtype: Dtype.float64 }),
});
const mu = dataFrameMemoryUsage(df, { index: false });
-mu.sum(); // 1000*8 + 1000*8 = 16000 bytes
+console.log(mu.sum()); // 1000*8 + 1000*8 = 16000 bytes
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/merge_asof.html b/playground/merge_asof.html
index c48b422c..bd015293 100644
--- a/playground/merge_asof.html
+++ b/playground/merge_asof.html
@@ -179,7 +179,8 @@ Basic example — backward (default)
// time | price | bid
// 1 | 100 | null ← no quote ≤ 1
// 5 | 200 | 98 ← most recent quote ≤ 5 is at time=2
-// 10 | 300 | 195 ← most recent quote ≤ 10 is at time=6
+// 10 | 300 | 195 ← most recent quote ≤ 10 is at time=6
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -203,7 +204,8 @@ Forward direction
on: "t",
direction: "forward",
});
-// t=1 → t=2 (w=20), t=3 → t=6 (w=60), t=7 → t=10 (w=100)
+// t=1 → t=2 (w=20), t=3 → t=6 (w=60), t=7 → t=10 (w=100)
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -223,7 +225,8 @@ Nearest direction
on: "time",
direction: "nearest",
});
-// Picks the quote with the smallest absolute time difference.
+// Picks the quote with the smallest absolute time difference.
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -251,7 +254,7 @@ Grouping with by
bid: [99, 198, 109, 208],
});
-mergeAsof(trades, quotes, { on: "time", by: "ticker" });
+console.log(mergeAsof(trades, quotes, { on: "time", by: "ticker" }));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -268,7 +271,7 @@ Tolerance
// Only match if the key distance is ≤ 2
-mergeAsof(left, right, { on: "t", tolerance: 2 });
+console.log(mergeAsof(left, right, { on: "t", tolerance: 2 }));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/merge_ordered.html b/playground/merge_ordered.html
index 4eb45e76..8f1a2c2f 100644
--- a/playground/merge_ordered.html
+++ b/playground/merge_ordered.html
@@ -181,7 +181,8 @@ Basic outer ordered merge
// 2 | null | 200
// 3 | 30 | 300
// 5 | 50 | null
-// 6 | null | 600
+// 6 | null | 600
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -206,7 +207,8 @@ Forward-fill after merge
// 2 | 10 | 200 ← price carried forward from date=1
// 3 | 30 | 300
// 5 | 50 | 300 ← volume carried forward from date=3
-// 6 | 50 | 600
+// 6 | 50 | 600
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -223,7 +225,7 @@ Inner join variant
// Only rows where both DataFrames have a key
-mergeOrdered(left, right, { on: "date", how: "inner" });
+console.log(mergeOrdered(left, right, { on: "date", how: "inner" }));
// date | price | volume
// 3 | 30 | 300
Click ▶ Run to execute
@@ -244,7 +246,7 @@ Different key column names per side
const left2 = DataFrame.fromColumns({ t_left: [1, 3, 5], a: [10, 30, 50] });
const right2 = DataFrame.fromColumns({ t_right: [2, 3, 6], b: [200, 300, 600] });
-mergeOrdered(left2, right2, { left_on: "t_left", right_on: "t_right" });
+console.log(mergeOrdered(left2, right2, { left_on: "t_left", right_on: "t_right" }));
// t_left | a | b
// 1 | 10 | null
// 2 | null | 200
@@ -289,7 +291,8 @@ Group-wise ordered merge (left_by / right_by)
// A | 3 | 30 | 30
// B | 1 | 100 | null
// B | 2 | null | 200
-// B | 3 | 300 | 300
+// B | 3 | 300 | 300
+console.log(right3);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -308,7 +311,7 @@ Overlapping non-key columns — suffixes
const left4 = DataFrame.fromColumns({ k: [1, 2, 3], val: [10, 20, 30] });
const right4 = DataFrame.fromColumns({ k: [2, 3, 4], val: [200, 300, 400] });
-mergeOrdered(left4, right4, { on: "k", suffixes: ["_L", "_R"] });
+console.log(mergeOrdered(left4, right4, { on: "k", suffixes: ["_L", "_R"] }));
// k | val_L | val_R
// 1 | 10 | null
// 2 | 20 | 200
diff --git a/playground/mode.html b/playground/mode.html
index eca873d3..9e7ca7be 100644
--- a/playground/mode.html
+++ b/playground/mode.html
@@ -162,7 +162,7 @@ 1 · Single mode
const s = new Series({ data: [1, 2, 2, 3] });
-modeSeries(s).values;
+console.log(modeSeries(s).values);
// → [2]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -180,7 +180,7 @@ 2 · Tied modes — all returned sorted
const s = new Series({ data: [1, 1, 2, 2, 3] });
-modeSeries(s).values;
+console.log(modeSeries(s).values);
// → [1, 2]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -198,7 +198,7 @@ 3 · String values
const s = new Series({ data: ["cat", "dog", "dog", "bird"] });
-modeSeries(s).values;
+console.log(modeSeries(s).values);
// → ["dog"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -216,7 +216,7 @@ 4 · Null values excluded (dropna=true default)
const s = new Series({ data: [null, 1, 1, null, null] });
-modeSeries(s).values;
+console.log(modeSeries(s).values);
// → [1]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -234,7 +234,7 @@ 5 · DataFrame column-wise (axis=0)
const df = DataFrame.fromColumns({ a: [1, 1, 2, 2], b: [5, 5, 5, 6] });
-modeDataFrame(df);
+console.log(modeDataFrame(df));
// a: [1, 2], b: [5, null] (null-padded)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -252,7 +252,7 @@ 6 · DataFrame row-wise (axis=1)
const df = DataFrame.fromColumns({ a: [1, 2], b: [1, 3], c: [2, 3] });
-modeDataFrame(df, { axis: 1 });
+console.log(modeDataFrame(df, { axis: 1 }));
// row 0: mode=1, row 1: mode=3
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/named_agg.html b/playground/named_agg.html
index 62fc72a5..4f3c69ee 100644
--- a/playground/named_agg.html
+++ b/playground/named_agg.html
@@ -182,7 +182,8 @@ Basic Usage
// result:
// | total_salary | avg_salary | employees | avg_score
// eng | 330 | 110 | 3 | 4.167
-// hr | 170 | 85 | 2 | 3.5
+// hr | 170 | 85 | 2 | 3.5
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -227,7 +228,8 @@ Custom Aggregation Functions
df.groupby("dept").aggNamed({
salary_range: namedAgg("salary", salaryRange),
-});
+});
+console.log(salaryRange);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/nancumops.html b/playground/nancumops.html
index 6e9d221a..009058fe 100644
--- a/playground/nancumops.html
+++ b/playground/nancumops.html
@@ -168,10 +168,10 @@ 💡 Usage Examples
const data = [1, 2, NaN, null, 3, 5];
-nansum(data); // 11
-nanmean(data); // 2.75
-nanmedian(data); // 2.5
-nanstd(data); // 1.708...
+console.log(nansum(data)); // 11
+console.log(nanmean(data)); // 2.75
+console.log(nanmedian(data)); // 2.5
+console.log(nanstd(data)); // 1.708...
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -192,9 +192,9 @@ 💡 Usage Examples
const s = new Series({ data: [10, null, 30, NaN, 50] });
-nancount(s); // 3
-nansum(s); // 90
-nanmean(s); // 30
+console.log(nancount(s)); // 3
+console.log(nansum(s)); // 90
+console.log(nanmean(s)); // 30
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -216,12 +216,12 @@ 💡 Usage Examples
const xs = [2, 4, 4, 4, 5, 5, 7, 9];
// Sample (ddof=1, default)
-nanvar(xs); // ≈ 4.571
-nanstd(xs); // ≈ 2.138
+console.log(nanvar(xs)); // ≈ 4.571
+console.log(nanstd(xs)); // ≈ 2.138
// Population (ddof=0)
-nanvar(xs, { ddof: 0 }); // 4.0
-nanstd(xs, { ddof: 0 }); // 2.0
+console.log(nanvar(xs, { ddof: 0 })); // 4.0
+console.log(nanstd(xs, { ddof: 0 })); // 2.0
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/natsort.html b/playground/natsort.html
index 5b2d3e94..a419c55b 100644
--- a/playground/natsort.html
+++ b/playground/natsort.html
@@ -194,11 +194,11 @@ 2 · Options
// ignoreCase — text tokens are folded to lower-case
const words = ["Banana", "apple", "Cherry"];
-natSorted(words, { ignoreCase: true });
+console.log(natSorted(words, { ignoreCase: true }));
// → ["apple", "Banana", "Cherry"]
// reverse — descending natural order
-natSorted(["file1", "file10", "file2"], { reverse: true });
+console.log(natSorted(["file1", "file10", "file2"], { reverse: true }));
// → ["file10", "file2", "file1"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -224,7 +224,7 @@ 3 · Sorting objects with a key function
// key extracts the string to sort by
import { natSorted } from "tsb";
const sorted = natSorted(rows, { key: r => r.path });
-sorted.map(r => r.path);
+console.log(sorted.map(r => r.path));
// → ["img/photo1.jpg", "img/photo2.jpg", "img/photo10.jpg"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -243,13 +243,13 @@ 4 · natSortKey — inspect the token representation
import { natSortKey } from "tsb";
-natSortKey("file10.txt"); // → ["file", 10, ".txt"]
-natSortKey("007bonds"); // → [7, "bonds"] (leading zeros stripped)
-natSortKey("abc"); // → ["abc"]
-natSortKey("42"); // → [42]
+console.log(natSortKey("file10.txt")); // → ["file", 10, ".txt"]
+console.log(natSortKey("007bonds")); // → [7, "bonds"] (leading zeros stripped)
+console.log(natSortKey("abc")); // → ["abc"]
+console.log(natSortKey("42")); // → [42]
// ignoreCase folds text tokens
-natSortKey("File10.TXT", { ignoreCase: true });
+console.log(natSortKey("File10.TXT", { ignoreCase: true }));
// → ["file", 10, ".txt"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -272,7 +272,7 @@ 5 · natArgSort — permutation indices
const idx = natArgSort(arr);
// → [2, 1, 0] (indices of "file1", "file2", "file10")
-idx.map(i => arr[i]);
+console.log(idx.map(i => arr[i]));
// → ["file1", "file2", "file10"]
// Use with a tsb Index to sort labels naturally:
@@ -300,7 +300,7 @@ 6 · Comparison with lexicographic sort
// → ["item1", "item12", "item2", "item20", "item3"] ← wrong
// Natural sort
-natSorted(data);
+console.log(natSorted(data));
// → ["item1", "item2", "item3", "item12", "item20"] ← correct
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/notna.html b/playground/notna.html
index 60910600..719d3aaf 100644
--- a/playground/notna.html
+++ b/playground/notna.html
@@ -163,18 +163,18 @@ Example 1 — scalars
import { isna, notna } from "tsb";
-isna(null); // true
-isna(undefined); // true
-isna(NaN); // true
+console.log(isna(null)); // true
+console.log(isna(undefined)); // true
+console.log(isna(NaN)); // true
-isna(0); // false — zero is not missing
-isna(""); // false — empty string is not missing
-isna(false); // false — false is not missing
-isna(42); // false
-isna("hello"); // false
+console.log(isna(0)); // false — zero is not missing
+console.log(isna("")); // false — empty string is not missing
+console.log(isna(false)); // false — false is not missing
+console.log(isna(42)); // false
+console.log(isna("hello")); // false
-notna(null); // false
-notna(42); // true
+console.log(notna(null)); // false
+console.log(notna(42)); // true
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -193,10 +193,10 @@ Example 2 — arrays
import { isna, notna } from "tsb";
const arr = [1, null, NaN, "x", undefined, false];
-isna(arr);
+console.log(isna(arr));
// [false, true, true, false, true, false]
-notna(arr);
+console.log(notna(arr));
// [true, false, false, true, false, true]
// Count missing values
@@ -220,10 +220,10 @@ Example 3 — Series
const s = new Series({ data: [10, null, NaN, 40], name: "sales" });
-isna(s).values;
+console.log(isna(s).values);
// [false, true, true, false]
-notna(s).values;
+console.log(notna(s).values);
// [true, false, false, true]
// Filter to non-missing values
@@ -251,7 +251,7 @@ Example 4 — DataFrame
active: [true, false, null ],
});
-isna(df).toRecords();
+console.log(isna(df).toRecords());
// [
// { name: false, score: false, active: false },
// { name: true, score: true, active: false },
@@ -284,8 +284,8 @@ Example 5 — aliases
// isnull is an alias for isna
// notnull is an alias for notna
-isnull(null); // true
-notnull("hello"); // true
+console.log(isnull(null)); // true
+console.log(notnull("hello")); // true
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/notna_boolean.html b/playground/notna_boolean.html
index 79141124..e7486bf4 100644
--- a/playground/notna_boolean.html
+++ b/playground/notna_boolean.html
@@ -167,10 +167,10 @@ Code Examples
const s = new Series({ data: [10, 20, 30, 40], index: ["a", "b", "c", "d"] });
// Keep elements where mask is true
-keepTrue(s, [true, false, true, false]).values; // [10, 30]
+console.log(keepTrue(s, [true, false, true, false]).values); // [10, 30]
// Keep elements where mask is false (complement)
-keepFalse(s, [true, false, true, false]).values; // [20, 40]
+console.log(keepFalse(s, [true, false, true, false]).values); // [20, 40]
// Filter DataFrame rows
const df = DataFrame.fromColumns(
@@ -178,11 +178,11 @@ Code Examples
{ index: ["alice", "bob", "carol", "dave"] },
);
const highScore = df.col("score").values.map((v) => (v as number) >= 80);
-filterBy(df, highScore).col("age").values; // [25, 35]
+console.log(filterBy(df, highScore).col("age").values); // [25, 35]
// Use a Series as a mask
const mask = new Series({ data: [true, null, true, false], index: ["a", "b", "c", "d"] });
-keepTrue(s, mask).values; // [10, 30] (null treated as false)
+console.log(keepTrue(s, mask).values); // [10, 30] (null treated as false)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/notna_isna.html b/playground/notna_isna.html
index 7f73051e..b58c30c8 100644
--- a/playground/notna_isna.html
+++ b/playground/notna_isna.html
@@ -166,49 +166,49 @@ 📝 Code examples
import { Series, DataFrame } from "tsb";
// ── scalar ──────────────────────────────────────────────────
-isna(null); // true
-isna(undefined); // true
-isna(NaN); // true
-isna(0); // false — zero is not missing
-isna(false); // false — false is not missing
-isna(""); // false — empty string is not missing
+console.log(isna(null)); // true
+console.log(isna(undefined)); // true
+console.log(isna(NaN)); // true
+console.log(isna(0)); // false — zero is not missing
+console.log(isna(false)); // false — false is not missing
+console.log(isna("")); // false — empty string is not missing
// ── array ───────────────────────────────────────────────────
-isna([1, null, NaN, 3]); // [false, true, true, false]
-notna([1, null, NaN, 3]); // [true, false, false, true]
+console.log(isna([1, null, NaN, 3])); // [false, true, true, false]
+console.log(notna([1, null, NaN, 3])); // [true, false, false, true]
// ── Series ──────────────────────────────────────────────────
const s = new Series({ data: [1, null, NaN, 4] });
-isna(s).values; // [false, true, true, false]
-notna(s).values; // [true, false, false, true]
+console.log(isna(s).values); // [false, true, true, false]
+console.log(notna(s).values); // [true, false, false, true]
// ── DataFrame ───────────────────────────────────────────────
const df = new DataFrame(new Map([
["a", new Series({ data: [1, null, 3] })],
["b", new Series({ data: [NaN, 5, 6] })],
]));
-isna(df).col("a").values; // [false, true, false]
-isna(df).col("b").values; // [true, false, false]
+console.log(isna(df).col("a").values); // [false, true, false]
+console.log(isna(df).col("b").values); // [true, false, false]
// ── aliases ─────────────────────────────────────────────────
-isnull(null); // true (same as isna)
-notnull(42); // true (same as notna)
+console.log(isnull(null)); // true (same as isna)
+console.log(notnull(42)); // true (same as notna)
// ── fillna ──────────────────────────────────────────────────
-fillna([1, null, NaN, 4], { value: 0 }); // [1, 0, 0, 4]
-fillna(s, { value: -1 }).values; // [1, -1, -1, 4]
-fillna(df, { value: 0 }).col("b").values; // [0, 5, 6]
+console.log(fillna([1, null, NaN, 4], { value: 0 })); // [1, 0, 0, 4]
+console.log(fillna(s, { value: -1 }).values); // [1, -1, -1, 4]
+console.log(fillna(df, { value: 0 }).col("b").values); // [0, 5, 6]
// ── dropna ──────────────────────────────────────────────────
-dropna([1, null, NaN, 3]); // [1, 3]
-dropna(s).values; // [1, 4]
-dropna(df).shape; // [2, 2] (row 0 dropped because b[0]=NaN, row 1 dropped because a[1]=null)
-dropna(df, { how: "all" }).shape; // drops only rows where ALL values are missing
-dropna(df, { axis: 1 }).columns.values; // drops columns that contain any missing value
+console.log(dropna([1, null, NaN, 3])); // [1, 3]
+console.log(dropna(s).values); // [1, 4]
+console.log(dropna(df).shape); // [2, 2] (row 0 dropped because b[0]=NaN, row 1 dropped because a[1]=null)
+console.log(dropna(df, { how: "all" }).shape); // drops only rows where ALL values are missing
+console.log(dropna(df, { axis: 1 }).columns.values); // drops columns that contain any missing value
// ── countna / countValid ─────────────────────────────────────
-countna([1, null, NaN, 3]); // 2
-countValid([1, null, NaN, 3]); // 2
+console.log(countna([1, null, NaN, 3])); // 2
+console.log(countValid([1, null, NaN, 3])); // 2
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/numeric_extended.html b/playground/numeric_extended.html
index a399d8ad..d92ec244 100644
--- a/playground/numeric_extended.html
+++ b/playground/numeric_extended.html
@@ -179,7 +179,7 @@ digitize — bin values
// Series version — preserves index
const s = new Series({ data: [15, 45, 70], index: ["Alice","Bob","Carol"] });
-seriesDigitize(s, [33, 66, 100]);
+console.log(seriesDigitize(s, [33, 66, 100]));
// Series: Alice→-1, Bob→1, Carol→2
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -208,7 +208,7 @@ histogram — frequency counts
const { counts: d, binEdges: e } = histogram(data, { bins: 5, density: true });
// Explicit edges
-histogram(data, { binEdges: [1, 4, 7, 10] });
+console.log(histogram(data, { binEdges: [1, 4, 7, 10] }));
// counts: [ 3, 3, 4 ]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -229,19 +229,19 @@ linspace & arange — number sequences
import { linspace, arange } from "tsb";
// 5 values from 0 to 1 (inclusive)
-linspace(0, 1, 5);
+console.log(linspace(0, 1, 5));
// → [0, 0.25, 0.5, 0.75, 1]
// 0..4
-arange(5);
+console.log(arange(5));
// → [0, 1, 2, 3, 4]
// From 2 to 10, step 2
-arange(2, 10, 2);
+console.log(arange(2, 10, 2));
// → [2, 4, 6, 8]
// Descending
-arange(5, 0, -1);
+console.log(arange(5, 0, -1));
// → [5, 4, 3, 2, 1]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -265,9 +265,9 @@ percentileOfScore — percentile rank
const grades = [55, 60, 70, 75, 80, 85, 90, 95];
// What percentile is a score of 75?
-percentileOfScore(grades, 75); // 50 (rank — default)
-percentileOfScore(grades, 75, "weak"); // 50 (≤ 75: 4/8 = 50%)
-percentileOfScore(grades, 75, "strict"); // 37.5 (< 75: 3/8 = 37.5%)
+console.log(percentileOfScore(grades, 75)); // 50 (rank — default)
+console.log(percentileOfScore(grades, 75, "weak")); // 50 (≤ 75: 4/8 = 50%)
+console.log(percentileOfScore(grades, 75, "strict")); // 37.5 (< 75: 3/8 = 37.5%)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -293,7 +293,8 @@ zscore — standardisation
// z.values ≈ [-1.5, -0.5, -0.5, -0.5, 0, 0, 1, 2]
// With population std (ddof=0)
-const zPop = zscore(s, { ddof: 0 });
+const zPop = zscore(s, { ddof: 0 });
+console.log(zPop);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -314,11 +315,11 @@ minMaxNormalize — scale to [0, 1]
import { minMaxNormalize, Series } from "tsb";
const s = new Series({ data: [0, 25, 50, 75, 100] });
-minMaxNormalize(s).values;
+console.log(minMaxNormalize(s).values);
// → [0, 0.25, 0.5, 0.75, 1]
// Scale to [-1, 1]
-minMaxNormalize(s, { featureRangeMin: -1, featureRangeMax: 1 }).values;
+console.log(minMaxNormalize(s, { featureRangeMin: -1, featureRangeMax: 1 }).values);
// → [-1, -0.5, 0, 0.5, 1]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -340,13 +341,13 @@ coefficientOfVariation — relative spread
import { coefficientOfVariation, Series } from "tsb";
// Dataset A: [10, 20, 30] mean=20, std=10 → CV=0.5
-coefficientOfVariation(new Series({ data: [10, 20, 30] }));
+console.log(coefficientOfVariation(new Series({ data: [10, 20, 30] })));
// Dataset B: [100, 200, 300] same shape, higher scale → CV=0.5
-coefficientOfVariation(new Series({ data: [100, 200, 300] }));
+console.log(coefficientOfVariation(new Series({ data: [100, 200, 300] })));
// CV with population std
-coefficientOfVariation(new Series({ data: [1, 2, 3, 4, 5] }), { ddof: 0 });
+console.log(coefficientOfVariation(new Series({ data: [1, 2, 3, 4, 5] }), { ddof: 0 }));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/nunique.html b/playground/nunique.html
index 77c6fa17..8b7d4e8a 100644
--- a/playground/nunique.html
+++ b/playground/nunique.html
@@ -165,8 +165,8 @@ 1 · nunique — count distinct values
const s = new Series({ data: [1, 2, 2, 3, 3, 3, null] });
-nuniqueSeries(s); // 3 (null excluded by default)
-nuniqueSeries(s, { dropna: false }); // 4 (null counted as a distinct value)
+console.log(nuniqueSeries(s)); // 3 (null excluded by default)
+console.log(nuniqueSeries(s, { dropna: false })); // 4 (null counted as a distinct value)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -187,12 +187,12 @@ 2 · any — is any element truthy?
const allZero = new Series({ data: [0, 0, 0] });
const hasOne = new Series({ data: [0, 0, 1] });
-anySeries(allZero); // false
-anySeries(hasOne); // true
+console.log(anySeries(allZero)); // false
+console.log(anySeries(hasOne)); // true
// With nulls (skipna=true by default)
const withNull = new Series({ data: [null, 0, null] });
-anySeries(withNull); // false — null skipped, 0 is falsy
+console.log(anySeries(withNull)); // false — null skipped, 0 is falsy
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -213,12 +213,12 @@ 3 · all — are all elements truthy?
const allTrue = new Series({ data: [1, 2, 3] });
const hasFalsy = new Series({ data: [1, 0, 3] });
-allSeries(allTrue); // true
-allSeries(hasFalsy); // false
+console.log(allSeries(allTrue)); // true
+console.log(allSeries(hasFalsy)); // false
// Empty or all-null series vacuously returns true
-allSeries(new Series({ data: [] })); // true
-allSeries(new Series({ data: [null, null] })); // true
+console.log(allSeries(new Series({ data: [] }))); // true
+console.log(allSeries(new Series({ data: [null, null] }))); // true
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -241,8 +241,8 @@ 4 · DataFrame nunique
value: [1, 2, 1, 3 ],
});
-nuniqueDataFrame(df); // per-column: category→3, value→3
-nuniqueDataFrame(df, { axis: 1 }); // per-row: how many distinct values in each row
+console.log(nuniqueDataFrame(df)); // per-column: category→3, value→3
+console.log(nuniqueDataFrame(df, { axis: 1 })); // per-row: how many distinct values in each row
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -265,12 +265,12 @@ 5 · DataFrame any / all
b: [1, 1, 1],
});
-anyDataFrame(df2); // a: true, b: true (each col has at least one truthy)
-allDataFrame(df2); // a: false, b: true (col a has a 0)
+console.log(anyDataFrame(df2)); // a: true, b: true (each col has at least one truthy)
+console.log(allDataFrame(df2)); // a: false, b: true (col a has a 0)
// axis=1: reduce across columns per row
-anyDataFrame(df2, { axis: 1 }); // row0: true, row1: true, row2: true
-allDataFrame(df2, { axis: 1 }); // row0: false, row1: false, row2: true
+console.log(anyDataFrame(df2, { axis: 1 })); // row0: true, row1: true, row2: true
+console.log(allDataFrame(df2, { axis: 1 })); // row0: false, row1: false, row2: true
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/pipe_apply.html b/playground/pipe_apply.html
index 4a26f5bc..d6d2fa50 100644
--- a/playground/pipe_apply.html
+++ b/playground/pipe_apply.html
@@ -180,7 +180,8 @@ pipe — functional pipeline
(x) => x * x, // 16
(x) => x - 1, // 15
);
-// n === 15
+// n === 15
+console.log(n);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -214,7 +215,8 @@ seriesApply — element-wise apply
new Series({ data: [10, 20, 30] }),
(v, _label, pos) => (v as number) + pos * 100,
);
-// [10, 120, 230]
+// [10, 120, 230]
+console.log(withPos);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -249,7 +251,8 @@ dataFrameApply — column/row aggregation
(row) => (row.at("score") as number) * (row.at("weight") as number),
1,
);
-// [85, 110.4, 62.4, 142.5]
+// [85, 110.4, 62.4, 142.5]
+console.log(weightedScore);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -283,7 +286,8 @@ dataFrameApplyMap — element-wise cell transform
// fn receives full context: (value, rowLabel, colName)
const tagged = dataFrameApplyMap(df, (v, row, col) => `${col}[${row}]=${v}`);
// a: ["a[0]=1", "a[1]=-2", "a[2]=3"]
-// b: ["b[0]=-4", "b[1]=5", "b[2]=-6"]
+// b: ["b[0]=-4", "b[1]=5", "b[2]=-6"]
+console.log(tagged);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -328,7 +332,8 @@ dataFrameTransform — column-wise transform
if (n <= q3) return "Q3";
return "Q4";
});
-});
+});
+console.log(binned);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -367,7 +372,8 @@ dataFrameTransformRows — row-wise transform
last: row["last"],
score: row["score"],
full: `${row["first"]} ${row["last"]}`,
-}));
+}));
+console.log(withFull);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -408,7 +414,8 @@ Combining pipe + apply
typeof v === "number" ? Math.round(v * 100) / 100 : v
)
),
-);
+);
+console.log(clean);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/pivot_table.html b/playground/pivot_table.html
index 74be448f..66ec2b94 100644
--- a/playground/pivot_table.html
+++ b/playground/pivot_table.html
@@ -181,7 +181,8 @@ Example 1 — sales by region and product (sum + margins)
// A B All
// North 220 200 420
// South 150 430 580
-// All 370 630 1000
+// All 370 630 1000
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -216,7 +217,8 @@ Example 2 — mean aggregation with custom margins_name
// Jr Sr Total
// Eng 70 90 80
// Mkt 60 80 70
-// Total 65 85 75
+// Total 65 85 75
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -247,7 +249,8 @@ Example 3 — sort=false preserves insertion order
});
// Rows in order: Z, A, M (insertion order)
-// Cols in order: b, a, c (insertion order)
+// Cols in order: b, a, c (insertion order)
+console.log(df);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -280,7 +283,8 @@ Example 4 — count with margins
// Jr Sr All
// Eng 1 2 3
// Mkt 1 1 2
-// All 2 3 5
+// All 2 3 5
+console.log(df);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/quantile.html b/playground/quantile.html
index 49c30941..849f0030 100644
--- a/playground/quantile.html
+++ b/playground/quantile.html
@@ -162,9 +162,9 @@ 1 · Scalar quantile (median)
const s = new Series({ data: [1, 2, 3, 4, 5] });
-quantileSeries(s); // default q=0.5 → 3
-quantileSeries(s, { q: 0.25 }); // → 2
-quantileSeries(s, { q: 0.75 }); // → 4
+console.log(quantileSeries(s)); // default q=0.5 → 3
+console.log(quantileSeries(s, { q: 0.25 })); // → 2
+console.log(quantileSeries(s, { q: 0.75 })); // → 4
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -182,7 +182,8 @@ 2 · Multiple quantile levels
const s = new Series({ data: [1, 2, 3, 4, 5] });
const q = quantileSeries(s, { q: [0.25, 0.5, 0.75] });
-// Series indexed by q-values: { 0.25: 2, 0.5: 3, 0.75: 4 }
+// Series indexed by q-values: { 0.25: 2, 0.5: 3, 0.75: 4 }
+console.log(q);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -200,11 +201,11 @@ 3 · Interpolation methods
const s = new Series({ data: [0, 10] });
// q=0.5 → position 0.5 between indices 0 and 1
-quantileSeries(s, { q: 0.5, interpolation: "linear" }); // 5
-quantileSeries(s, { q: 0.5, interpolation: "lower" }); // 0
-quantileSeries(s, { q: 0.5, interpolation: "higher" }); // 10
-quantileSeries(s, { q: 0.5, interpolation: "midpoint" }); // 5
-quantileSeries(s, { q: 0.5, interpolation: "nearest" }); // 0
+console.log(quantileSeries(s, { q: 0.5, interpolation: "linear" })); // 5
+console.log(quantileSeries(s, { q: 0.5, interpolation: "lower" })); // 0
+console.log(quantileSeries(s, { q: 0.5, interpolation: "higher" })); // 10
+console.log(quantileSeries(s, { q: 0.5, interpolation: "midpoint" })); // 5
+console.log(quantileSeries(s, { q: 0.5, interpolation: "nearest" })); // 0
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -221,8 +222,8 @@ 4 · NaN handling (skipna=true by default)
const s = new Series({ data: [1, null, 3, NaN, 5] });
-quantileSeries(s, { q: 0.5 }); // ignores null/NaN → 3
-quantileSeries(s, { q: 0.5, skipna: false }); // NaN propagates → NaN
+console.log(quantileSeries(s, { q: 0.5 })); // ignores null/NaN → 3
+console.log(quantileSeries(s, { q: 0.5, skipna: false })); // NaN propagates → NaN
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -239,10 +240,10 @@ 5 · DataFrame — axis=0 (per-column quantiles)
const df = DataFrame.fromColumns({ a: [1, 2, 3, 4], b: [10, 20, 30, 40] });
-quantileDataFrame(df, { q: 0.5 });
+console.log(quantileDataFrame(df, { q: 0.5 }));
// Series { a: 2.5, b: 25 }
-quantileDataFrame(df, { q: [0.25, 0.5, 0.75] });
+console.log(quantileDataFrame(df, { q: [0.25, 0.5, 0.75] }));
// DataFrame 3×2: rows=[0.25, 0.5, 0.75], cols=[a, b]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -260,7 +261,7 @@ 6 · DataFrame — axis=1 (per-row quantiles)
const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [3, 4, 5], c: [5, 6, 7] });
-quantileDataFrame(df, { axis: 1, q: 0.5 });
+console.log(quantileDataFrame(df, { axis: 1, q: 0.5 }));
// Series — median of each row: [3, 4, 5]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -278,7 +279,7 @@ 7 · Q=[0, 0.25, 0.5, 0.75, 1] summary table
const df = DataFrame.fromColumns({ score: [55, 70, 80, 88, 92, 95, 99] });
-quantileDataFrame(df, { q: [0, 0.25, 0.5, 0.75, 1] });
+console.log(quantileDataFrame(df, { q: [0, 0.25, 0.5, 0.75, 1] }));
// → summary statistics table
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/reduce_ops.html b/playground/reduce_ops.html
index 993ae52c..8f481400 100644
--- a/playground/reduce_ops.html
+++ b/playground/reduce_ops.html
@@ -169,8 +169,8 @@ nuniqueSeries — count distinct values
import { Series, nuniqueSeries } from "tsb";
const s = new Series([1, 2, 2, null, 3]);
-nuniqueSeries(s); // 3 (null excluded by default)
-nuniqueSeries(s, { dropna: false }); // 4 (null counted as a distinct value)
+console.log(nuniqueSeries(s)); // 3 (null excluded by default)
+console.log(nuniqueSeries(s, { dropna: false })); // 4 (null counted as a distinct value)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -193,7 +193,7 @@ nunique — count distinct per column (axis=0, default)
rating: [5, 3, 5, 4],
flag: [true, false, true, null],
});
-nunique(df);
+console.log(nunique(df));
// Series { brand: 3, rating: 3, flag: 2 }
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -210,7 +210,7 @@ nunique — count distinct per row (axis=1)
↺ Reset
- nunique(df, { axis: 1 });
+ console.log(nunique(df, { axis: 1 }));
// Series [3, 3, 3, 3] — each row has 3 distinct values
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -230,16 +230,16 @@ anySeries / allSeries
import { Series, anySeries, allSeries } from "tsb";
const flags = new Series([false, false, true]);
-anySeries(flags); // true — at least one truthy
-allSeries(flags); // false — not all truthy
+console.log(anySeries(flags)); // true — at least one truthy
+console.log(allSeries(flags)); // false — not all truthy
const ones = new Series([1, 2, 3]);
-allSeries(ones); // true — all truthy
+console.log(allSeries(ones)); // true — all truthy
// skipna option
const withNull = new Series([1, null, 2]);
-allSeries(withNull); // true (null skipped)
-allSeries(withNull, { skipna: false }); // false (null is falsy)
+console.log(allSeries(withNull)); // true (null skipped)
+console.log(allSeries(withNull, { skipna: false })); // false (null is falsy)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -263,14 +263,14 @@ anyDataFrame / allDataFrame
c: [0, 0, 0],
});
-anyDataFrame(df2);
+console.log(anyDataFrame(df2));
// Series { a: true, b: true, c: false }
-allDataFrame(df2);
+console.log(allDataFrame(df2));
// Series { a: false, b: true, c: false }
// axis=1: reduce across columns → one boolean per row
-anyDataFrame(df2, { axis: 1 });
+console.log(anyDataFrame(df2, { axis: 1 }));
// Series [true, true, true] (row 0: 0,1,0 → any=true via b)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -293,7 +293,7 @@ boolOnly option
});
// Only consider boolean columns
-anyDataFrame(mixed, { boolOnly: true });
+console.log(anyDataFrame(mixed, { boolOnly: true }));
// Series { flag: true } — 'nums' column excluded
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/reindex.html b/playground/reindex.html
index ac05172c..6e4860aa 100644
--- a/playground/reindex.html
+++ b/playground/reindex.html
@@ -166,19 +166,19 @@ 1 · reindexSeries — basics
const s = new Series({ data: [10, 20, 30], index: new Index(["a", "b", "c"]) });
// Reorder labels
-reindexSeries(s, ["c", "a", "b"]).toArray();
+console.log(reindexSeries(s, ["c", "a", "b"]).toArray());
// → [30, 10, 20]
// Extend with new labels → null by default
-reindexSeries(s, ["a", "b", "c", "d"]).toArray();
+console.log(reindexSeries(s, ["a", "b", "c", "d"]).toArray());
// → [10, 20, 30, null]
// Extend with custom fill value
-reindexSeries(s, ["a", "b", "c", "d"], { fillValue: 0 }).toArray();
+console.log(reindexSeries(s, ["a", "b", "c", "d"], { fillValue: 0 }).toArray());
// → [10, 20, 30, 0]
// Drop labels
-reindexSeries(s, ["a", "c"]).toArray();
+console.log(reindexSeries(s, ["a", "c"]).toArray());
// → [10, 30]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -203,21 +203,21 @@ 2 · Fill methods
});
// Forward fill — carry last known value forward
-reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "ffill" }).toArray();
+console.log(reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "ffill" }).toArray());
// → [15, 15, 18, 18, 18, 22]
// ^^ ^^ ^^ ← filled from left
// Backward fill — carry next known value backward
-reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "bfill" }).toArray();
+console.log(reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "bfill" }).toArray());
// → [15, 18, 18, 22, 22, 22]
// ^^ ^^ ^^ ← filled from right
// Nearest — use closest value (prefer right on tie)
-reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "nearest" }).toArray();
+console.log(reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "nearest" }).toArray());
// → [15, 15, 18, 18, 22, 22]
// Limit — cap consecutive fills
-reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "ffill", limit: 1 }).toArray();
+console.log(reindexSeries(temps, [0, 1, 2, 3, 4, 5], { method: "ffill", limit: 1 }).toArray());
// → [15, 15, 18, null, null, 22]
// ^^ ^^ only 1 consecutive fill
Click ▶ Run to execute
@@ -244,11 +244,11 @@ 3 · reindexDataFrame — rows
// shape [3, 2], RangeIndex [0, 1, 2]
// Extend to 5 rows — new rows filled with null
-reindexDataFrame(df, { index: [0, 1, 2, 3, 4] }).col("open").toArray();
+console.log(reindexDataFrame(df, { index: [0, 1, 2, 3, 4] }).col("open").toArray());
// → [100, 102, 105, null, null]
// Forward-fill new rows
-reindexDataFrame(df, { index: [0, 1, 2, 3, 4], method: "ffill" }).col("open").toArray();
+console.log(reindexDataFrame(df, { index: [0, 1, 2, 3, 4], method: "ffill" }).col("open").toArray());
// → [100, 102, 105, 105, 105]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -270,12 +270,12 @@ 4 · reindexDataFrame — columns
const df = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
// Reorder columns
-reindexDataFrame(df, { columns: ["b", "a"] }).columns.toArray();
+console.log(reindexDataFrame(df, { columns: ["b", "a"] }).columns.toArray());
// → ["b", "a"]
// Add a new column filled with 0
const r = reindexDataFrame(df, { columns: ["a", "b", "c"], fillValue: 0 });
-r.col("c").toArray();
+console.log(r.col("c").toArray());
// → [0, 0, 0]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -305,8 +305,8 @@ 5 · Reindex rows and columns simultaneously
fillValue: -1,
});
// shape [4, 3]
-r.col("z").toArray(); // → [-1, -1, -1, -1]
-r.col("x").toArray(); // → [1, 2, 3, -1]
+console.log(r.col("z").toArray()); // → [-1, -1, -1, -1]
+console.log(r.col("x").toArray()); // → [1, 2, 3, -1]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/rename_ops.html b/playground/rename_ops.html
index 8dbf1ad5..2317026b 100644
--- a/playground/rename_ops.html
+++ b/playground/rename_ops.html
@@ -177,37 +177,37 @@ Code Examples
const s = new Series({ data: [1, 2, 3], index: ["a", "b", "c"] });
// Record mapping — only matched labels are changed
-renameSeriesIndex(s, { a: "x", c: "z" }).index.values; // ["x", "b", "z"]
+console.log(renameSeriesIndex(s, { a: "x", c: "z" }).index.values); // ["x", "b", "z"]
// Function mapper — called for every index label
-renameSeriesIndex(s, l => l.toUpperCase()).index.values; // ["A", "B", "C"]
+console.log(renameSeriesIndex(s, l => l.toUpperCase()).index.values); // ["A", "B", "C"]
// ── renameDataFrame ──────────────────────────────────────────────────────────
const df = DataFrame.fromColumns({ a: [1, 2], b: [3, 4] },
{ index: ["r0", "r1"] });
// Rename columns
-renameDataFrame(df, { columns: { a: "x", b: "y" } }).columns.values; // ["x","y"]
+console.log(renameDataFrame(df, { columns: { a: "x", b: "y" } }).columns.values); // ["x","y"]
// Rename row index
-renameDataFrame(df, { index: { r0: "row0", r1: "row1" } }).index.values;
+console.log(renameDataFrame(df, { index: { r0: "row0", r1: "row1" } }).index.values);
// ── add_prefix / add_suffix ──────────────────────────────────────────────────
-addPrefixDataFrame(df, "col_").columns.values; // ["col_a","col_b"]
-addSuffixDataFrame(df, "_v1").columns.values; // ["a_v1","b_v1"]
+console.log(addPrefixDataFrame(df, "col_").columns.values); // ["col_a","col_b"]
+console.log(addSuffixDataFrame(df, "_v1").columns.values); // ["a_v1","b_v1"]
-addPrefixSeries(s, "idx_").index.values; // ["idx_a","idx_b","idx_c"]
-addSuffixSeries(s, "_end").index.values; // ["a_end","b_end","c_end"]
+console.log(addPrefixSeries(s, "idx_").index.values); // ["idx_a","idx_b","idx_c"]
+console.log(addSuffixSeries(s, "_end").index.values); // ["a_end","b_end","c_end"]
// ── set_axis ─────────────────────────────────────────────────────────────────
-setAxisSeries(s, ["x", "y", "z"]).index.values; // ["x","y","z"]
-setAxisDataFrame(df, ["col1","col2"], 1).columns.values; // ["col1","col2"]
-setAxisDataFrame(df, ["rowA","rowB"], 0).index.values; // ["rowA","rowB"]
+console.log(setAxisSeries(s, ["x", "y", "z"]).index.values); // ["x","y","z"]
+console.log(setAxisDataFrame(df, ["col1","col2"], 1).columns.values); // ["col1","col2"]
+console.log(setAxisDataFrame(df, ["rowA","rowB"], 0).index.values); // ["rowA","rowB"]
// ── to_frame ─────────────────────────────────────────────────────────────────
const score = new Series({ data: [90, 80, 70], name: "score" });
-seriesToFrame(score).columns.values; // ["score"]
-seriesToFrame(score, "points").columns.values; // ["points"]
+console.log(seriesToFrame(score).columns.values); // ["score"]
+console.log(seriesToFrame(score, "points").columns.values); // ["points"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/rolling_apply.html b/playground/rolling_apply.html
index ecfcac0a..ff99fed7 100644
--- a/playground/rolling_apply.html
+++ b/playground/rolling_apply.html
@@ -179,7 +179,7 @@ 1. rollingApply — Custom Function Per Window
// Custom: range (max - min) over each 3-day window
const range = (w) => Math.max(...w) - Math.min(...w);
-rollingApply(prices, 3, range).toArray();
+console.log(rollingApply(prices, 3, range).toArray());
// [null, null, 2, 4, 4, 5]
// ↑↑ insufficient data (need 3 observations)
Click ▶ Run to execute
@@ -198,11 +198,11 @@ Options
// minPeriods=1 → start computing from the very first position
-rollingApply(prices, 3, range, { minPeriods: 1 }).toArray();
+console.log(rollingApply(prices, 3, range, { minPeriods: 1 }).toArray());
// [0, 2, 2, 4, 4, 5]
// center=true → symmetric window around each point
-rollingApply(prices, 3, range, { center: true }).toArray();
+console.log(rollingApply(prices, 3, range, { center: true }).toArray());
// [null, 2, 4, 4, 5, null]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -235,7 +235,8 @@ 2. rollingAgg — Multiple Aggregations at Once
// result is a DataFrame with columns: "mean", "max", "min", "range"
// result.col("mean").toArray() → [null, null, 2, 3, 4, 5, 6, 7]
-// result.col("range").toArray() → [null, null, 2, 2, 2, 2, 2, 2]
+// result.col("range").toArray() → [null, null, 2, 2, 2, 2, 2, 2]
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -263,7 +264,7 @@ 3. dataFrameRollingApply — Apply Per Column
// Pairwise range within each 2-step window per column
const range = (w) => Math.max(...w) - Math.min(...w);
-dataFrameRollingApply(df, 2, range);
+console.log(dataFrameRollingApply(df, 2, range));
// open close
// 0 null null
// 1 2 2
@@ -304,7 +305,8 @@ 4. dataFrameRollingAgg — Multi-Agg Per Column
// A_sum: [null, null, 6, 9, 12]
// A_mean: [null, null, 2, 3, 4]
// B_sum: [null, null, 60, 90, 120]
-// B_mean: [null, null, 20, 30, 40]
+// B_mean: [null, null, 20, 30, 40]
+console.log(out);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -342,7 +344,8 @@ Use case: Bollinger Band width
const mean = stats.col("mean").toArray()[i];
if (std === null || mean === null || mean === 0) return null;
return (4 * (std as number)) / (mean as number);
-});
+});
+console.log(bw);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/scalar_extract.html b/playground/scalar_extract.html
index 3f1554ca..bf8bbc13 100644
--- a/playground/scalar_extract.html
+++ b/playground/scalar_extract.html
@@ -190,8 +190,8 @@ squeezeSeries — extract scalar from a single-element Series
import { Series, squeezeSeries } from "tsb";
-squeezeSeries(new Series({ data: [42] })); // 42
-squeezeSeries(new Series({ data: [1, 2, 3] })); // Series([1, 2, 3])
+console.log(squeezeSeries(new Series({ data: [42] }))); // 42
+console.log(squeezeSeries(new Series({ data: [1, 2, 3] }))); // Series([1, 2, 3])
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -238,16 +238,16 @@ squeezeDataFrame — squeeze 1-D axis objects
import { DataFrame, squeezeDataFrame } from "tsb";
// 1×1 → scalar
-squeezeDataFrame(DataFrame.fromColumns({ A: [10] })); // 10
+console.log(squeezeDataFrame(DataFrame.fromColumns({ A: [10] }))); // 10
// 1 row, N cols → Series over columns
-squeezeDataFrame(DataFrame.fromColumns({ A: [1], B: [2] })); // Series([1, 2])
+console.log(squeezeDataFrame(DataFrame.fromColumns({ A: [1], B: [2] }))); // Series([1, 2])
// N rows, 1 col → Series over rows
-squeezeDataFrame(DataFrame.fromColumns({ A: [1, 2, 3] })); // Series([1, 2, 3])
+console.log(squeezeDataFrame(DataFrame.fromColumns({ A: [1, 2, 3] }))); // Series([1, 2, 3])
// axis=1: force squeeze along columns axis
-squeezeDataFrame(DataFrame.fromColumns({ A: [1, 2, 3] }), 1); // Series([1, 2, 3])
+console.log(squeezeDataFrame(DataFrame.fromColumns({ A: [1, 2, 3] }), 1)); // Series([1, 2, 3])
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -289,8 +289,8 @@ itemSeries — return the single element of a Series
import { Series, itemSeries } from "tsb";
-itemSeries(new Series({ data: [7] })); // 7
-itemSeries(new Series({ data: [1, 2] })); // throws RangeError
+console.log(itemSeries(new Series({ data: [7] }))); // 7
+console.log(itemSeries(new Series({ data: [1, 2] }))); // throws RangeError
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -330,10 +330,10 @@ boolSeries / boolDataFrame — convert to boolean
import { Series, DataFrame, boolSeries, boolDataFrame } from "tsb";
-boolSeries(new Series({ data: [1] })); // true
-boolSeries(new Series({ data: [0] })); // false
-boolDataFrame(DataFrame.fromColumns({ A: [1] })); // true
-boolDataFrame(DataFrame.fromColumns({ A: [false] })); // false
+console.log(boolSeries(new Series({ data: [1] }))); // true
+console.log(boolSeries(new Series({ data: [0] }))); // false
+console.log(boolDataFrame(DataFrame.fromColumns({ A: [1] }))); // true
+console.log(boolDataFrame(DataFrame.fromColumns({ A: [false] }))); // false
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -378,11 +378,11 @@ firstValidIndex / lastValidIndex — find first/last non-NA label
import { Series, firstValidIndex, lastValidIndex } from "tsb";
const s = new Series({ data: [null, NaN, 3, 4], index: ["a", "b", "c", "d"] });
-firstValidIndex(s); // "c"
-lastValidIndex(s); // "d"
+console.log(firstValidIndex(s)); // "c"
+console.log(lastValidIndex(s)); // "d"
const allNA = new Series({ data: [null, null] });
-firstValidIndex(allNA); // null
+console.log(firstValidIndex(allNA)); // null
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -427,8 +427,8 @@ dataFrameFirstValidIndex / dataFrameLastValidIndex
A: [null, null, 1],
B: [null, 2, 3],
});
-dataFrameFirstValidIndex(df); // 1
-dataFrameLastValidIndex(df); // 2
+console.log(dataFrameFirstValidIndex(df)); // 1
+console.log(dataFrameLastValidIndex(df)); // 2
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/select_dtypes.html b/playground/select_dtypes.html
index 1aebc52c..8c172170 100644
--- a/playground/select_dtypes.html
+++ b/playground/select_dtypes.html
@@ -253,7 +253,8 @@ 6 · Interactive: try your own
z: ["a", "b", "c"],
});
const result = selectDtypes(df, { include: "number" });
-return result.columns.toArray().join(", ");
+return result.columns.toArray().join(", ");
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/sem_var.html b/playground/sem_var.html
index 521c67b8..7dfbd2d4 100644
--- a/playground/sem_var.html
+++ b/playground/sem_var.html
@@ -165,7 +165,8 @@ 1 · Sample variance (ddof=1)
const s = new Series({ data: [2, 4, 4, 4, 5, 5, 7, 9] });
varSeries(s); // 4.0 (sample variance, ddof=1)
-varSeries(s, { ddof: 0 }); // 3.5 (population variance, ddof=0)
+varSeries(s, { ddof: 0 }); // 3.5 (population variance, ddof=0)
+console.log(s);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -184,7 +185,7 @@ 2 · Standard error of the mean
import { semSeries } from "tsb";
// SEM = sqrt(var / n)
-semSeries(s); // sqrt(4 / 8) ≈ 0.7071
+console.log(semSeries(s)); // sqrt(4 / 8) ≈ 0.7071
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -204,7 +205,8 @@ 3 · Handling missing values
varSeries(s2); // skipna=true (default): ignores null
varSeries(s2, { skipna: false }); // propagates NaN when null present
-varSeries(s2, { minCount: 5 }); // NaN: need 5 valid values but only 4
+varSeries(s2, { minCount: 5 }); // NaN: need 5 valid values but only 4
+console.log(s2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -228,7 +230,7 @@ 4 · DataFrame column-wise variance
});
varDataFrame(df); // Series { a: 1, b: 100 }
-semDataFrame(df); // Series { a: sqrt(1/3), b: sqrt(100/3) }
+console.log(semDataFrame(df)); // Series { a: sqrt(1/3), b: sqrt(100/3) }
varDataFrame(df, { axis: 1 }); // row-wise variance
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -251,7 +253,8 @@ 5 · numericOnly — skip non-numeric columns
});
varDataFrame(df2, { numericOnly: true });
-// Only includes "score", excludes "label"
+// Only includes "score", excludes "label"
+console.log(df2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/skew_kurt.html b/playground/skew_kurt.html
index 3157da85..d326c945 100644
--- a/playground/skew_kurt.html
+++ b/playground/skew_kurt.html
@@ -162,7 +162,7 @@ 1 · Symmetric distribution — skew ≈ 0
const s = new Series({ data: [1, 2, 3, 4, 5] });
-skewSeries(s);
+console.log(skewSeries(s));
// → 0
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -180,7 +180,7 @@ 2 · Right-skewed distribution — positive skew
const s = new Series({ data: [1, 2, 3, 4, 100] });
-skewSeries(s);
+console.log(skewSeries(s));
// → large positive value
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -198,7 +198,7 @@ 3 · Kurtosis — uniform-like (platykurtic, negative excess)
const s = new Series({ data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] });
-kurtSeries(s);
+console.log(kurtSeries(s));
// → negative (flatter than normal)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -215,8 +215,8 @@ 4 · NaN propagation — too few values
↺ Reset
- skewSeries(new Series({ data: [1, 2] })); // NaN — need ≥ 3
-kurtSeries(new Series({ data: [1, 2, 3] })); // NaN — need ≥ 4
+ console.log(skewSeries(new Series({ data: [1, 2] }))); // NaN — need ≥ 3
+console.log(kurtSeries(new Series({ data: [1, 2, 3] }))); // NaN — need ≥ 4
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -236,7 +236,7 @@ 5 · DataFrame column-wise skewness
symmetric: [1, 2, 3, 4, 5],
right_skew: [1, 2, 3, 4, 100],
});
-skewDataFrame(df).values;
+console.log(skewDataFrame(df).values);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -255,7 +255,7 @@ 6 · DataFrame row-wise kurtosis
const df = DataFrame.fromColumns({
a: [1, 10], b: [2, 10], c: [3, 10], d: [4, 10], e: [100, 10], f: [5, 10],
});
-kurtDataFrame(df, { axis: 1 }).values;
+console.log(kurtDataFrame(df, { axis: 1 }).values);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/sort_ops.html b/playground/sort_ops.html
index 9c9ba9f4..1d5ed930 100644
--- a/playground/sort_ops.html
+++ b/playground/sort_ops.html
@@ -194,9 +194,9 @@ sortValuesSeries — sort a Series by its values
const s = new Series({ data: [3, 1, 2], index: ["b", "a", "c"] });
-sortValuesSeries(s); // [1, 2, 3] index: ["a","c","b"]
-sortValuesSeries(s, { ascending: false }); // [3, 2, 1] index: ["b","c","a"]
-sortValuesSeries(s, { ignoreIndex: true }); // resets index to [0, 1, 2]
+console.log(sortValuesSeries(s)); // [1, 2, 3] index: ["a","c","b"]
+console.log(sortValuesSeries(s, { ascending: false })); // [3, 2, 1] index: ["b","c","a"]
+console.log(sortValuesSeries(s, { ignoreIndex: true })); // resets index to [0, 1, 2]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -233,8 +233,8 @@ NaN / null handling
const s2 = new Series({ data: [3, null, 1] });
-sortValuesSeries(s2); // [1, 3, null]
-sortValuesSeries(s2, { naPosition: "first" }); // [null, 1, 3]
+console.log(sortValuesSeries(s2)); // [1, 3, null]
+console.log(sortValuesSeries(s2, { naPosition: "first" })); // [null, 1, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -271,7 +271,7 @@ sortIndexSeries — sort a Series by its index labels
import { sortIndexSeries } from "tsb";
const s = new Series({ data: [3, 1, 2], index: ["b", "a", "c"] });
-sortIndexSeries(s);
+console.log(sortIndexSeries(s));
// values: [1, 3, 2], index: ["a", "b", "c"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -317,10 +317,10 @@ sortValuesDataFrame — sort DataFrame rows by column values
const df = DataFrame.fromColumns({ a: [3, 1, 2], b: [10, 30, 20] });
-sortValuesDataFrame(df, "a");
+console.log(sortValuesDataFrame(df, "a"));
// col a: [1, 2, 3] col b: [30, 20, 10]
-sortValuesDataFrame(df, ["a", "b"], { ascending: [true, false] });
+console.log(sortValuesDataFrame(df, ["a", "b"], { ascending: [true, false] }));
// compound sort: by a ascending, then b descending
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -359,11 +359,11 @@ sortIndexDataFrame — sort DataFrame rows (or columns) by index
import { sortIndexDataFrame } from "tsb";
const df2 = DataFrame.fromColumns({ z: [1], a: [2], m: [3] });
-sortIndexDataFrame(df2, { axis: 1 });
+console.log(sortIndexDataFrame(df2, { axis: 1 }));
// columns in alphabetical order: "a", "m", "z"
const df3 = DataFrame.fromColumns({ v: [1, 2, 3] }, { index: ["c", "a", "b"] });
-sortIndexDataFrame(df3);
+console.log(sortIndexDataFrame(df3));
// rows in index order: "a" (2), "b" (3), "c" (1)
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/str_findall_and_json_denormalize.html b/playground/str_findall_and_json_denormalize.html
index a8a9e94e..a8a2e70c 100644
--- a/playground/str_findall_and_json_denormalize.html
+++ b/playground/str_findall_and_json_denormalize.html
@@ -183,8 +183,8 @@ 1. strFindall — all regex matches per element
// ]
// Parse the JSON to get actual arrays:
-JSON.parse(allPrices.values[0]); // ["$10.99", "$5.00"]
-JSON.parse(allPrices.values[1]); // []
+console.log(JSON.parse(allPrices.values[0])); // ["$10.99", "$5.00"]
+console.log(JSON.parse(allPrices.values[1])); // []
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -205,7 +205,8 @@ With capture groups
const names = strFindall(s, /name: (\w+)/);
// Series ['["Alice"]', '["Bob"]', '[]']
-// First capture group is extracted (pandas behaviour)
+// First capture group is extracted (pandas behaviour)
+console.log(names);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -224,7 +225,8 @@ Null / NaN handling
const s = new Series({ data: ['hello', null, NaN, 'world'] });
const result = strFindall(s, /\w+/);
// Series ['["hello"]', null, null, '["world"]']
-// Null/NaN elements return null (not []) — matches pandas
+// Null/NaN elements return null (not []) — matches pandas
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -248,7 +250,7 @@ 2. strFindallCount — count matches per element
// Count vowels per word
const vowels = new Series({ data: ['beautiful', 'rhythm', 'aeiou'] });
-strFindallCount(vowels, /[aeiou]/i);
+console.log(strFindallCount(vowels, /[aeiou]/i));
// Series [5, 0, 5]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -278,7 +280,8 @@ 3. strFindFirst — first match per element
// Extract just the year (first capture group)
const years = strFindFirst(logs, /(\d{4})-\d{2}-\d{2}/);
-// Series ['2024', '2024', null]
+// Series ['2024', '2024', null]
+console.log(years);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -311,7 +314,8 @@ 4. strFindallExpand — expand capture groups into a DataFrame
// 0 1
// 0 John 30
// 1 Jane 25
-// 2 null null
+// 2 null null
+console.log(df2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -354,7 +358,8 @@ 5. toJsonDenormalize — flat DataFrame → nested JSON
];
const df = jsonNormalize(original);
const recovered = toJsonDenormalize(df);
-// recovered ≈ original (with the same structure)
+// recovered ≈ original (with the same structure)
+console.log(recovered);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -375,7 +380,7 @@ Custom separator
'user__name': ['Alice'],
'user__city': ['NYC'],
});
-toJsonDenormalize(df2, { sep: '__' });
+console.log(toJsonDenormalize(df2, { sep: '__' }));
// [{ user: { name: 'Alice', city: 'NYC' } }]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -393,7 +398,7 @@ Drop null values
const df3 = DataFrame.fromColumns({ a: [1, null], b: [null, 2] });
-toJsonDenormalize(df3, { dropNull: true });
+console.log(toJsonDenormalize(df3, { dropNull: true }));
// [{ a: 1 }, { b: 2 }] ← null fields are omitted
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -412,7 +417,7 @@ toJsonRecords — orient="records"
import { toJsonRecords } from 'tsb';
const df = DataFrame.fromColumns({ a: [1, 2], b: ['x', 'y'] });
-toJsonRecords(df);
+console.log(toJsonRecords(df));
// [{ a: 1, b: 'x' }, { a: 2, b: 'y' }]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -430,10 +435,10 @@ toJsonSplit — orient="split"
import { toJsonSplit } from 'tsb';
-toJsonSplit(df);
+console.log(toJsonSplit(df));
// { columns: ['a', 'b'], index: [0, 1], data: [[1, 'x'], [2, 'y']] }
-toJsonSplit(df, { includeIndex: false });
+console.log(toJsonSplit(df, { includeIndex: false }));
// { columns: ['a', 'b'], data: [[1, 'x'], [2, 'y']] }
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -451,7 +456,7 @@ toJsonIndex — orient="index"
import { toJsonIndex } from 'tsb';
-toJsonIndex(df);
+console.log(toJsonIndex(df));
// { '0': { a: 1, b: 'x' }, '1': { a: 2, b: 'y' } }
// With custom string index
@@ -459,7 +464,7 @@ toJsonIndex — orient="index"
{ v: [10, 20] },
{ index: ['alice', 'bob'] }
);
-toJsonIndex(df2);
+console.log(toJsonIndex(df2));
// { alice: { v: 10 }, bob: { v: 20 } }
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/style.html b/playground/style.html
index c7ff9071..5afd7a6c 100644
--- a/playground/style.html
+++ b/playground/style.html
@@ -183,7 +183,8 @@ Overview
.setTableStyles([
{ selector: "th", props: { "background-color": "#343a40", color: "#fff" } },
])
- .toHtml();
+ .toHtml();
+console.log(html);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -235,7 +236,8 @@ Factory function
const styler = dataFrameStyle(df);
// Equivalent to: new Styler(df)
-// Equivalent to: df.style (in pandas)
+// Equivalent to: df.style (in pandas)
+console.log(styler);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -252,10 +254,10 @@ .format(formatter, subset?, naRep?)
// Function formatter
-dataFrameStyle(df).format((v) => typeof v === "number" ? `$${v.toFixed(2)}` : String(v));
+console.log(dataFrameStyle(df).format((v) => typeof v === "number" ? `$${v.toFixed(2)}` : String(v)));
// Template string (replaces {v} with the cell value)
-dataFrameStyle(df).format("{v}%", ["pct_col"]);
+console.log(dataFrameStyle(df).format("{v}%", ["pct_col"]));
// Only format specific columns
dataFrameStyle(df).format(
@@ -264,7 +266,7 @@ .format(formatter, subset?, naRep?)
);
// null formatter resets to default
-dataFrameStyle(df).format(null);
+console.log(dataFrameStyle(df).format(null));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -281,7 +283,7 @@ .formatIndex(formatter)
// Format the row index labels
-dataFrameStyle(df).formatIndex((v) => `[${String(v)}]`);
+console.log(dataFrameStyle(df).formatIndex((v) => `[${String(v)}]`));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -298,7 +300,7 @@ .setPrecision(n)
// Show 2 decimal places by default
-dataFrameStyle(df).setPrecision(2);
+console.log(dataFrameStyle(df).setPrecision(2));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -315,7 +317,7 @@ .setNaRep(str)
// Show "N/A" for missing values
-dataFrameStyle(df).setNaRep("N/A");
+console.log(dataFrameStyle(df).setNaRep("N/A"));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -342,8 +344,8 @@ .apply(fn, axis?, subset?)
);
// String axis aliases
-dataFrameStyle(df).apply(fn, "index"); // same as axis=0
-dataFrameStyle(df).apply(fn, "columns"); // same as axis=1
+console.log(dataFrameStyle(df).apply(fn, "index")); // same as axis=0
+console.log(dataFrameStyle(df).apply(fn, "columns")); // same as axis=1
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -365,7 +367,7 @@ .applymap(fn, subset?) / .map(fn, subset?)
);
// .map() is an alias
-dataFrameStyle(df).map((v) => v === null ? "background-color: #ffeeee;" : "");
+console.log(dataFrameStyle(df).map((v) => v === null ? "background-color: #ffeeee;" : ""));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -382,7 +384,7 @@ .setProperties(props, subset?)
// Apply CSS to all cells (or a subset)
-dataFrameStyle(df).setProperties({ "font-weight": "bold", color: "navy" }, ["important"]);
+console.log(dataFrameStyle(df).setProperties({ "font-weight": "bold", color: "navy" }, ["important"]));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -437,7 +439,7 @@ .highlightNull(color?, subset?)
↺ Reset
- dataFrameStyle(df).highlightNull("orange"); // default color: "red"
+ console.log(dataFrameStyle(df).highlightNull("orange")); // default color: "red"
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -501,7 +503,7 @@ .textGradient(options?)
// Same as backgroundGradient but applies to text color instead
-dataFrameStyle(df).textGradient({ cmap: "RdYlGn" });
+console.log(dataFrameStyle(df).textGradient({ cmap: "RdYlGn" }));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -540,7 +542,7 @@ .setCaption(text)
↺ Reset
- dataFrameStyle(df).setCaption("Q3 Sales Report");
+ console.log(dataFrameStyle(df).setCaption("Q3 Sales Report"));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -578,7 +580,7 @@ .setTableAttributes(attrs)
↺ Reset
- dataFrameStyle(df).setTableAttributes('class="report-table" id="q3-report"');
+ console.log(dataFrameStyle(df).setTableAttributes('class="report-table" id="q3-report"'));
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -594,10 +596,10 @@ .hide(axis?, subset?)
↺ Reset
- dataFrameStyle(df).hide(0); // hide row index
-dataFrameStyle(df).hide("index"); // same
-dataFrameStyle(df).hide(1, ["col_a"]); // hide specific columns
-dataFrameStyle(df).hide("columns", ["b"]); // same
+ console.log(dataFrameStyle(df).hide(0)); // hide row index
+console.log(dataFrameStyle(df).hide("index")); // same
+console.log(dataFrameStyle(df).hide(1, ["col_a"])); // hide specific columns
+console.log(dataFrameStyle(df).hide("columns", ["b"])); // same
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -618,7 +620,8 @@ .toHtml(uuid?) / .render(uuid?)
.toHtml(); // .render() is an alias
// Inject into a page
-document.getElementById("output").innerHTML = html;
+document.getElementById("output").innerHTML = html;
+console.log(html);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -636,7 +639,8 @@ .toLatex(environment?, hrules?)
const latex: string = dataFrameStyle(df)
.setCaption("Results")
- .toLatex("tabular", true); // environment, hrules
+ .toLatex("tabular", true); // environment, hrules
+console.log(latex);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -655,7 +659,8 @@ .exportStyles()
const records: StyleRecord[] = dataFrameStyle(df)
.highlightMax()
.exportStyles();
-// [{ row: 0, col: 1, css: "background-color: yellow;" }, ...]
+// [{ row: 0, col: 1, css: "background-color: yellow;" }, ...]
+console.log(records);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -672,7 +677,7 @@ .clearStyles()
// Remove all accumulated styles (keeps caption, hide state, precision)
-styler.clearStyles();
+console.log(styler.clearStyles());
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/swaplevel.html b/playground/swaplevel.html
index 54fdad58..c4363906 100644
--- a/playground/swaplevel.html
+++ b/playground/swaplevel.html
@@ -198,7 +198,8 @@ swapLevelSeries — swap two levels
const swapped = swapLevelSeries(s, 0, 1);
// index tuples: [(1,"a"), (2,"a"), (1,"b")]
-// values: [10, 20, 30]
+// values: [10, 20, 30]
+console.log(swapped);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -249,7 +250,8 @@ swapLevelDataFrame — swap row-index levels
);
const swapped = swapLevelDataFrame(df, "letter", "number");
-// row index tuples: [(1,"a"), (2,"b")]
+// row index tuples: [(1,"a"), (2,"b")]
+console.log(swapped);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -297,7 +299,8 @@ reorderLevelsSeries — arbitrary level reordering
const s = new Series({ data: [10, 20], index: mi as unknown as Index<Label> });
const reordered = reorderLevelsSeries(s, [2, 0, 1]);
-// index tuples: [("x","a",1), ("y","b",2)]
+// index tuples: [("x","a",1), ("y","b",2)]
+console.log(reordered);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -348,7 +351,8 @@ reorderLevelsDataFrame
);
const reordered = reorderLevelsDataFrame(df, [1, 0]);
-// row index tuples: [(1,"a"), (2,"b")]
+// row index tuples: [(1,"a"), (2,"b")]
+console.log(reordered);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/testing.html b/playground/testing.html
index 49e13fcb..b6a80b37 100644
--- a/playground/testing.html
+++ b/playground/testing.html
@@ -186,7 +186,7 @@ Passing example
const a = new Series({ data: [1, 2, 3], name: "x" });
const b = new Series({ data: [1, 2, 3], name: "x" });
-assertSeriesEqual(a, b);
+console.log(assertSeriesEqual(a, b));
// ✅ no exception thrown
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -204,7 +204,7 @@ Failing example
const c = new Series({ data: [1, 2, 99], name: "x" });
-assertSeriesEqual(a, c);
+console.log(assertSeriesEqual(a, c));
// ❌ AssertionError: Series: values differ at index 2 (position 2).
// left=3, right=99
Click ▶ Run to execute
@@ -224,9 +224,9 @@ Float tolerance
const p = new Series({ data: [1.0, 2.0] });
const q = new Series({ data: [1.0 + 1e-9, 2.0] }); // tiny rounding error
-assertSeriesEqual(p, q); // ✅ passes (within default atol=1e-8)
+console.log(assertSeriesEqual(p, q)); // ✅ passes (within default atol=1e-8)
-assertSeriesEqual(p, q, { checkExact: true }); // ❌ exact comparison fails
+console.log(assertSeriesEqual(p, q, { checkExact: true })); // ❌ exact comparison fails
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -246,7 +246,7 @@ Passing example
const a = DataFrame.fromColumns({ x: [1, 2], y: [3, 4] });
const b = DataFrame.fromColumns({ x: [1, 2], y: [3, 4] });
-assertFrameEqual(a, b); // ✅
+console.log(assertFrameEqual(a, b)); // ✅
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -263,7 +263,7 @@ Ignore column order
const c = DataFrame.fromColumns({ y: [3, 4], x: [1, 2] }); // columns reversed
-assertFrameEqual(a, c, { checkLike: true }); // ✅ order ignored
+console.log(assertFrameEqual(a, c, { checkLike: true })); // ✅ order ignored
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -284,10 +284,10 @@ assertIndexEqual(left, right, options?)
const a = new Index(["a", "b", "c"]);
const b = new Index(["a", "b", "c"]);
-assertIndexEqual(a, b); // ✅
+console.log(assertIndexEqual(a, b)); // ✅
const c = new Index(["a", "b", "z"]);
-assertIndexEqual(a, c);
+console.log(assertIndexEqual(a, c));
// ❌ AssertionError: Index: Index values differ at position 2. left=c, right=z
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/to_datetime.html b/playground/to_datetime.html
index 59e15651..99c08a60 100644
--- a/playground/to_datetime.html
+++ b/playground/to_datetime.html
@@ -164,20 +164,20 @@ Quick examples
import { toDatetime, Series } from "tsb";
// Scalar
-toDatetime("2024-03-15"); // Date: Mar 15 2024
-toDatetime(1710460800000); // Date from Unix ms
-toDatetime(1710460800, { unit: "s" }); // Date from Unix seconds
-toDatetime(null); // null
-toDatetime("nope", { errors: "coerce" }); // null
-toDatetime("nope", { errors: "ignore" }); // "nope"
+console.log(toDatetime("2024-03-15")); // Date: Mar 15 2024
+console.log(toDatetime(1710460800000)); // Date from Unix ms
+console.log(toDatetime(1710460800, { unit: "s" })); // Date from Unix seconds
+console.log(toDatetime(null)); // null
+console.log(toDatetime("nope", { errors: "coerce" })); // null
+console.log(toDatetime("nope", { errors: "ignore" })); // "nope"
// Array
-toDatetime(["2024-01-01", null, "2024-06-15"]);
+console.log(toDatetime(["2024-01-01", null, "2024-06-15"]));
// => [Date, null, Date]
// Series
const s = new Series({ data: ["2024-01-01", "2024-06-15", null] });
-toDatetime(s);
+console.log(toDatetime(s));
// => Series<Date | null> with dtype=datetime
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/to_from_dict.html b/playground/to_from_dict.html
index 890a77e8..c84f9e95 100644
--- a/playground/to_from_dict.html
+++ b/playground/to_from_dict.html
@@ -170,27 +170,27 @@ Example — all orientations
);
// "dict" / "columns"
-toDictOriented(df, "dict");
+console.log(toDictOriented(df, "dict"));
// { name: { r0: "Alice", r1: "Bob" }, score: { r0: 92, r1: 85 } }
// "list"
-toDictOriented(df, "list");
+console.log(toDictOriented(df, "list"));
// { name: ["Alice", "Bob"], score: [92, 85] }
// "records"
-toDictOriented(df, "records");
+console.log(toDictOriented(df, "records"));
// [ { name: "Alice", score: 92 }, { name: "Bob", score: 85 } ]
// "split"
-toDictOriented(df, "split");
+console.log(toDictOriented(df, "split"));
// { index: ["r0", "r1"], columns: ["name", "score"], data: [["Alice", 92], ["Bob", 85]] }
// "index"
-toDictOriented(df, "index");
+console.log(toDictOriented(df, "index"));
// { r0: { name: "Alice", score: 92 }, r1: { name: "Bob", score: 85 } }
// fromDictOriented — columns (default)
-fromDictOriented({ name: ["Alice", "Bob"], score: [92, 85] });
+console.log(fromDictOriented({ name: ["Alice", "Bob"], score: [92, 85] }));
// fromDictOriented — index
fromDictOriented(
diff --git a/playground/to_numeric.html b/playground/to_numeric.html
index 56911d79..cb89d3b3 100644
--- a/playground/to_numeric.html
+++ b/playground/to_numeric.html
@@ -205,7 +205,8 @@ 3 · Series conversion
index: ["a", "b", "c"]
});
toNumericSeries(prices, { errors: "coerce" })
-// Series [10.5, NaN, 22] name="price"
+// Series [10.5, NaN, 22] name="price"
+console.log(prices);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -246,7 +247,8 @@ 5 · Live sandbox
// Try it yourself!
const s = new Series(["100", "200.5", "NaN", null, "abc"]);
const result = toNumericSeries(s, { errors: "coerce" });
-return JSON.stringify(result.values);
+return JSON.stringify(result.values);
+console.log(result);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/to_timedelta.html b/playground/to_timedelta.html
index 584edfc5..2287c8eb 100644
--- a/playground/to_timedelta.html
+++ b/playground/to_timedelta.html
@@ -164,34 +164,34 @@ Quick examples
import { toTimedelta, Timedelta, formatTimedelta, Series } from "tsb";
// Scalar — various string formats
-toTimedelta("1 days 02:03:04"); // Timedelta(93_784_000 ms)
-toTimedelta("01:30:00"); // Timedelta(5_400_000 ms)
-toTimedelta("P1DT2H3M4S"); // ISO 8601
-toTimedelta("1h 30m 20s 500ms"); // human-readable
+console.log(toTimedelta("1 days 02:03:04")); // Timedelta(93_784_000 ms)
+console.log(toTimedelta("01:30:00")); // Timedelta(5_400_000 ms)
+console.log(toTimedelta("P1DT2H3M4S")); // ISO 8601
+console.log(toTimedelta("1h 30m 20s 500ms")); // human-readable
// Scalar — numeric
-toTimedelta(1_000_000_000); // default unit "ns" → 1000 ms
-toTimedelta(5000, { unit: "ms" }); // 5000 ms
-toTimedelta(2, { unit: "D" }); // 2 days
+console.log(toTimedelta(1_000_000_000)); // default unit "ns" → 1000 ms
+console.log(toTimedelta(5000, { unit: "ms" })); // 5000 ms
+console.log(toTimedelta(2, { unit: "D" })); // 2 days
// Missing values
-toTimedelta(null); // null
-toTimedelta("nope", { errors: "coerce" }); // null
-toTimedelta("nope", { errors: "ignore" }); // "nope" (unchanged)
+console.log(toTimedelta(null)); // null
+console.log(toTimedelta("nope", { errors: "coerce" })); // null
+console.log(toTimedelta("nope", { errors: "ignore" })); // "nope" (unchanged)
// Timedelta arithmetic
const a = toTimedelta("1h") as Timedelta;
const b = toTimedelta("30m") as Timedelta;
-a.add(b).toString(); // "0 days 01:30:00"
-a.subtract(b).totalMs; // 1_800_000
+console.log(a.add(b).toString()); // "0 days 01:30:00"
+console.log(a.subtract(b).totalMs); // 1_800_000
// Array
-toTimedelta(["1h", "30m", null]);
+console.log(toTimedelta(["1h", "30m", null]));
// => [Timedelta(3_600_000), Timedelta(1_800_000), null]
// Series
const s = new Series({ data: ["1h", "30m", null] });
-toTimedelta(s);
+console.log(toTimedelta(s));
// => Series<Timedelta | null> with dtype=timedelta
// formatTimedelta
diff --git a/playground/transform_agg.html b/playground/transform_agg.html
index 24d1072b..12dc7045 100644
--- a/playground/transform_agg.html
+++ b/playground/transform_agg.html
@@ -167,19 +167,19 @@ API
import { seriesTransform, dataFrameTransform } from "tsb";
// single function or built-in name → Series
-seriesTransform(s, "cumsum");
-seriesTransform(s, (x) => x);
+console.log(seriesTransform(s, "cumsum"));
+console.log(seriesTransform(s, (x) => x));
// array → DataFrame (one column per function)
-seriesTransform(s, ["sum", "cumsum", "mean"]);
+console.log(seriesTransform(s, ["sum", "cumsum", "mean"]));
// Record → DataFrame with named columns
-seriesTransform(s, { total: "sum", running: "cumsum" });
+console.log(seriesTransform(s, { total: "sum", running: "cumsum" }));
// DataFrame transform (column-wise by default)
-dataFrameTransform(df, "cumsum");
-dataFrameTransform(df, { a: "sum", b: "cummin" }); // per-column
-dataFrameTransform(df, "cumsum", { axis: 1 }); // row-wise
+console.log(dataFrameTransform(df, "cumsum"));
+console.log(dataFrameTransform(df, { a: "sum", b: "cummin" })); // per-column
+console.log(dataFrameTransform(df, "cumsum", { axis: 1 })); // row-wise
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -220,20 +220,20 @@ Examples
const s = new Series({ data: [1, 2, 3, 4] });
// cumulative sum
-seriesTransform(s, "cumsum").values; // [1, 3, 6, 10]
+console.log(seriesTransform(s, "cumsum").values); // [1, 3, 6, 10]
// broadcast aggregate
-seriesTransform(s, "sum").values; // [10, 10, 10, 10]
+console.log(seriesTransform(s, "sum").values); // [10, 10, 10, 10]
// multiple functions
const df = seriesTransform(s, ["sum", "cumsum", "mean"]);
-df.col("sum").values; // [10, 10, 10, 10]
-df.col("cumsum").values; // [1, 3, 6, 10]
-df.col("mean").values; // [2.5, 2.5, 2.5, 2.5]
+console.log(df.col("sum").values); // [10, 10, 10, 10]
+console.log(df.col("cumsum").values); // [1, 3, 6, 10]
+console.log(df.col("mean").values); // [2.5, 2.5, 2.5, 2.5]
// DataFrame transform
const frame = DataFrame.fromColumns({ a: [1,2,3], b: [10,20,30] });
-dataFrameTransform(frame, "cumsum").col("b").values; // [10, 30, 60]
+console.log(dataFrameTransform(frame, "cumsum").col("b").values); // [10, 30, 60]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/truncate.html b/playground/truncate.html
index 2287cdd8..ca3530d8 100644
--- a/playground/truncate.html
+++ b/playground/truncate.html
@@ -203,9 +203,9 @@ truncateSeries — keep rows within [before, after]
const s = new Series({ data: [10, 20, 30, 40, 50], index: [0, 1, 2, 3, 4] });
-truncateSeries(s, 1, 3).values; // [20, 30, 40]
-truncateSeries(s, 2).values; // [30, 40, 50]
-truncateSeries(s, undefined, 2).values; // [10, 20, 30]
+console.log(truncateSeries(s, 1, 3).values); // [20, 30, 40]
+console.log(truncateSeries(s, 2).values); // [30, 40, 50]
+console.log(truncateSeries(s, undefined, 2).values); // [10, 20, 30]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -258,8 +258,8 @@ truncateDataFrame — truncate rows
);
const result = truncateDataFrame(df, 1, 3);
-result.col("a").values; // [20, 30, 40]
-result.index.values; // [1, 2, 3]
+console.log(result.col("a").values); // [20, 30, 40]
+console.log(result.index.values); // [1, 2, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -305,7 +305,7 @@ truncateDataFrame — truncate columns (axis=1)
const df = DataFrame.fromColumns({ a: [1, 2], b: [3, 4], c: [5, 6] });
const result = truncateDataFrame(df, "a", "b", { axis: 1 });
-result.columns.values; // ["a", "b"]
+console.log(result.columns.values); // ["a", "b"]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -356,7 +356,7 @@ String index truncation
index: ["apple", "banana", "cherry", "date", "elderberry"],
});
-truncateSeries(s, "banana", "date").values; // [2, 3, 4]
+console.log(truncateSeries(s, "banana", "date").values); // [2, 3, 4]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/update.html b/playground/update.html
index 8874d754..ccfa6937 100644
--- a/playground/update.html
+++ b/playground/update.html
@@ -191,7 +191,7 @@ seriesUpdate — basic overwrite
const s = new Series({ data: [1, null, 3], index: [0, 1, 2] });
const other = new Series({ data: [null, 20, null], index: [0, 1, 2] });
-seriesUpdate(s, other).values;
+console.log(seriesUpdate(s, other).values);
// [1, 20, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -237,7 +237,7 @@ overwrite=false — only fill NA
const s = new Series({ data: [1, null, 3] });
const other = new Series({ data: [10, 20, 30] });
-seriesUpdate(s, other, { overwrite: false }).values;
+console.log(seriesUpdate(s, other, { overwrite: false }).values);
// [1, 20, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -287,8 +287,8 @@ dataFrameUpdate — update from another DataFrame
const df = DataFrame.fromColumns({ a: [1, null, 3], b: [10, 20, 30] });
const other = DataFrame.fromColumns({ a: [null, 99, null] });
const result = dataFrameUpdate(df, other);
-result.col("a").values; // [1, 99, 3]
-result.col("b").values; // [10, 20, 30]
+console.log(result.col("a").values); // [1, 99, 3]
+console.log(result.col("b").values); // [10, 20, 30]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -310,7 +310,7 @@ Label alignment
const s = new Series({ data: [1, 2, 3], index: [0, 1, 2] });
// other only has label 1 — other labels unchanged
const other = new Series({ data: [99], index: [1] });
-seriesUpdate(s, other).values;
+console.log(seriesUpdate(s, other).values);
// [1, 99, 3]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/value_counts_full.html b/playground/value_counts_full.html
index 3f285240..11f53c8f 100644
--- a/playground/value_counts_full.html
+++ b/playground/value_counts_full.html
@@ -193,7 +193,8 @@ Basic binning
const s = new Series({ data: [1, 2, 3, 4, 5] });
const vc = valueCountsBinned(s, 2);
// Index: ["(0.995, 3.0]", "(3.0, 5.005]"]
-// Values: [3, 2] ← sorted by count (default)
+// Values: [3, 2] ← sorted by count (default)
+console.log(vc);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -212,7 +213,8 @@ Interval order (sort=false)
const vc2 = valueCountsBinned(s, 2, { sort: false });
// Index: ["(0.995, 3.0]", "(3.0, 5.005]"]
-// Values: [3, 2] ← in interval order
+// Values: [3, 2] ← in interval order
+console.log(vc2);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -231,7 +233,8 @@ Proportions (normalize=true)
const vc3 = valueCountsBinned(s, 2, { normalize: true });
// Index: ["(0.995, 3.0]", "(3.0, 5.005]"]
-// Values: [0.6, 0.4]
+// Values: [0.6, 0.4]
+console.log(vc3);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -250,7 +253,8 @@ Handling NaN / null
const s2 = new Series({ data: [1, null, 2, NaN, 3, 4, 5] });
const vc4 = valueCountsBinned(s2, 2);
-// NaN and null values are excluded. Total = 5.
+// NaN and null values are excluded. Total = 5.
+console.log(vc4);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/wide_to_long.html b/playground/wide_to_long.html
index 75482237..0f894a49 100644
--- a/playground/wide_to_long.html
+++ b/playground/wide_to_long.html
@@ -192,7 +192,7 @@ 1 · Numeric suffix (default)
A1: [1, 2], A2: [3, 4],
B1: [5, 6], B2: [7, 8],
});
-wideToLong(df, ["A", "B"], "id", "year");
+console.log(wideToLong(df, ["A", "B"], "id", "year"));
// id year A B
// x 1 1 5
// y 1 2 6
@@ -227,7 +227,8 @@ 2 · Underscore separator
// 1 pre 80
// 2 pre 90
// 1 post 85
-// 2 post 95
+// 2 post 95
+console.log(df);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -250,7 +251,7 @@ 3 · Multiple id columns
gdp2020: [21, 2.7, 3.8],
gdp2021: [23, 3.1, 4.2],
});
-wideToLong(df, "gdp", ["country","region"], "year", { sep: "" });
+console.log(wideToLong(df, "gdp", ["country","region"], "year", { sep: "" }));
// country region year gdp
// US East 2020 21
// UK South 2020 2.7
diff --git a/playground/window_extended.html b/playground/window_extended.html
index 0b368ebd..328f97a1 100644
--- a/playground/window_extended.html
+++ b/playground/window_extended.html
@@ -191,7 +191,8 @@ 1. rollingSem — Standard Error of the Mean
const s = new Series({ data: [2, 4, 4, 4, 5, 5, 7, 9], name: "x" });
const sem3 = rollingSem(s, 3);
-// [null, null, 0.667, 0, 0.577, 0.577, 1.155, 2.082]
+// [null, null, 0.667, 0, 0.577, 0.577, 1.155, 2.082]
+console.log(sem3);
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -232,7 +233,7 @@ 2. rollingSkew — Fisher-Pearson Skewness
import { rollingSkew, Series } from "tsb";
const s = new Series({ data: [1, 2, 3, 4, 5] });
-rollingSkew(s, 3);
+console.log(rollingSkew(s, 3));
// [null, null, 0, 0, 0] ← symmetric windows → zero skew
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -274,7 +275,7 @@ 3. rollingKurt — Excess Kurtosis
import { rollingKurt, Series } from "tsb";
const s = new Series({ data: [1, 2, 3, 4] });
-rollingKurt(s, 4);
+console.log(rollingKurt(s, 4));
// [null, null, null, -1.2] ← uniform distribution has kurt = -1.2
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
@@ -298,9 +299,9 @@ 4. rollingQuantile — Rolling Quantile
const s = new Series({ data: [1, 2, 3, 4, 5] });
-rollingQuantile(s, 0.5, 3); // rolling median: [null, null, 2, 3, 4]
-rollingQuantile(s, 0.25, 3); // [null, null, 1.5, 2.5, 3.5]
-rollingQuantile(s, 0.75, 3); // [null, null, 2.5, 3.5, 4.5]
+console.log(rollingQuantile(s, 0.5, 3)); // rolling median: [null, null, 2, 3, 4]
+console.log(rollingQuantile(s, 0.25, 3)); // [null, null, 1.5, 2.5, 3.5]
+console.log(rollingQuantile(s, 0.75, 3)); // [null, null, 2.5, 3.5, 4.5]
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent
diff --git a/playground/xs.html b/playground/xs.html
index 7272d74b..3e838963 100644
--- a/playground/xs.html
+++ b/playground/xs.html
@@ -172,10 +172,10 @@ Code Examples
);
// Select row "y" → Series { a: 2, b: 5 }
-xsDataFrame(df, "y");
+console.log(xsDataFrame(df, "y"));
// Select column "b" → Series { x: 4, y: 5, z: 6 }
-xsDataFrame(df, "b", { axis: 1 });
+console.log(xsDataFrame(df, "b", { axis: 1 }));
// ── MultiIndex ─────────────────────────────────────────────────────────────
const mi = MultiIndex.fromTuples([
@@ -185,11 +185,11 @@ Code Examples
const miDf = new DataFrame( ... , mi);
// All "A" rows → DataFrame with 2 rows
-xsDataFrame(miDf, "A");
+console.log(xsDataFrame(miDf, "A"));
// ── Series ─────────────────────────────────────────────────────────────────
const s = new Series({ data: [10, 20, 30], index: ["a", "b", "c"] });
-xsSeries(s, "b"); // → 20
+console.log(xsSeries(s, "b")); // → 20
Click ▶ Run to execute
Ctrl+Enter to run · Tab to indent