df-script 1.8.0 → 1.9.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.
package/README.md CHANGED
@@ -142,6 +142,8 @@ DFScript uses the `$df` namespace to bootstrap DataFrames, refer to columns, bui
142
142
  - `$df.exclude(columns)`: Creates an expression matching all columns except the specified ones.
143
143
  - `$df.coalesce(...exprs)`: Returns the first non-null value among columns or literal expressions.
144
144
  - `$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.
145
147
  - `$df.when(predicate).then(value)...otherwise(value)`: Constructs a conditional expression (when-then-otherwise chain).
146
148
  - `$df.implode(column)`: Aggregates a column's rows (or grouped values) into a list.
147
149
  - `$df.seq_range(value, options?)`: Generates a sequence range of values.
@@ -158,28 +160,38 @@ DFScript uses the `$df` namespace to bootstrap DataFrames, refer to columns, bui
158
160
  ## 🛠️ DataFrame API Reference
159
161
 
160
162
  ### 1. Transformations & Projection
161
- - **`select(...exprs)`**: Projects columns. Supports strings, raw column names, `$df.col(...)` expressions, and `$df.all()`.
163
+ - **`select(...exprs)`**: Projects columns. Supports strings, raw column names, `$df.col(...)` expressions, `$df.all()`, and `$df.col("struct").struct.unnest()`.
162
164
  - **`with_columns(...exprs)`**: Adds or overrides columns. Accepts expressions, strings, or options objects mapping keys to values/expressions.
163
165
  - **`drop(...names)`**: Drops one or more columns from the DataFrame.
164
166
  - **`rename(mapping)`**: Renames columns using a `{ oldName: newName }` object.
167
+ - **`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.
165
169
 
166
170
  ### 2. Filtering & Row Selection
167
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).
168
173
  - **`unique(columns?)`**: Returns unique rows. If a subset of columns is provided, deduplicates based on those columns.
169
174
  - **`limit(n, options?)`**: Returns the first `n` rows. Options include `offset` and direction `from: "start" | "end"`.
170
175
  - **`head(n)`** / **`tail(n)`**: Shortcuts for `limit` from the start or end of the DataFrame.
171
176
  - **`slice(start, end?)`**: Extract a subset of rows using standard index slicing.
172
- - **`gather(indices, options?)`**: Gathers rows at specified indices. Supports single index, arrays of indices, and negative indexing. Options include `{ null_on_oob?: boolean }` (default: `false` which throws an error on out-of-bounds indices; if `true`, out-of-bounds indices result in `null` values).
177
+ - **`gather(indices, options?)`**: Gathers rows at specified indices. Supports single index, arrays of indices, and negative indexing. Options include `{ null_on_oob?: boolean }`.
173
178
 
174
- ### 3. Sorting
179
+ ### 3. Sorting & Structural Operations
175
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.
176
182
 
177
183
  ### 4. Grouping & Aggregations
178
184
  - **`groupby(keys)`**: Groups the data by one or more columns, returning a `GroupedData` object.
179
185
  - **`GroupedData.agg(...exprs)`**: Run aggregations on grouped data (e.g. `$df.col("sales").sum()`).
180
186
 
181
187
  ### 5. Reshaping & Joining
