df-script 1.9.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +148 -235
  2. package/dist/api.d.ts +41 -36
  3. package/dist/columnExpressions/ColumnExpr.d.ts +5 -8
  4. package/dist/columnExpressions/functions/all.d.ts +13 -13
  5. package/dist/columnExpressions/functions/coalesce.d.ts +2 -2
  6. package/dist/columnExpressions/functions/duration.d.ts +16 -21
  7. package/dist/columnExpressions/functions/element.d.ts +10 -10
  8. package/dist/columnExpressions/functions/exclude.d.ts +14 -14
  9. package/dist/columnExpressions/functions/implode.d.ts +7 -7
  10. package/dist/columnExpressions/functions/lit.d.ts +9 -9
  11. package/dist/columnExpressions/functions/seqRange.d.ts +69 -0
  12. package/dist/columnExpressions/functions/struct.d.ts +6 -6
  13. package/dist/columnExpressions/functions/when.d.ts +25 -28
  14. package/dist/columnExpressions/index.d.ts +3 -7
  15. package/dist/columnExpressions/mixins/AggregationExpr.d.ts +550 -221
  16. package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +701 -327
  17. package/dist/columnExpressions/mixins/ArrayExpr.d.ts +508 -212
  18. package/dist/columnExpressions/mixins/ComparisonExpr.d.ts +398 -201
  19. package/dist/columnExpressions/mixins/LogicalExpr.d.ts +59 -29
  20. package/dist/columnExpressions/mixins/ManipulationExpr.d.ts +23 -9
  21. package/dist/columnExpressions/mixins/StandardExpr.d.ts +3234 -0
  22. package/dist/columnExpressions/mixins/StringExpr.d.ts +1163 -524
  23. package/dist/columnExpressions/mixins/StructExpr.d.ts +67 -25
  24. package/dist/columnExpressions/mixins/TemporalExpr.d.ts +518 -212
  25. package/dist/columnExpressions/mixins/WindowExpr.d.ts +270 -102
  26. package/dist/columnExpressions/typeInference.d.ts +3 -3
  27. package/dist/columnExpressions/types.d.ts +5 -0
  28. package/dist/columnExpressions/utils.d.ts +7 -0
  29. package/dist/constants.d.ts +11 -2
  30. package/dist/dataframe/dataframe.d.ts +755 -592
  31. package/dist/dataframe/grouped/grouped.d.ts +24 -6
  32. package/dist/dataframe/grouped.d.ts +70 -0
  33. package/dist/dataframe/index.d.ts +1 -1
  34. package/dist/dataframe/lazy.d.ts +37 -0
  35. package/dist/dataframe/types.d.ts +46 -22
  36. package/dist/dataframe/utils.d.ts +10 -4
  37. package/dist/datatypes/index.d.ts +11 -4
  38. package/dist/expressions.js +1 -0
  39. package/dist/expressions.mjs +1 -0
  40. package/dist/functions/concat.d.ts +68 -16
  41. package/dist/functions/index.d.ts +2 -2
  42. package/dist/functions/readCsv.d.ts +35 -0
  43. package/dist/functions/readJson.d.ts +33 -0
  44. package/dist/index.js +5 -6
  45. package/dist/index.mjs +5 -6
  46. package/dist/types.d.ts +42 -9
  47. package/dist/utils/array.d.ts +17 -14
  48. package/dist/utils/csv.d.ts +4 -1
  49. package/dist/utils/date.d.ts +3 -19
  50. package/dist/utils/duration.d.ts +7 -5
  51. package/dist/utils/json.d.ts +5 -3
  52. package/dist/utils/object.d.ts +0 -18
  53. package/dist/utils/string.d.ts +5 -0
  54. package/dist/utils.js +4 -0
  55. package/dist/utils.mjs +4 -0
  56. package/package.json +29 -8
  57. package/dist/assets/index-DBhGK6Tp.css +0 -1
  58. package/dist/assets/index-DEJEV_tU.js +0 -195
  59. package/dist/index.html +0 -17
package/README.md CHANGED
@@ -1,38 +1,57 @@
1
- # 🚀 DFScript
2
-
3
- [![GitHub Repository](https://img.shields.io/badge/GitHub-Repository-blue?style=for-the-badge&logo=github)](https://github.com/trentamorris/df-script)
1
+ # 🚀 df-script: High-Performance TypeScript DataFrame Library
2
+
3
+ [![GitHub Repository](https://img.shields.io/badge/GitHub-Repository-181717?style=for-the-badge&logo=github)](https://github.com/trentamorris/df-script)
4
+ [![npm version](https://img.shields.io/npm/v/df-script?style=for-the-badge&logo=npm&color=CB3837)](https://www.npmjs.com/package/df-script)
5
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/df-script?style=for-the-badge&color=blue)](https://bundlephobia.com/package/df-script)
6
+ [![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-success?style=for-the-badge)](#)
7
+ [![TypeScript & JavaScript](https://img.shields.io/badge/Supports-TS%20%7C%20TSX%20%7C%20JS%20%7C%20JSX-blue?style=for-the-badge&logo=typescript)](https://www.typescriptlang.org/)
8
+ [![Universal Runtimes](https://img.shields.io/badge/Runtimes-Node%20%7C%20Bun%20%7C%20Deno%20%7C%20Browser-brightgreen?style=for-the-badge)](#)
9
+ [![License](https://img.shields.io/npm/l/df-script?style=for-the-badge&color=informational)](LICENSE)
4
10
  [![Donate](https://img.shields.io/badge/Donate-Support-green?style=for-the-badge)](DONATIONS.md)
5
- [![Environment](https://img.shields.io/badge/Environment-Node.js%20%7C%20Browser%20%7C%20Bun%20%7C%20Deno%20%7C%20Workers-brightgreen?style=for-the-badge)](#)
6
- [![Zero Dependencies](https://img.shields.io/badge/Dependencies-Zero-success?style=for-the-badge)](#)
11
+ **df-script** is a blazing-fast, **zero-dependency**, expression-based DataFrame and data manipulation library for **TypeScript** and **JavaScript**. Heavily inspired by modern columnar engines like **Polars** and **Pandas**, `df-script` brings declarative, high-performance columnar analytical queries and ETL workflows directly to JavaScript environments (Node.js, Browser, Bun, Deno, and Edge Workers).
12
+
13
+ With cache-optimized columnar storage and flat memory layout under the hood, `df-script` eliminates garbage collection thrashing caused by intermediate array allocations in chained `.map()`, `.filter()`, and `.reduce()` calls.
14
+
15
+ ---
16
+
17
+ ## 🌐 Universal Language & Environment Support
7
18
 
8
- DFScript is a lightweight, high-performance, and **zero-dependency** data analysis library for TypeScript and JavaScript. Heavily inspired by modern dataframe libraries like **Polars** and **Pandas**, DFScript brings a robust, expression-based columnar data processing engine directly to the JavaScript ecosystem.
19
+ `df-script` is built with **zero native dependencies** and ships with dual **ESM** (`dist/index.mjs`) and **CommonJS** (`dist/index.js`) modules alongside comprehensive `.d.ts` type declarations. It runs natively everywhere JavaScript or TypeScript runs:
9
20
 
10
- With optimized columnar storage under the hood, DFScript enables you to build clean, maintainable, and type-safe data pipelines using a declarative expression API.
21
+ - 📄 **Languages & File Formats**: Full first-class support in **TypeScript (`.ts`, `.tsx`)**, **JavaScript (`.js`, `.jsx`)**, and module formats (`.mjs`, `.cjs`).
22
+ - ⚛️ **UI Frameworks & Bundlers**: React (JSX/TSX), Next.js, Vue, Nuxt, Svelte, SolidJS, Astro, Vite, Webpack, and esbuild.
23
+ - ⚙️ **Runtimes & Target Standard**: Standard **ES2020+** compatible. Fully tested on **Node.js** (14+), **Bun**, **Deno**, modern **Web Browsers** (Chrome 80+, Safari 13.1+, Firefox 74+, Edge 80+), Cloudflare Workers, Fastly Compute, and AWS Lambda.
24
+ - 🌐 **Browser / Client-Side Compatibility**: 100% in-memory analytical transformations, joins, grouping, and expressions run natively in all browser runtimes. File writing methods (`df.writeCsv()`, `df.writeJson()`) automatically fallback to returning strings or writing to custom stream objects when running in browser environments.
25
+ - 📦 **Package Managers**: Works seamlessly with `npm`, `pnpm`, `bun`, and `yarn`.
11
26
 
12
- ## 💡 Why DFScript?
27
+ ---
13
28
 
14
- Like many developers, I spent years working on frontend codebases filled with deeply nested, unoptimized data processing loops. We've all seen them: chained `.map()`, `.filter()`, `.sort()`, and `.forEach()` loops processing arrays of objects. Each step in the chain allocates new intermediate arrays, triggers garbage collection thrashing, and operates on row-based layouts that slow down browser main threads.
29
+ ## 💡 Why df-script? (Polars & Pandas for TypeScript)
15
30
 
16
- When you need to perform complex analytical transformations on the client-side—handling missing values, formatting timezone-aware datetimes, parsing decimals, or computing rolling averages—relying on standard JavaScript array methods quickly becomes a performance and maintenance nightmare. There had to be a better, cleaner, and faster way to express these pipelines. I realized that if nobody else had built a lightweight, zero-dependency columnar expression engine for the JavaScript ecosystem yet, why not roll up my sleeves and build it myself?
31
+ In modern web apps and Node.js backend services, data transformation code often degrades into nested chains of `.map()`, `.filter()`, and `.sort()` on arrays of objects. Each step in the chain allocates new intermediate arrays, slows down garbage collection, and creates maintenance overhead.
17
32
 
18
- DFScript was born from that frustration. It brings Polars-like columnar execution, strict domain namespaces (`.str`, `.dt`, `.arr`, `.struct`), and lazy/declarative expression compilation to JavaScript. Under the hood, it avoids intermediate array allocations and uses highly optimized loops with cached lengths, so your frontend code stays clean, type-safe, and incredibly fast.
33
+ `df-script` provides:
34
+ - ⚡ **Columnar Execution**: Column-oriented arrays with cached loop lengths for fast computation and minimal memory allocation.
35
+ - 🔗 **Fluent Expressions**: Declarative, composable queries using `$df.col(...)` expressions with automatic post-operation schema deduction.
36
+ - 📂 **Strict Domain Namespaces**: Clean, dedicated namespaces (`.str`, `.dt`, `.arr`, `.struct`) to prevent method clutter and ensure discoverable APIs.
37
+ - 🛡️ **Zero External Dependencies**: Lightweight runtime footprint with zero supply-chain risk.
38
+ - 🧠 **TypeScript First**: Full IDE autocomplete and compile-time type safety for column selections and schemas.
19
39
 
20
40
  ---
21
41
 
22
42
  ## 🗺️ Table of Contents
23
43
 
24
44
  - [✨ Key Features](#-key-features)
25
- - [⚙️ Compatibility & Design Principles](#-compatibility--design-principles)
26
- - [🤝 Contributing & Collective Wisdom](#-contributing--collective-wisdom)
45
+ - [🌐 Universal Language & Environment Support](#-universal-language--environment-support)
27
46
  - [📦 Installation](#-installation)
28
47
  - [🚀 Quick Start](#-quick-start)
29
48
  - [📖 Core Concepts](#-core-concepts)
30
- - [🛠️ DataFrame API Reference](#-dataframe-api-reference)
49
+ - [🛠️ DataFrame API Reference](#️-dataframe-api-reference)
31
50
  - [📂 File / Data I/O](#-file--data-io)
32
51
  - [🧮 Expressions API Reference](#-expressions-api-reference)
33
52
  - [📂 Namespaces](#-namespaces)
34
53
  - [🪟 Window & Rolling Expressions](#-window--rolling-expressions)
35
- - [🛡️ Typing and Schema Registry](#-typing-and-schema-registry)
54
+ - [🛡️ Typing and Schema Registry](#️-typing-and-schema-registry)
36
55
  - [🧑‍💻 Contributing & Development](#-contributing--development)
37
56
  - [📄 License](#-license)
38
57
 
@@ -40,88 +59,67 @@ DFScript was born from that frustration. It brings Polars-like columnar executio
40
59
 
41
60
  ## ✨ Key Features
42
61
 
43
- - 📦 **Zero Dependencies** — Extremely lightweight with zero runtime overhead.
44
- - ⚡ **Columnar Execution** — Operates on efficient columnar arrays, minimizing allocations and speed bottlenecks.
45
- - 🔗 **Expression-Based API** — Compose complex calculations, mappings, and filters using fluent, Polars-like expressions.
46
- - 📂 **Strict Namespaces** — Clear API organization for specific domains:
47
- - `.str` for advanced string manipulations.
48
- - `.dt` for microsecond-precision datetimes, timezones, and duration calculations.
49
- - `.arr` for robust array/list column operations.
50
- - `.struct` for nested object and struct manipulation.
51
- - 🪟 **Analytical Window Functions** — Windowing (`over()`), cumulative aggregations (`cum_sum()`, `cum_max()`), and rolling metrics (`rolling_mean()`, `rolling_std()`).
52
- - 🛠️ **Relational Operations** — Rich, high-speed joins, pivots, unpivots, vertical/horizontal concatenations, and group-by aggregations.
53
- - 🛡️ **Defensive & Type-Safe** — Native type-coercion, robust null-safety, and strict schema validation.
54
-
55
- ---
56
-
57
- ## ⚙️ Compatibility & Design Principles
58
-
59
- DFScript is designed with a **low-abstraction, zero-dependency** philosophy to guarantee maximum compatibility, predictability, and runtime performance:
60
-
61
- - 📦 **Zero External Dependencies** — Lightweight footprint with zero runtime overhead or supply chain vulnerabilities.
62
- - 🌐 **Universal Compatibility** — Works out-of-the-box in any JavaScript/TypeScript environment, including Node.js, Deno, Bun, web browsers, and cloud/edge workers.
63
- - 🧱 **Built-in Standards** — Prioritizes native, built-in APIs (like standard `Date`, `Intl` formatting, and `TextEncoder`) and standard arrays rather than custom wrappers or heavy runtime abstractions.
64
- - ⚡ **Optimized Execution Paths** — Under the hood, performance-critical code avoids higher-level array iterators and short-lived intermediate allocations in favor of simple, fast `for` and `while` loops with cached lengths, keeping garbage collection overhead to an absolute minimum.
65
- - 🔄 **Easy Transpilation** — Relies strictly on low-level native operations, making it fully compatible with older environments (like ES6 or even ES5) without requiring complex polyfills or modern engine-specific features.
66
-
67
- ---
68
-
69
- ## 🤝 Contributing & Collective Wisdom
70
-
71
- We don’t pretend to have encountered every localized date format, database quirk, or environment-specific edge case. DFScript is built on the belief that software correctness is a collective endeavor.
72
-
73
- If you run into an unsupported edge case or unexpected behavior in any of our functions, we want to hear about it. Help us harden this engine by opening a GitHub Issue or submitting a PR—every report makes the library more robust for everyone.
62
+ - 📦 **Zero Dependencies** — 0 external runtime dependencies; completely standalone.
63
+ - ⚡ **Columnar Execution** — Fast columnar processing that eliminates intermediate array allocations.
64
+ - 🔗 **Expression-Based API** — Compose complex transformations, aggregations, and conditions using fluent `$df` expressions.
65
+ - 📂 **Strict Namespaces**:
66
+ - `.str` Unicode string manipulations, regex extractions, and JSON path lookups.
67
+ - `.dt` Timezone conversions, business days, microsecond-precision datetimes, and durations.
68
+ - `.arr` Array/list column operations and element-wise `.arr.eval()` mapping.
69
+ - `.struct` Nested object handling and `.struct.unnest()` column flattening.
70
+ - 🪟 **Analytical Window Functions** — Partitioned windowing (`.over()`), cumulative aggregations (`cumSum()`, `cumMax()`), and rolling moving statistics (`rollingMean()`, `rollingStd()`).
71
+ - 🛠️ **Relational Operations** — Inner/left/right/outer/cross joins, `joinAsof` time-series matching, pivots, unpivots, and multi-axis concatenations.
72
+ - 🛡️ **Defensive & Type-Safe** — Automatic type coercion, Kleene three-valued logic for null safety, and strict schema validation.
74
73
 
75
74
  ---
76
75
 
77
76
  ## 📦 Installation
78
77
 
79
- Install DFScript using your favorite package manager:
78
+ Install `df-script` using your package manager:
80
79
 
81
80
  ```bash
82
81
  npm install df-script
83
82
  ```
84
83
 
85
- Or with Yarn/PNPM:
84
+ Or with Yarn, PNPM, or Bun:
86
85
 
87
86
  ```bash
88
87
  yarn add df-script
89
88
  pnpm add df-script
89
+ bun add df-script
90
90
  ```
91
91
 
92
92
  ---
93
93
 
94
94
  ## 🚀 Quick Start
95
95
 
96
- Here is a quick example showing how to load data, run expressions, perform aggregations, and compute rolling statistics.
97
-
98
96
  ```typescript
99
97
  import { $df } from "df-script";
100
98
 
101
99
  // 1. Create a DataFrame with structured data and automatic schema inference
102
100
  const df = $df.data([
103
- { id: 1, name: "Alice", join_date: "2026-01-15", sales: 1200.50, tags: ["sales", "east"] },
104
- { id: 2, name: "Bob", join_date: "2026-02-20", sales: 850.00, tags: ["support", "west"] },
105
- { id: 3, name: "Charlie", join_date: "2026-03-05", sales: 2300.00, tags: ["sales", "north"] },
106
- { id: 4, name: "David", join_date: "2026-03-12", sales: null, tags: ["marketing"] },
101
+ { id: 1, name: "Alice", joinDate: "2026-01-15", sales: 1200.50, tags: ["sales", "east"] },
102
+ { id: 2, name: "Bob", joinDate: "2026-02-20", sales: 850.00, tags: ["support", "west"] },
103
+ { id: 3, name: "Charlie", joinDate: "2026-03-05", sales: 2300.00, tags: ["sales", "north"] },
104
+ { id: 4, name: "David", joinDate: "2026-03-12", sales: null, tags: ["marketing"] },
107
105
  ]);
108
106
 
109
- // 2. Select columns, transform strings, format dates, and fill missing values
107
+ // 2. Select columns, transform strings, format dates, and compute expressions
110
108
  const processedDf = df.select(
111
109
  $df.col("id"),
112
110
  $df.col("name").str.upper().alias("NAME_UPPER"),
113
- $df.col("join_date").str.to_datetime().dt.year().alias("join_year"),
114
- $df.col("sales").add(500).alias("sales_adjusted"),
115
- $df.col("tags").arr.lengths().alias("tag_count")
111
+ $df.col("joinDate").str.toDatetime().dt.year().alias("joinYear"),
112
+ $df.col("sales").add(500).alias("salesAdjusted"),
113
+ $df.col("tags").arr.lengths().alias("tagCount")
116
114
  );
117
115
 
118
- console.log(processedDf.to_dicts());
116
+ console.log(processedDf.toDicts());
119
117
  /* Output:
120
118
  [
121
- { id: 1, NAME_UPPER: 'ALICE', join_year: 2026, sales_adjusted: 1700.5, tag_count: 2 },
122
- { id: 2, NAME_UPPER: 'BOB', join_year: 2026, sales_adjusted: 1350, tag_count: 2 },
123
- { id: 3, NAME_UPPER: 'CHARLIE', join_year: 2026, sales_adjusted: 2800, tag_count: 2 },
124
- { id: 4, NAME_UPPER: 'DAVID', join_year: 2026, sales_adjusted: null, tag_count: 1 }
119
+ { id: 1, NAME_UPPER: 'ALICE', joinYear: 2026, salesAdjusted: 1700.5, tagCount: 2 },
120
+ { id: 2, NAME_UPPER: 'BOB', joinYear: 2026, salesAdjusted: 1350, tagCount: 2 },
121
+ { id: 3, NAME_UPPER: 'CHARLIE', joinYear: 2026, salesAdjusted: 2800, tagCount: 2 },
122
+ { id: 4, NAME_UPPER: 'DAVID', joinYear: 2026, salesAdjusted: null, tagCount: 1 }
125
123
  ]
126
124
  */
127
125
  ```
@@ -132,93 +130,88 @@ console.log(processedDf.to_dicts());
132
130
 
133
131
  ### The `$df` Entry Point
134
132
 
135
- DFScript uses the `$df` namespace to bootstrap DataFrames, refer to columns, build expressions, and access data types.
133
+ `df-script` uses the `$df` namespace to instantiate DataFrames, reference columns, construct expressions, and specify data types.
136
134
 
137
135
  - `$df.data(dataRowsOrCols, schema?)`: Instantiates a new `DataFrame`.
138
- - `$df.read_json(content, options?)`: Reads JSON/NDJSON content into a new `DataFrame`.
139
- - `$df.read_csv(content, options?)`: Reads CSV content into a new `DataFrame`.
140
- - `$df.col(name)`: Creates a column reference expression.
136
+ - `$df.readJson(content, options?)`: Reads JSON/NDJSON content into a new `DataFrame`.
137
+ - `$df.readCsv(content, options?)`: Reads CSV content into a new `DataFrame` with automatic schema inference.
138
+ - `$df.col(selector)`: Creates a column reference expression by column name (`"a"`), multiple names (`["a", "b"]`), RegExp pattern (`/^user_/`), or DataType selector (`$df.Float64`, `$df.Numeric`).
141
139
  - `$df.all()`: Selects all columns in the DataFrame.
142
- - `$df.exclude(columns)`: Creates an expression matching all columns except the specified ones.
143
- - `$df.coalesce(...exprs)`: Returns the first non-null value among columns or literal expressions.
140
+ - `$df.exclude(columns)`: Matches all columns except the specified ones.
141
+ - `$df.coalesce(...exprs)`: Returns the first non-null value among columns or expressions.
144
142
  - `$df.lit(val)`: Explicitly wraps a raw value into a literal expression.
145
- - `$df.duration(options)`: Constructs a `Duration` expression supporting days, hours, minutes, seconds, milliseconds, weeks, and timeUnit precision.
146
- - `$df.struct(fields)`: Constructs a nested `Struct` object column expression from an object of named expressions or sibling columns.
147
- - `$df.when(predicate).then(value)...otherwise(value)`: Constructs a conditional expression (when-then-otherwise chain).
148
- - `$df.implode(column)`: Aggregates a column's rows (or grouped values) into a list.
149
- - `$df.seq_range(value, options?)`: Generates a sequence range of values.
143
+ - `$df.duration(optionsOrString)`: Constructs a `Duration` expression from component options (`{ days: 1, hours: 12 }`) or compound duration strings (`"1d 12h 30m"`).
144
+ - `$df.struct(fields)`: Constructs a nested struct object expression from named expressions or sibling columns.
145
+ - `$df.when(predicate).then(value)...otherwise(value)`: Constructs a conditional `CASE WHEN` expression chain.
146
+ - `$df.implode(column)`: Aggregates a column's rows or grouped values into a list.
147
+ - `$df.seqRange(value, options?)`: Generates a sequence range of values.
150
148
  - `$df.element()`: References the current array element within an `.arr.eval(...)` expression.
151
- - `$df.DataType`: Direct access to the `DataTypeRegistry` for schema specification.
152
-
153
- ### DataFrames vs. Columns
154
-
155
- - **`DataFrame`** holds data in a columnar-oriented object: `columns: Record<string, any[]>`.
156
- - **`ColumnExpr`** represents an evaluation sequence over rows. Operations (arithmetic, strings, lists, date-time, comparisons) are chained to build a tree of computations evaluated lazily.
149
+ - `$df.Float64`, `$df.Int32`, `$df.Utf8`, etc.: Direct access to data types and constructors for schema definitions and type-based column selection.
157
150
 
158
151
  ---
159
152
 
160
153
  ## 🛠️ DataFrame API Reference
161
154
 
162
155
  ### 1. Transformations & Projection
163
- - **`select(...exprs)`**: Projects columns. Supports strings, raw column names, `$df.col(...)` expressions, `$df.all()`, and `$df.col("struct").struct.unnest()`.
164
- - **`with_columns(...exprs)`**: Adds or overrides columns. Accepts expressions, strings, or options objects mapping keys to values/expressions.
156
+ - **`select(...exprs)`**: Projects columns. Supports strings, `$df.col(...)` expressions, `$df.all()`, RegExp patterns (`/^prefix_/`), DataType selectors (`$df.Numeric`), and `$df.col("struct").struct.unnest()`.
157
+ - **`withColumns(...exprs)`**: Adds or overrides columns. Accepts expressions, options mapping keys, RegExp patterns, or DataType selectors.
165
158
  - **`drop(...names)`**: Drops one or more columns from the DataFrame.
166
159
  - **`rename(mapping)`**: Renames columns using a `{ oldName: newName }` object.
167
160
  - **`explode(columns)`**: Unnests list-like columns into multiple rows, replicating other columns per list element.
168
- - **`implode(columns)`**: Groups values in specified columns back into a single list element per column.
161
+ - **`implode(columns)`**: Groups values in specified columns back into a list element per column.
169
162
 
170
163
  ### 2. Filtering & Row Selection
171
- - **`filter(...predicates)`**: Filters rows where all predicate expressions evaluate to `true` (or non-null truthy values).
172
- - **`find(predicate)`**: Evaluates a predicate expression and returns the first matching row record object (or `undefined` if no match is found).
173
- - **`unique(columns?)`**: Returns unique rows. If a subset of columns is provided, deduplicates based on those columns.
164
+ - **`filter(...predicates)`**: Filters rows where all predicate expressions evaluate to `true`.
165
+ - **`find(predicate)`**: Returns the first matching row record object (or `undefined`).
166
+ - **`unique(columns?)`**: Returns unique rows, optionally deduplicating based on a subset of columns.
174
167
  - **`limit(n, options?)`**: Returns the first `n` rows. Options include `offset` and direction `from: "start" | "end"`.
175
168
  - **`head(n)`** / **`tail(n)`**: Shortcuts for `limit` from the start or end of the DataFrame.
176
- - **`slice(start, end?)`**: Extract a subset of rows using standard index slicing.
177
- - **`gather(indices, options?)`**: Gathers rows at specified indices. Supports single index, arrays of indices, and negative indexing. Options include `{ null_on_oob?: boolean }`.
169
+ - **`slice(start, end?)`**: Extracts a subset of rows using standard index slicing.
170
+ - **`gather(indices, options?)`**: Gathers rows at specified indices (supports negative indexing and `{ nullOnOob?: boolean }`).
178
171
 
179
172
  ### 3. Sorting & Structural Operations
180
- - **`sort({ by, descending?, nullsLast?, custom? })`**: Sorts rows. Supports single or multiple columns/expressions, custom descending configurations per column, custom null sorting rules, and custom comparator functions.
181
- - **`clone()`**: Performs a complete deep copy of the `DataFrame`, replicating all underlying column arrays and schema metadata.
173
+ - **`sort({ by, descending?, nullsLast?, custom? })`**: Sorts rows by single/multiple columns, custom null ordering, or comparator functions.
174
+ - **`clone()`**: Performs a deep copy of the `DataFrame`, replicating all underlying column arrays and schema metadata.
175
+ - **`transpose(options?)`**: Transposes the DataFrame (swapping rows and columns).
182
176
 
183
177
  ### 4. Grouping & Aggregations
184
- - **`groupby(keys)`**: Groups the data by one or more columns, returning a `GroupedData` object.
185
- - **`GroupedData.agg(...exprs)`**: Run aggregations on grouped data (e.g. `$df.col("sales").sum()`).
178
+ - **`groupBy(keys)`**: Groups data by one or more columns, returning a `GroupedData` object.
179
+ - **`groupByDynamic(indexColumn, options)`**: Dynamic time-series / numeric window grouping over tumbling, sliding, or rolling temporal aggregation intervals (`every`, `period`, `offset`, `closed`, `label`, `startBy`, `includeBoundaries`, `by`).
180
+ - **`GroupedData.agg(...exprs)`**: Computes aggregations on grouped data (e.g. `$df.col("sales").sum()`).
186
181
 
187
182
  ### 5. Reshaping & Joining
188
183
  - **`join(other, onOrOptions, how?, suffixes?)`**: Merges two DataFrames. Supports:
189
184
  - Join modes (`how`): `"inner" | "left" | "right" | "outer" | "semi" | "anti" | "cross"`.
190
- - Heterogeneous key names (`leftOn`, `rightOn`).
191
- - Key coalescing (`coalesce: boolean`).
192
- - Row order preservation (`maintain_order: "none" | "left" | "right" | "left_right" | "right_left"`).
193
- - **`join_asof(other, options)`**: Performs inexact time-series or nearest-neighbor joins on sorted key columns.
194
- - Parameters: `on`, `leftOn`, `rightOn`, grouping parameters (`by`, `leftBy`, `rightBy`), matching `strategy` (`"backward" | "forward" | "nearest"`), numeric/duration `tolerance`, and `allow_exact_matches`.
185
+ - Keys: `leftOn`, `rightOn`, `coalesce`, and order preservation options.
186
+ - **`joinAsof(other, options)`**: Inexact time-series / nearest-neighbor joins on sorted key columns.
187
+ - Parameters: `on`, `leftOn`, `rightOn`, `by`, `strategy` (`"backward" | "forward" | "nearest"`), and `tolerance`.
195
188
  - **`pivot(index, columns, values)`**: Pivots the table, converting unique values in `columns` into column headers.
196
- - **`unpivot(idVars, valueVars, varName?, valueName?)`**: Melts/unpivots the table, converting wide columns into long format name-value pairs.
197
- - **`concat(items, options?)`**: Concatenates multiple DataFrames. Supported concat strategies: `"vertical" | "horizontal" | "diagonal"`.
189
+ - **`unpivot(idVars, valueVars, varName?, valueName?)`**: Melts/unpivots wide columns into long format name-value pairs.
190
+ - **`concat(items, options?)`**: Concatenates multiple DataFrames (`"vertical" | "horizontal" | "diagonal"`).
198
191
 
199
192
  ---
200
193
 
201
194
  ## 📂 File / Data I/O
202
195
 
203
- DFScript provides helpers to serialize and parse data formats like JSON and CSV.
196
+ `df-script` provides built-in parsers and serializers for JSON and CSV formats.
204
197
 
205
198
  ### Reading Data
206
- - **`$df.read_json(content, options?)`**: Reads a JSON array or Newline Delimited JSON (NDJSON) string and loads it into a new DataFrame.
199
+ - **`$df.readJson(content, options?)`**: Reads standard JSON or Newline Delimited JSON (NDJSON) string.
207
200
  ```typescript
208
201
  import { $df } from "df-script";
209
202
 
210
- // Read standard JSON array
211
- const df = $df.read_json('[{"id": 1, "name": "Alice"}]');
203
+ // Read standard JSON
204
+ const df = $df.readJson('[{"id": 1, "name": "Alice"}]');
212
205
 
213
- // Read Newline Delimited JSON (NDJSON)
214
- const dfNdjson = $df.read_json('{"id": 1}\n{"id": 2}', { format: "ndjson" });
206
+ // Read NDJSON
207
+ const dfNdjson = $df.readJson('{"id": 1}\n{"id": 2}', { format: "ndjson" });
215
208
  ```
216
- - **`$df.read_csv(content, options?)`**: Reads a CSV string and loads it into a new DataFrame, with automatic data type inference.
209
+ - **`$df.readCsv(content, options?)`**: Reads a CSV string with automatic type inference.
217
210
  ```typescript
218
211
  import { $df } from "df-script";
219
212
 
220
213
  const csvContent = "id,name,active\n1,Alice,true\n2,Bob,false";
221
- const df = $df.read_csv(csvContent, {
214
+ const df = $df.readCsv(csvContent, {
222
215
  separator: ",",
223
216
  hasHeader: true,
224
217
  inferSchema: true
@@ -226,49 +219,45 @@ DFScript provides helpers to serialize and parse data formats like JSON and CSV.
226
219
  ```
227
220
 
228
221
  ### Writing Data
229
- - **`df.write_json(file?, options?)`**: Serializes a DataFrame into a JSON or NDJSON string. If a file path or writable stream/object (with a `.write` method) is provided, writes/streams the content as a side-effect. Always returns the serialized string.
222
+ - **`df.writeJson(file?, options?)`**: Serializes a DataFrame into a JSON or NDJSON string.
230
223
  ```typescript
231
- // Write to a file and get the string
232
- const jsonStr = df.write_json("output.json");
224
+ const jsonStr = df.writeJson();
225
+ df.writeJson("output.json");
233
226
  ```
234
- - **`df.write_csv(file?, options?)`**: Serializes a DataFrame into a CSV string. Supports options for headers, custom separators, quote styles, float precision, and BOM. If a file path or writable stream/object (with a `.write` method) is provided, writes/streams the content as a side-effect. Always returns the serialized string.
227
+ - **`df.writeCsv(file?, options?)`**: Serializes a DataFrame into a CSV string.
235
228
  ```typescript
236
- // Serialize to a CSV string
237
- const csvStr = df.write_csv();
238
-
239
- // Write to a file with custom separator
240
- df.write_csv("output.csv", { separator: ";" });
229
+ const csvStr = df.writeCsv();
230
+ df.writeCsv("output.csv", { separator: ";" });
241
231
  ```
242
232
 
243
233
  ---
244
234
 
245
235
  ## 🧮 Expressions API Reference
246
236
 
247
- All column expressions inherit from `ExprBase` and support standard operators.
237
+ All column expressions inherit from `ExprBase` and support chaining.
248
238
 
249
239
  ### ➕ Arithmetic Expressions
250
- Chained mathematical functions execute cleanly with built-in null-safety (Kleene logic).
251
240
  - `.add(val)`, `.sub(val)`, `.mul(val)`, `.div(val)`, `.floordiv(val)`, `.mod(val)`, `.pow(val)`
252
241
  - `.abs()`, `.sqrt()`, `.cbrt()`, `.exp()`, `.expm1()`, `.log(base?)`, `.log1p()`
253
242
  - `.ceil()`, `.floor()`, `.trunc()`, `.round(decimals)`, `.clip(lower, upper)`, `.sign()`, `.negate()`
254
- - `.sin()`, `.cos()`, `.tan()`, `.sinh()`, `.cosh()`, `.tanh()`, `.asin()`, `.acos()`, `.atan()`, `.asinh()`, `.acosh()`, `.atanh()`, `.degrees()`, `.radians()`, `.hypot(val)`
243
+ - `.sin()`, `.cos()`, `.tan()`, `.cot()`, `.sinh()`, `.cosh()`, `.tanh()`, `.arcsin()`, `.arccos()`, `.arctan()`, `.arctan2(val)`, `.arcsinh()`, `.arccosh()`, `.arctanh()`, `.degrees()`, `.radians()`, `.hypot(val)`
255
244
 
256
245
  ### 🔍 Comparison Expressions
257
- - `.eq(val)`, `.ne(val)` — Strict value equivalence (null values return null).
258
- - `.eq_missing(val)`, `.ne_missing(val)` — Equality checking that treats null/undefined values as equal.
246
+ - `.eq(val)`, `.ne(val)` — Strict value equivalence (Kleene null-propagation).
247
+ - `.eqMissing(val)`, `.neMissing(val)` — Null-safe equality treating null/undefined as equal.
259
248
  - `.gt(val)`, `.ge(val)`, `.lt(val)`, `.le(val)`
260
- - `.is_null()`, `.is_not_null()`
261
- - `.is_finite()`, `.is_infinite()`, `.is_nan()`, `.is_not_nan()`
262
- - `.is_in(arrayOrExpr)`, `.not_in(arrayOrExpr)`
249
+ - `.isNull()`, `.isNotNull()`
250
+ - `.isFinite()`, `.isInfinite()`, `.isNan()`, `.isNotNan()`
251
+ - `.isNDistinct(index, nullOnOob?)` — Matches the N-th distinct value by positive/negative index position.
252
+ - `.isIn(arrayOrExpr)`, `.notIn(arrayOrExpr)`
263
253
 
264
254
  ### ⚡ Aggregations
265
255
  - `.sum()`, `.product()`, `.avg()` / `.mean()`, `.median()`, `.mode()`, `.variance()`, `.std()`, `.skew()`, `.kurtosis()`, `.entropy(base?, normalize?)`
266
- - `.min()`, `.max()`, `.nan_min()`, `.nan_max()`, `.min_by(by)`, `.max_by(by)`, `.arg_min()`, `.arg_max()`
267
- - `.count(options?)` — Option `{ includeNulls: boolean }`.
256
+ - `.min()`, `.max()`, `.nanMin()`, `.nanMax()`, `.minBy(by)`, `.maxBy(by)`, `.argMin()`, `.argMax()`
257
+ - `.count(options?)` — Options: `{ includeNulls: boolean }`.
268
258
  - `.first()`, `.last()`
269
- - `.any()`, `.all()`, `.any_null()`, `.all_null()`, `.n_unique()`, `.null_count()`
270
- - `.bitwise_and()`, `.bitwise_or()`, `.bitwise_xor()`
271
-
259
+ - `.any()`, `.all()`, `.anyNull()`, `.allNull()`, `.nUnique()`, `.nullCount()`
260
+ - `.bitwiseAnd()`, `.bitwiseOr()`, `.bitwiseXor()`
272
261
 
273
262
  ### 🔀 Control Flow & Conditionals
274
263
  Construct dynamic `CASE WHEN` branches using the `$df.when` API:
@@ -280,118 +269,84 @@ df.select(
280
269
  $df.when($df.col("sales").gt(2000)).then("High Performance")
281
270
  .when($df.col("sales").gt(1000)).then("Standard Performance")
282
271
  .otherwise("Low Performance")
283
- .alias("sales_category")
272
+ .alias("salesCategory")
284
273
  );
285
274
  ```
286
- - `$df.when(predicate).then(value)`: Starts a conditional evaluation.
287
- - `.when(predicate).then(value)`: Chains additional conditions.
288
- - `.otherwise(value)`: Specifies the fallback value when no conditions match (returns a complete `ColumnExpr`).
289
- - `$df.coalesce(...exprs)`: Returns the first non-null value among the provided expressions or literals.
290
275
 
291
276
  ---
292
277
 
293
278
  ## 📂 Namespaces
294
279
 
295
- To maintain a clean and uncluttered API namespace, specific data transforms are grouped under dedicated accessors.
280
+ Specific domain transforms are grouped under dedicated namespaces:
296
281
 
297
282
  ### 🔤 String Operations (`.str`)
298
283
  Available on any expression via `.str`:
299
284
  ```typescript
300
285
  $df.col("name").str.lower()
301
- $df.col("code").str.starts_with("A")
286
+ $df.col("code").str.startsWith("A")
302
287
  $df.col("description").str.replace(/foo/i, "bar")
303
288
  ```
304
- - **Methods**: `lower()`, `upper()`, `to_titlecase()`, `len()`, `len_bytes()`, `len_chars()`, `trim()`, `trim_start()`, `trim_end()`, `starts_with(prefix)`, `ends_with(suffix)`, `contains(pattern)`, `contains_any(patterns)`, `count_matches(pattern)`, `find(pattern)`, `find_many(patterns)`, `replace(pattern, repl)`, `replace_all(pattern, repl)`, `replace_many(patterns, replacements)`, `slice(offset, length?)`, `split(delimiter, options?)`, `explode()`, `reverse()`, `lpad(w, f)`, `rpad(w, f)`, `zfill(w)`, `strip_chars(chars?)`, `strip_chars_start(chars?)`, `strip_chars_end(chars?)`, `strip_prefix(pfx)`, `strip_suffix(sfx)`, `escape_regex()`, `extract(pattern, groupIndex?)`, `extract_all(pattern)`, `extract_groups(pattern)`, `extract_many(patterns)`, `encode(encoding)`, `decode(encoding, strict?)`, `json_decode(options?)`, `json_path_match(jsonPath)`, `normalize(form?)`, `join(separator)`, `strptime(format, strict?)`, `to_integer()`, `to_decimal(p, s)`, `to_date()`, `to_datetime()`, `to_time()`.
289
+ - **Methods**: `lower()`, `upper()`, `toTitlecase()`, `len()`, `lenBytes()`, `lenChars()`, `trim()`, `trimStart()`, `trimEnd()`, `startsWith(pfx)`, `endsWith(sfx)`, `contains(pat)`, `containsAny(pats)`, `countMatches(pat)`, `find(pat)`, `findMany(pats)`, `replace(pat, repl)`, `replaceAll(pat, repl)`, `replaceMany(pats, repls)`, `slice(offset, len?)`, `split(delim, options?)`, `explode()`, `reverse()`, `lpad(w, f)`, `rpad(w, f)`, `zfill(w)`, `stripChars(chars?)`, `stripCharsStart(chars?)`, `stripCharsEnd(chars?)`, `stripPrefix(pfx)`, `stripSuffix(sfx)`, `escapeRegex()`, `extract(pat, group?)`, `extractAll(pat)`, `extractGroups(pat)`, `extractMany(pats)`, `encode(enc)`, `decode(enc, strict?)`, `jsonDecode(options?)`, `jsonPathMatch(path)`, `normalize(form?)`, `join(sep)`, `strptime(fmt, strict?)`, `toInteger()`, `toDecimal(p, s)`, `toDate()`, `toDatetime()`, `toTime()`.
305
290
 
306
291
  ### 📅 Temporal Operations (`.dt`)
307
292
  Available on datetime or duration values via `.dt`:
308
293
  ```typescript
309
294
  $df.col("timestamp").dt.year()
310
- $df.col("timestamp").dt.convert_time_zone("America/New_York")
311
- $df.col("duration").dt.total_seconds()
295
+ $df.col("timestamp").dt.convertTimeZone("America/New_York")
296
+ $df.col("duration").dt.totalSeconds()
312
297
  ```
313
- - **Datetime Methods**: `year()`, `month()`, `day()`, `hour()`, `minute()`, `second()`, `millisecond()`, `microsecond()`, `nanosecond()`, `weekday()`, `week()`, `quarter()`, `century()`, `millennium()`, `ordinal_day()`, `is_leap_year()`, `month_start()`, `month_end()`, `date()`, `time()`, `offset_day(n, options?)`, `offset_business_day(n, options?)`, `convert_time_zone(tz)`, `cast_time_unit(unit)`, `with_time_unit(unit)`, `replace(options)`, `truncate(every)`, `utc_offset(timeZone?, options?)`, `epoch(unit)`, `timestamp(unit)`, `strftime(format, locale?)`.
314
- - **Duration Methods**: `total_days()`, `total_hours()`, `total_minutes()`, `total_seconds()`, `total_milliseconds()`, `total_microseconds()`, `total_nanoseconds()`.
298
+ - **Datetime Methods**: `year()`, `month()`, `day()`, `hour()`, `minute()`, `second()`, `millisecond()`, `microsecond()`, `nanosecond()`, `weekday()`, `week()`, `quarter()`, `century()`, `millennium()`, `ordinalDay()`, `isLeapYear()`, `monthStart()`, `monthEnd()`, `date()`, `time()`, `offsetDay(n, options?)`, `offsetBusinessDay(n, options?)`, `convertTimeZone(tz)`, `castTimeUnit(unit)`, `withTimeUnit(unit)`, `replace(options)`, `truncate(every)`, `utcOffset(tz?, options?)`, `epoch(unit)`, `timestamp(unit)`, `strftime(fmt, locale?)`.
299
+ - **Duration Methods**: `totalDays()`, `totalHours()`, `totalMinutes()`, `totalSeconds()`, `totalMilliseconds()`, `totalMicroseconds()`, `totalNanoseconds()`.
315
300
 
316
301
  ### 📊 Array/List Operations (`.arr`)
317
- Available on any array or list column expression via `.arr`:
302
+ Available on array/list column expressions via `.arr`:
318
303
  ```typescript
319
304
  $df.col("tags").arr.contains("vip")
320
- $df.col("matrix").arr.get(2)
321
-
322
- // Element-wise manipulation inside arrays:
323
- $df.col("numbers").arr.eval(element().mul(2)).alias("numbers_doubled")
324
- $df.col("tags").arr.eval(element().str.to_uppercase()).alias("upper_tags")
305
+ $df.col("numbers").arr.eval($df.element().mul(2)).alias("numbersDoubled")
325
306
  ```
326
- - **Methods**: `lengths()`, `len()`, `get(idx, null_on_oob?)`, `first(null_on_oob?)`, `last(null_on_oob?)`, `gather(indices, null_on_oob?)`, `gather_every(n, offset?)`, `slice(offset, length?)`, `contains(item)`, `count_matches(item)`, `join(separator)`, `sort(descending?)`, `reverse()`, `unique()`, `sum()`, `mean()`, `median()`, `mode()`, `min()`, `max()`, `arg_min()`, `arg_max()`, `agg(expr)`, `eval(expr)`.
307
+ - **Methods**: `lengths()`, `len()`, `get(idx, nullOnOob?)`, `first(nullOnOob?)`, `last(nullOnOob?)`, `gather(indices, nullOnOob?)`, `gatherEvery(n, offset?)`, `slice(offset, len?)`, `contains(item)`, `countMatches(item)`, `join(sep)`, `sort(descending?)`, `reverse()`, `unique()`, `sum()`, `mean()`, `median()`, `mode()`, `min()`, `max()`, `argMin()`, `argMax()`, `agg(expr)`, `eval(expr)`.
327
308
 
328
309
  ### 🗃️ Struct/Object Operations (`.struct`)
329
- Available on any struct or nested object column expression via `.struct`. You can access fields dynamically via properties or explicit methods:
310
+ Available on nested struct/object column expressions via `.struct`:
330
311
  ```typescript
331
312
  // Sibling fields access via Proxy
332
313
  $df.col("address").struct.city.alias("city")
333
314
 
334
- // Explicit struct field access or struct creation
335
- $df.struct({ city: $df.col("city"), state: $df.col("state") })
315
+ // Struct unnesting (flattens fields to top-level columns in select)
316
+ df.select($df.col("address").struct.unnest())
336
317
  ```
337
- - **Methods**:
338
- - `field(name)`: Accesses a field within the struct.
339
- - `rename_fields(mapping)`: Renames fields in the struct based on a `{ oldKey: newKey }` mapping.
340
- - `with_fields(fields)`: Adds or overrides fields in the struct. Accepts an array of aliased expressions or an object.
341
- - `unnest()`: Expands the fields of the struct into individual top-level columns in a select projection.
342
- ```typescript
343
- // Flattens the address struct into "city", "state", etc. at the top-level
344
- df.select($df.col("address").struct.unnest())
345
- ```
318
+ - **Methods**: `field(name)`, `renameFields(mapping)`, `withFields(fields)`, `unnest()`.
346
319
 
347
320
  ---
348
321
 
349
322
  ## 🪟 Window & Rolling Expressions
350
323
 
351
- DFScript provides full support for analytic partition window operations using `.over()` and rolling filters.
324
+ Analytical partition window operations using `.over()` and moving calculations:
352
325
 
353
326
  ```typescript
354
- // Calculate partition cumulative sums and row numbers
355
327
  df.select(
356
328
  $df.col("department"),
357
329
  $df.col("sales"),
358
- $df.col("sales").sum().over("department").alias("dept_total_sales"),
359
- $df.col("sales").cum_sum().over("department").alias("dept_running_sales"),
360
- $df.all().row_number().over("department").alias("dept_rank")
330
+ $df.col("sales").sum().over("department").alias("deptTotalSales"),
331
+ $df.col("sales").cumSum().over("department").alias("deptRunningSales"),
332
+ $df.all().rowNumber().over("department").alias("deptRank")
361
333
  );
362
334
  ```
363
335
 
364
336
  ### 1. Cumulative Windows
365
- - `.cum_sum(reverse?)`
366
- - `.cum_prod(reverse?)`
367
- - `.cum_min(reverse?)`
368
- - `.cum_max(reverse?)`
369
- - `.cum_count(reverse?)`
337
+ - `.cumSum(reverse?)`, `.cumProd(reverse?)`, `.cumMin(reverse?)`, `.cumMax(reverse?)`, `.cumCount(reverse?)`
370
338
 
371
339
  ### 2. Rolling Metrics (Moving Window)
372
- Apply moving calculations over a fixed window size:
373
- - `.rolling_sum(size)`
374
- - `.rolling_mean(size)`
375
- - `.rolling_median(size)`
376
- - `.rolling_min(size)`
377
- - `.rolling_max(size)`
378
- - `.rolling_std(size)`
379
- - `.rolling_rank(size)`
380
- - `.rolling_quantile(quantile, size)`
340
+ - **Generic Rolling Reducer**: `.rolling(sizeOrOptions, exprOrFn)` (evaluates custom functions or `$df` column expressions over each sliding window).
341
+ - **Specialized Rolling Reducers**: `.rollingSum(size)`, `.rollingMean(size)`, `.rollingMedian(size)`, `.rollingMin(size)`, `.rollingMax(size)`, `.rollingStd(size)`, `.rollingRank(size)`, `.rollingQuantile(quantile, size)`
381
342
 
382
343
  ### 3. Positional & Rank Windows
383
- - `.lead(offset, defaultVal?)`
384
- - `.lag(offset, defaultVal?)`
385
- - `.rank()`
386
- - `.dense_rank()`
387
- - `.row_number()`
344
+ - `.lead(offset, defaultVal?)`, `.lag(offset, defaultVal?)`, `.rank()`, `.denseRank()`, `.rowNumber()`
388
345
 
389
346
  ---
390
347
 
391
348
  ## 🛡️ Typing and Schema Registry
392
349
 
393
- You can optionally declare schemas to enforce precise data types and automatic type coercion during construction.
394
-
395
350
  ```typescript
396
351
  import { $df } from "df-script";
397
352
 
@@ -399,53 +354,12 @@ const schema = {
399
354
  id: $df.DataType.Int32,
400
355
  price: $df.DataType.Decimal(10, 2),
401
356
  active: $df.DataType.Boolean,
402
- created_at: $df.DataType.Datetime
357
+ createdAt: $df.DataType.Datetime
403
358
  };
404
359
 
405
360
  const df = $df.data(rawData, schema);
406
361
  ```
407
362
 
408
- ### 🧠 TypeScript Type Inference & IDE Safety
409
-
410
- When you pass a schema to `$df.data()`, DFScript's types automatically infer the target types of the fields, turning dynamic dataframes into compile-safe records. Your IDE will auto-complete column names and validate that operations match the underlying types.
411
-
412
- ```typescript
413
- import { $df } from "df-script";
414
-
415
- const schema = {
416
- name: $df.DataType.Utf8,
417
- age: $df.DataType.Int32,
418
- is_active: $df.DataType.Boolean
419
- };
420
-
421
- // Inferred DataFrame type is DataFrame<{ name: string; age: number; is_active: boolean }>
422
- const df = $df.data(rawData, schema);
423
-
424
- // Full IDE autocomplete, type validation, and compiler safety!
425
- const activeUsers = df.filter($df.col("is_active").eq(true));
426
- ```
427
-
428
- ### ⚡ Post-Operation Schema Type Deduction
429
-
430
- DFScript features an intelligent post-operation schema inference engine that automatically determines the correct resulting `DataType` across complex expression trees without requiring manual `.cast()` calls:
431
-
432
- - **Temporal & Duration Arithmetic**:
433
- - `Datetime - Datetime => Duration`
434
- - `Datetime ± Duration => Datetime`
435
- - `Time - Time => Duration`
436
- - `Time ± Duration => Time`
437
- - `Duration * / Numeric => Duration`
438
- - **Integer Promotion & Signedness Hierarchy**: Automatically preserves or promotes integer widths:
439
- - Preserves exact unsigned/signed types (`UInt8 + UInt8 => UInt8`, `Int16 + Int16 => Int16`).
440
- - Correctly promotes across sizes and signedness (`UInt16 + Int8 => Int16`, `UInt32 + Int32 => Int32`, `Int32 + Int64 => Int64`).
441
- - **Floating-Point & Decimal Resolution**:
442
- - `Int + Float => Float64`
443
- - `Float32 + Float32 => Float32`
444
- - `Decimal + Int => Decimal`
445
- - Evaluates non-integer operation results (e.g. division `10 / 3`) and promotes to `Float64`.
446
- - **Conditional Branch Widening**: Multi-branch expressions (`when().then().otherwise()`) progressively widen branch types to their common denominator.
447
- - **Statistical Aggregations**: `.mean()` and `.std()` promote integer columns to `Float64`, while non-numeric `.count()` operations resolve to `Int32`.
448
-
449
363
  ### Supported Data Types
450
364
  - **Integers**: `Int8`, `Int16`, `Int32`, `Int64`, `UInt8`, `UInt16`, `UInt32`, `UInt64`
451
365
  - **Floats & Decimals**: `Float32`, `Float64`, `Decimal(precision?, scale?)`
@@ -457,17 +371,16 @@ DFScript features an intelligent post-operation schema inference engine that aut
457
371
 
458
372
  ## 🧑‍💻 Contributing & Development
459
373
 
460
- We welcome contributions! Please make sure to review our [Developer Guidelines](DEVELOPER_GUIDELINES.md) when writing code.
461
-
462
- ### Running Project Tests
463
- DFScript has a comprehensive suite of unit tests. Run them using:
464
-
465
374
  ```bash
466
- npx tsx _tests/run_all_project_tests.ts
375
+ # Run test suite
376
+ npm test
377
+
378
+ # Build production bundles
379
+ npm run build
467
380
  ```
468
381
 
469
382
  ---
470
383
 
471
384
  ## 📄 License
472
385
 
473
- DFScript is open-source software licensed under the [MIT License](LICENSE).
386
+ `df-script` is open-source software licensed under the [MIT License](LICENSE).