182
- - **`join(other, on, how, suffixes?)`**: Merges two DataFrames on join keys. Supported join types: `"inner" | "left" | "right" | "outer"`.
188
+ - **`join(other, onOrOptions, how?, suffixes?)`**: Merges two DataFrames. Supports:
189
+ - 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`.
183
195
  - **`pivot(index, columns, values)`**: Pivots the table, converting unique values in `columns` into column headers.
184
196
  - **`unpivot(idVars, valueVars, varName?, valueName?)`**: Melts/unpivots the table, converting wide columns into long format name-value pairs.
185
197
  - **`concat(items, options?)`**: Concatenates multiple DataFrames. Supported concat strategies: `"vertical" | "horizontal" | "diagonal"`.
@@ -250,10 +262,13 @@ Chained mathematical functions execute cleanly with built-in null-safety (Kleene
250
262
  - `.is_in(arrayOrExpr)`, `.not_in(arrayOrExpr)`
251
263
 
252
264
  ### ⚡ Aggregations
253
- - `.sum()`, `.avg()` / `.mean()`, `.median()`, `.mode()`, `.std()`, `.min()`, `.max()`
265
+ - `.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()`
254
267
  - `.count(options?)` — Option `{ includeNulls: boolean }`.
255
268
  - `.first()`, `.last()`
256
- - `.any()`, `.all()`, `.any_null()`, `.all_null()`, `.n_unique()`
269
+ - `.any()`, `.all()`, `.any_null()`, `.all_null()`, `.n_unique()`, `.null_count()`
270
+ - `.bitwise_and()`, `.bitwise_or()`, `.bitwise_xor()`
271
+
257
272
 
258
273
  ### 🔀 Control Flow & Conditionals
259
274
  Construct dynamic `CASE WHEN` branches using the `$df.when` API:
@@ -271,6 +286,7 @@ df.select(
271
286
  - `$df.when(predicate).then(value)`: Starts a conditional evaluation.
272
287
  - `.when(predicate).then(value)`: Chains additional conditions.
273
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.
274
290
 
275
291
  ---
276
292
 
@@ -285,16 +301,16 @@ $df.col("name").str.lower()
285
301
  $df.col("code").str.starts_with("A")
286
302
  $df.col("description").str.replace(/foo/i, "bar")
287
303
  ```
288
- - **Methods**: `lower()`, `upper()`, `len()`, `len_bytes()`, `len_chars()`, `trim()`, `trim_start()`, `trim_end()`, `starts_with(prefix)`, `ends_with(suffix)`, `contains(pattern)`, `replace(pattern, repl)`, `replace_all(pattern, repl)`, `slice(offset, length?)`, `split(delimiter)`, `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)`, `to_titlecase()`, `strptime(format, strict?)`, `to_integer()`, `to_decimal(p, s)`, `to_date()`, `to_datetime()`, `to_time()`.
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
305
 
290
306
  ### 📅 Temporal Operations (`.dt`)
291
307
  Available on datetime or duration values via `.dt`:
292
308
  ```typescript
293
309
  $df.col("timestamp").dt.year()
294
- $df.col("timestamp").dt.strftime("%Y-%m-%d %H:%M:%S")
310
+ $df.col("timestamp").dt.convert_time_zone("America/New_York")
295
311
  $df.col("duration").dt.total_seconds()
296
312
  ```
297
- - **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?)`, `utc_offset(timeZone?, options?)`, `epoch(unit)`, `timestamp(unit)`, `strftime(format, locale?)`.
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?)`.
298
314
  - **Duration Methods**: `total_days()`, `total_hours()`, `total_minutes()`, `total_seconds()`, `total_milliseconds()`, `total_microseconds()`, `total_nanoseconds()`.
299
315
 
300
316
  ### 📊 Array/List Operations (`.arr`)
@@ -307,7 +323,7 @@ $df.col("matrix").arr.get(2)
307
323
  $df.col("numbers").arr.eval(element().mul(2)).alias("numbers_doubled")
308
324
  $df.col("tags").arr.eval(element().str.to_uppercase()).alias("upper_tags")
309
325
  ```
310
- - **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()`, `eval(expr)`.
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)`.
311
327
 
312
328
  ### 🗃️ Struct/Object Operations (`.struct`)
313
329
  Available on any struct or nested object column expression via `.struct`. You can access fields dynamically via properties or explicit methods:
@@ -315,8 +331,8 @@ Available on any struct or nested object column expression via `.struct`. You ca
315
331
  // Sibling fields access via Proxy
316
332
  $df.col("address").struct.city.alias("city")
317
333
 
318
- // Or using the explicit field method
319
- $df.col("address").struct.field("city")
334
+ // Explicit struct field access or struct creation
335
+ $df.struct({ city: $df.col("city"), state: $df.col("state") })
320
336
  ```
321
337
  - **Methods**:
322
338
  - `field(name)`: Accesses a field within the struct.
@@ -409,6 +425,27 @@ const df = $df.data(rawData, schema);
409
425
  const activeUsers = df.filter($df.col("is_active").eq(true));
410
426
  ```
411
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
+
412
449
  ### Supported Data Types
413
450
  - **Integers**: `Int8`, `Int16`, `Int32`, `Int64`, `UInt8`, `UInt16`, `UInt32`, `UInt64`
414
451
  - **Floats & Decimals**: `Float32`, `Float64`, `Decimal(precision?, scale?)`
@@ -12,10 +12,17 @@ export declare class ExprBase implements IExpr {
12
12
  _literalValue?: any;
13
13
  _aggFn?: AggFn<any> | null;
14
14
  _castType?: RegisteredDataType;
15
+ _binaryMeta?: {
16
+ left: any;
17
+ right: any;
18
+ };
15
19
  _groupingOpsIndex?: number;
16
20
  _partitionOpsIndex?: number;
17
21
  _partitionBy: (string | IExpr)[] | null;
18
22
  _evaluateWindow?: (groupPreValues: any[], partitionIndices: number[], currentIndex: number) => any;
23
+ _baseExpr?: IExpr;
24
+ _fieldName?: string;
25
+ _isUnnest?: boolean;
19
26
  _evaluatePost(opsIndex: number | undefined, aggregatedArray: any[], columns: ColumnDict): ColumnData;
20
27
  _evaluatePre(opsIndex: number | undefined, columns: ColumnDict, height: number): ColumnData;
21
28
  _getInitialValue(columns: ColumnDict, height: number): ColumnData;
@@ -4,3 +4,4 @@ export declare const COALESCE_MARKER = "*coalesce*";
4
4
  export declare const ELEMENT_MARKER = "*element*";
5
5
  export declare const STRUCT_MARKER = "*struct*";
6
6
  export declare const DURATION_MARKER = "*duration*";
7
+ export declare const WHEN_MARKER = "*when*";
@@ -1,6 +1,6 @@
1
1
  import { ColumnExpr } from "../ColumnExpr";
2
2
  import type { IExpr, ValidScalarTypes } from "../../types";
3
- type WhenArg = IExpr | ValidScalarTypes;
3
+ type WhenArg = IExpr | ValidScalarTypes | any[];
4
4
  export declare class WhenThenChain {
5
5
  private _predicates;
6
6
  private _values;
@@ -13,12 +13,14 @@ export declare class When {
13
13
  then(value: WhenArg): WhenThen;
14
14
  }
15
15
  export declare class WhenThen extends ColumnExpr<any> {
16
- private _predicates;
17
- private _values;
18
- private _otherwiseValue;
19
- constructor(predicates: WhenArg[] | string, values?: WhenArg[], otherwiseValue?: WhenArg);
16
+ _predicates: WhenArg[];
17
+ _values: WhenArg[];
18
+ _otherwise: WhenArg;
19
+ get _otherwiseValue(): WhenArg;
20
+ get _branchOperands(): WhenArg[];
21
+ constructor(predicates?: WhenArg[], values?: WhenArg[], otherwise?: WhenArg);
20
22
  when(predicate: WhenArg): WhenThenChain;
21
- otherwise(value: WhenArg): ColumnExpr<any>;
23
+ otherwise(value: WhenArg): WhenThen;
22
24
  }
23
25
  /**
24
26
  * Provides conditional branch evaluations inside column expressions.
@@ -21,4 +21,5 @@ export * from "./functions/seq_range";
21
21
  export * from "./functions/element";
22
22
  export * from "./functions/struct";
23
23
  export * from "./functions/duration";
24
+ export * from "./typeInference";
24
25
  export * from "./utils";
@@ -1,4 +1,4 @@
1
- import type { AggFn, UniqueArrayStatsOptions } from "../../types";
1
+ import type { AggFn, UniqueArrayStatsOptions, SkewOptions, KurtosisOptions, EntropyOptions } from "../../types";
2
2
  import { ExprBase } from "../ExprBase";
3
3
  /**
4
4
  * @namespace $df.col
@@ -66,6 +66,34 @@ export declare class AggregationExpr extends ExprBase {
66
66
  * └───────┴──────────┘
67
67
  */
68
68
  any_null(): this;
69
+ /**
70
+ * Aggregation: Finds the index of the maximum value in the group.
71
+ * @returns ColumnExpression
72
+ * @example
73
+ * >>> const df = $df.data({ val: [10, 50, 20] })
74
+ * >>> df.select($df.col("val").arg_max().alias("max_idx"))
75
+ * shape: (1, 1)
76
+ * ┌─────────┐
77
+ * │ max_idx │
78
+ * ├─────────┤
79
+ * │ 1 │
80
+ * └─────────┘
81
+ */
82
+ arg_max(): this;
83
+ /**
84
+ * Aggregation: Finds the index of the minimum value in the group.
85
+ * @returns ColumnExpression
86
+ * @example
87
+ * >>> const df = $df.data({ val: [10, 50, 20] })
88
+ * >>> df.select($df.col("val").arg_min().alias("min_idx"))
89
+ * shape: (1, 1)
90
+ * ┌─────────┐
91
+ * │ min_idx │
92
+ * ├─────────┤
93
+ * │ 0 │
94
+ * └─────────┘
95
+ */
96
+ arg_min(): this;
69
97
  /**
70
98
  * Aggregation: Computes the arithmetic mean of the group.
71
99
  * @returns ColumnExpression
@@ -80,6 +108,48 @@ export declare class AggregationExpr extends ExprBase {
80
108
  * └───────┴──────┘
81
109
  */
82
110
  avg(): this;
111
+ /**
112
+ * Aggregation: Computes bitwise AND across all elements in the group.
113
+ * @returns ColumnExpression
114
+ * @example
115
+ * >>> const df = $df.data({ val: [0b11, 0b10] })
116
+ * >>> df.select($df.col("val").bitwise_and().alias("res"))
117
+ * shape: (1, 1)
118
+ * ┌─────┐
119
+ * │ res │
120
+ * ├─────┤
121
+ * │ 2 │
122
+ * └─────┘
123
+ */
124
+ bitwise_and(): this;
125
+ /**
126
+ * Aggregation: Computes bitwise OR across all elements in the group.
127
+ * @returns ColumnExpression
128
+ * @example
129
+ * >>> const df = $df.data({ val: [0b01, 0b10] })
130
+ * >>> df.select($df.col("val").bitwise_or().alias("res"))
131
+ * shape: (1, 1)
132
+ * ┌─────┐
133
+ * │ res │
134
+ * ├─────┤
135
+ * │ 3 │
136
+ * └─────┘
137
+ */
138
+ bitwise_or(): this;
139
+ /**
140
+ * Aggregation: Computes bitwise XOR across all elements in the group.
141
+ * @returns ColumnExpression
142
+ * @example
143
+ * >>> const df = $df.data({ val: [0b11, 0b10] })
144
+ * >>> df.select($df.col("val").bitwise_xor().alias("res"))
145
+ * shape: (1, 1)
146
+ * ┌─────┐
147
+ * │ res │
148
+ * ├─────┤
149
+ * │ 1 │
150
+ * └─────┘
151
+ */
152
+ bitwise_xor(): this;
83
153
  /**
84
154
  * Aggregation: Computes the Pearson correlation coefficient between two columns.
85
155
  * @param other The target column expression to correlate with.
@@ -142,6 +212,21 @@ export declare class AggregationExpr extends ExprBase {
142
212
  * └─────────────┘
143
213
  */
144
214
  dot(other: any): this;
215
+ /**
216
+ * Aggregation: Computes the Shannon entropy of a column or group.
217
+ * @param options Entropy options ({ base?: number, normalize?: boolean }, default base=Math.E, normalize=true).
218
+ * @returns ColumnExpression
219
+ * @example
220
+ * >>> const df = $df.data({ val: ["a", "b", "a", "c"] })
221
+ * >>> df.select($df.col("val").entropy().alias("h"))
222
+ * shape: (1, 1)
223
+ * ┌──────────┐
224
+ * │ h │
225
+ * ├──────────┤
226
+ * │ 1.039721 │
227
+ * └──────────┘
228
+ */
229
+ entropy(options?: EntropyOptions): this;
145
230
  /**
146
231
  * Aggregation: Finds the first value in the group.
147
232
  * @returns ColumnExpression
@@ -170,6 +255,21 @@ export declare class AggregationExpr extends ExprBase {
170
255
  * └───────┴──────────┘
171
256
  */
172
257
  implode(): this;
258
+ /**
259
+ * Aggregation: Computes the kurtosis (peakedness/tailedness) of a numeric column.
260
+ * @param options Kurtosis calculation options ({ fisher?: boolean, bias?: boolean }, default fisher=true, bias=true).
261
+ * @returns ColumnExpression
262
+ * @example
263
+ * >>> const df = $df.data({ val: [1, 2, 3, 4, 5] })
264
+ * >>> df.select($df.col("val").kurtosis().alias("kurt"))
265
+ * shape: (1, 1)
266
+ * ┌───────┐
267
+ * │ kurt │
268
+ * ├───────┤
269
+ * │ -1.3 │
270
+ * └───────┘
271
+ */
272
+ kurtosis(options?: KurtosisOptions): this;
173
273
  /**
174
274
  * Aggregation: Finds the last value in the group.
175
275
  * @returns ColumnExpression
@@ -198,6 +298,21 @@ export declare class AggregationExpr extends ExprBase {
198
298
  * └───────┴─────────┘
199
299
  */
200
300
  max(): this;
301
+ /**
302
+ * Aggregation: Finds the value in this column corresponding to the maximum value in the `by` expression.
303
+ * @param by Column or expression to order by.
304
+ * @returns ColumnExpression
305
+ * @example
306
+ * >>> const df = $df.data({ name: ["a", "b", "c"], score: [10, 50, 20] })
307
+ * >>> df.select($df.col("name").max_by($df.col("score")).alias("top_scorer"))
308
+ * shape: (1, 1)
309
+ * ┌────────────┐
310
+ * │ top_scorer │
311
+ * ├────────────┤
312
+ * │ "b" │
313
+ * └────────────┘
314
+ */
315
+ max_by(by: any): this;
201
316
  /**
202
317
  * Aggregation: Computes the arithmetic mean of elements in the group.
203
318
  * @returns ColumnExpression
@@ -240,6 +355,21 @@ export declare class AggregationExpr extends ExprBase {
240
355
  * └───────┴─────────┘
241
356
  */
242
357
  min(): this;
358
+ /**
359
+ * Aggregation: Finds the value in this column corresponding to the minimum value in the `by` expression.
360
+ * @param by Column or expression to order by.
361
+ * @returns ColumnExpression
362
+ * @example
363
+ * >>> const df = $df.data({ name: ["a", "b", "c"], score: [10, 50, 20] })
364
+ * >>> df.select($df.col("name").min_by($df.col("score")).alias("lowest_scorer"))
365
+ * shape: (1, 1)
366
+ * ┌──────────────┐
367
+ * │ lowest_scorer│
368
+ * ├──────────────┤
369
+ * │ "a" │
370
+ * └──────────────┘
371
+ */
372
+ min_by(by: any): this;
243
373
  /**
244
374
  * Aggregation: Finds the statistical mode (most frequent value).
245
375
  * @returns ColumnExpression
@@ -269,6 +399,34 @@ export declare class AggregationExpr extends ExprBase {
269
399
  * └───────┴────────────┘
270
400
  */
271
401
  n_unique(options?: UniqueArrayStatsOptions): this;
402
+ /**
403
+ * Aggregation: Finds the maximum value in the group, taking NaN values into account (NaN propagates).
404
+ * @returns ColumnExpression
405
+ * @example
406
+ * >>> const df = $df.data({ group: ["A", "A"], val: [10, NaN] })
407
+ * >>> df.group_by("group").agg($df.col("val").nan_max().alias("nan_max_val"))
408
+ * shape: (1, 2)
409
+ * ┌───────┬─────────────┐
410
+ * │ group │ nan_max_val │
411
+ * ├───────┼─────────────┤
412
+ * │ "A" │ NaN │
413
+ * └───────┴─────────────┘
414
+ */
415
+ nan_max(): this;
416
+ /**
417
+ * Aggregation: Finds the minimum value in the group, taking NaN values into account (NaN propagates).
418
+ * @returns ColumnExpression
419
+ * @example
420
+ * >>> const df = $df.data({ group: ["A", "A"], val: [10, NaN] })
421
+ * >>> df.group_by("group").agg($df.col("val").nan_min().alias("nan_min_val"))
422
+ * shape: (1, 2)
423
+ * ┌───────┬─────────────┐
424
+ * │ group │ nan_min_val │
425
+ * ├───────┼─────────────┤
426
+ * │ "A" │ NaN │
427
+ * └───────┴─────────────┘
428
+ */
429
+ nan_min(): this;
272
430
  /**
273
431
  * Aggregation: Counts the number of null or missing records.
274
432
  * @returns ColumnExpression
@@ -298,8 +456,38 @@ export declare class AggregationExpr extends ExprBase {
298
456
  * └─────┘
299
457
  */
300
458
  quantile(q: number): this;
459
+ /**
460
+ * Aggregation: Computes the product of all elements in the group.
461
+ * @returns ColumnExpression
462
+ * @example
463
+ * >>> const df = $df.data({ group: ["A", "A"], val: [2, 5] })
464
+ * >>> df.group_by("group").agg($df.col("val").product().alias("p"))
465
+ * shape: (1, 2)
466
+ * ┌───────┬────┐
467
+ * │ group │ p │
468
+ * ├───────┼────┤
469
+ * │ "A" │ 10 │
470
+ * └───────┴────┘
471
+ */
472
+ product(): this;
473
+ /**
474
+ * Aggregation: Computes the sample skewness as the Fisher-Pearson coefficient of skewness.
475
+ * @param options Skew calculation options ({ bias?: boolean }, default bias=true).
476
+ * @returns ColumnExpression
477
+ * @example
478
+ * >>> const df = $df.data({ val: [1, 2, 5, 10, 20] })
479
+ * >>> df.select($df.col("val").skew().alias("skewness"))
480
+ * shape: (1, 1)
481
+ * ┌──────────┐
482
+ * │ skewness │
483
+ * ├──────────┤
484
+ * │ 0.859427 │
485
+ * └──────────┘
486
+ */
487
+ skew(options?: SkewOptions): this;
301
488
  /**
302
489
  * Aggregation: Computes the Spearman rank correlation coefficient.
490
+
303
491
  * @param other The other column expression to correlate with.
304
492
  * @returns ColumnExpression
305
493
  * @example
@@ -341,6 +529,20 @@ export declare class AggregationExpr extends ExprBase {
341
529
  * └───────┴───────┘
342
530
  */
343
531
  sum(): this;
532
+ /**
533
+ * Aggregation: Computes sample variance.
534
+ * @returns ColumnExpression
535
+ * @example
536
+ * >>> const df = $df.data({ group: ["A", "A", "A"], val: [10, 20, 30] })
537
+ * >>> df.group_by("group").agg($df.col("val").variance().alias("v"))
538
+ * shape: (1, 2)
539
+ * ┌───────┬─────┐
540
+ * │ group │ v │
541
+ * ├───────┼─────┤
542
+ * │ "A" │ 100 │
543
+ * └───────┴─────┘
544
+ */
545
+ variance(): this;
344
546
  /**
345
547
  * Aggregation: Computes weighted average.
346
548
  * @param weights The weight values or column expression.
@@ -10,6 +10,22 @@ export declare class ArrayExprNamespace {
10
10
  expr: any;
11
11
  constructor(expr: any);
12
12
  _deriveArray(fn: (arr: any[] | AnyTypedArray) => any): any;
13
+ /**
14
+ * Applies an aggregation expression or element-wise calculation over each array cell.
15
+ * @param expr Aggregation expression (e.g. $df.element().sum() or $df.element().max())
16
+ * @returns ColumnExpression
17
+ * @example
18
+ * >>> const df = $df.data({ a: [[1, 2, 3], [4, 5]] })
19
+ * >>> df.with_columns($df.col("a").arr.agg($df.element().sum()).alias("sum_a"))
20
+ * shape: (2, 2)
21
+ * ┌───────────┬───────┐
22
+ * │ a │ sum_a │
23
+ * ├───────────┼───────┤
24
+ * │ [1, 2, 3] │ 6 │
25
+ * │ [4, 5] │ 9 │
26
+ * └───────────┴───────┘
27
+ */
28
+ agg(expr: IExpr): any;
13
29
  /**
14
30
  * Returns true if all items in nested list cells are truthy.
15
31
  * @returns ColumnExpression
@@ -40,6 +56,36 @@ export declare class ArrayExprNamespace {
40
56
  * └────────────────┴──────────┘
41
57
  */
42
58
  any(): any;
59
+ /**
60
+ * Finds the index of the maximum value in each array.
61
+ * @returns ColumnExpression
62
+ * @example
63
+ * >>> const df = $df.data({ a: [[1, 5, 2], [10, 4]] })
64
+ * >>> df.with_columns($df.col("a").arr.arg_max().alias("max_idx"))
65
+ * shape: (2, 2)
66
+ * ┌───────────┬─────────┐
67
+ * │ a │ max_idx │
68
+ * ├───────────┼─────────┤
69
+ * │ [1, 5, 2] │ 1 │
70
+ * │ [10, 4] │ 0 │
71
+ * └───────────┴─────────┘
72
+ */
73
+ arg_max(): any;
74
+ /**
75
+ * Finds the index of the minimum value in each array.
76
+ * @returns ColumnExpression
77
+ * @example
78
+ * >>> const df = $df.data({ a: [[5, 1, 2], [10, 4]] })
79
+ * >>> df.with_columns($df.col("a").arr.arg_min().alias("min_idx"))
80
+ * shape: (2, 2)
81
+ * ┌───────────┬─────────┐
82
+ * │ a │ min_idx │
83
+ * ├───────────┼─────────┤
84
+ * │ [5, 1, 2] │ 1 │
85
+ * │ [10, 4] │ 1 │
86
+ * └───────────┴─────────┘
87
+ */
88
+ arg_min(): any;
43
89
  /**
44
90
  * Checks if nested lists contain item.
45
91
  * @param item The element to search for.
@@ -122,20 +168,20 @@ export declare class ArrayExprNamespace {
122
168
  */
123
169
  filter(expr: IExpr): any;
124
170
  /**
125
- * Expands lists into row-wise records.
171
+ * Expands lists into row-wise elements and produces an index mapping for DataFrame unnesting.
126
172
  * @param options Config options including handling of empty arrays and nulls.
127
173
  * @returns ColumnExpression
128
174
  * @example
129
- * >>> const df = $df.data({ a: [[1, 2], [3]] })
130
- * >>> df.explode($df.col("a").arr.explode())
131
- * shape: (3, 1)
132
- * ┌───┐
133
- * │ a
134
- * ├───┤
135
- * │ 1 │
136
- * │ 2
137
- * │ 3
138
- * └───┘
175
+ * >>> const df = $df.data({ id: [1, 2], values: [[10, 20], [30]] })
176
+ * >>> df.select([$df.col("id"), $df.col("values").arr.explode()])
177
+ * shape: (3, 2)
178
+ * ┌─────┬────────┐
179
+ * │ id │ values
180
+ * ├─────┼────────┤
181
+ * │ 1 10
182
+ * │ 1 │ 20
183
+ * │ 2 │ 30
184
+ * └─────┴────────┘
139
185
  */
140
186
  explode({ empty_as_null, keep_nulls }?: ExplodeOptions): any;
141
187
  /**
@@ -271,21 +317,6 @@ export declare class ArrayExprNamespace {
271
317
  * └───────────┴───────┘
272
318
  */
273
319
  max(): any;
274
- /**
275
- * Returns the index of maximum value.
276
- * @returns ColumnExpression
277
- * @example
278
- * >>> const df = $df.data({ a: [[1, 5, 2], [10, 4]] })
279
- * >>> df.with_columns($df.col("a").arr.max_index().alias("max_idx"))
280
- * shape: (2, 2)
281
- * ┌───────────┬─────────┐
282
- * │ a │ max_idx │
283
- * ├───────────┼─────────┤
284
- * │ [1, 5, 2] │ 1 │
285
- * │ [10, 4] │ 0 │
286
- * └───────────┴─────────┘
287
- */
288
- max_index(): any;
289
320
  /**
290
321
  * Returns average of elements inside each list.
291
322
  * @returns ColumnExpression
@@ -331,21 +362,6 @@ export declare class ArrayExprNamespace {
331
362
  * └───────────┴───────┘
332
363
  */
333
364
  min(): any;
334
- /**
335
- * Returns the index of minimum value.
336
- * @returns ColumnExpression
337
- * @example
338
- * >>> const df = $df.data({ a: [[5, 1, 2], [10, 4]] })
339
- * >>> df.with_columns($df.col("a").arr.min_index().alias("min_idx"))
340
- * shape: (2, 2)
341
- * ┌───────────┬─────────┐
342
- * │ a │ min_idx │
343
- * ├───────────┼─────────┤
344
- * │ [5, 1, 2] │ 1 │
345
- * │ [10, 4] │ 1 │
346
- * └───────────┴─────────┘
347
- */
348
- min_index(): any;
349
365
  /**
350
366
  * Returns the mode value inside each list.
351
367
  * @returns ColumnExpression