df-script 1.4.0 → 1.5.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 (95) hide show
  1. package/README.md +83 -34
  2. package/dist/api.d.ts +16 -8
  3. package/dist/api.js +11 -3
  4. package/dist/columnExpressions/ColumnExpr.d.ts +26 -364
  5. package/dist/columnExpressions/ColumnExpr.js +199 -3
  6. package/dist/columnExpressions/ExprBase.d.ts +8 -11
  7. package/dist/columnExpressions/ExprBase.js +20 -61
  8. package/dist/columnExpressions/constants.d.ts +2 -0
  9. package/dist/columnExpressions/constants.js +3 -1
  10. package/dist/columnExpressions/functions/coalesce.js +8 -4
  11. package/dist/columnExpressions/functions/element.d.ts +5 -0
  12. package/dist/columnExpressions/functions/element.js +11 -0
  13. package/dist/columnExpressions/functions/implode.d.ts +3 -0
  14. package/dist/columnExpressions/functions/implode.js +7 -0
  15. package/dist/columnExpressions/functions/lit.d.ts +3 -1
  16. package/dist/columnExpressions/functions/lit.js +8 -13
  17. package/dist/columnExpressions/functions/repeat.d.ts +47 -0
  18. package/dist/columnExpressions/functions/repeat.js +131 -0
  19. package/dist/columnExpressions/functions/seq_range.d.ts +31 -0
  20. package/dist/columnExpressions/functions/seq_range.js +91 -0
  21. package/dist/columnExpressions/functions/when.js +8 -4
  22. package/dist/columnExpressions/index.d.ts +5 -2
  23. package/dist/columnExpressions/index.js +5 -48
  24. package/dist/columnExpressions/mixins/AggregationExpr.d.ts +25 -50
  25. package/dist/columnExpressions/mixins/AggregationExpr.js +69 -165
  26. package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +41 -66
  27. package/dist/columnExpressions/mixins/ArithmeticExpr.js +126 -138
  28. package/dist/columnExpressions/mixins/BooleanExpr.d.ts +40 -0
  29. package/dist/columnExpressions/mixins/BooleanExpr.js +67 -0
  30. package/dist/columnExpressions/mixins/ComparisonExpr.d.ts +31 -60
  31. package/dist/columnExpressions/mixins/ComparisonExpr.js +231 -370
  32. package/dist/columnExpressions/mixins/ListExpr.d.ts +15 -39
  33. package/dist/columnExpressions/mixins/ListExpr.js +124 -148
  34. package/dist/columnExpressions/mixins/LogicalExpr.d.ts +7 -33
  35. package/dist/columnExpressions/mixins/LogicalExpr.js +48 -49
  36. package/dist/columnExpressions/mixins/ManipulationExpr.d.ts +6 -31
  37. package/dist/columnExpressions/mixins/ManipulationExpr.js +61 -25
  38. package/dist/columnExpressions/mixins/NumericExpr.d.ts +92 -0
  39. package/dist/columnExpressions/mixins/NumericExpr.js +259 -0
  40. package/dist/columnExpressions/mixins/StringExpr.d.ts +5 -30
  41. package/dist/columnExpressions/mixins/StringExpr.js +37 -49
  42. package/dist/columnExpressions/mixins/StructExpr.d.ts +16 -0
  43. package/dist/columnExpressions/mixins/StructExpr.js +139 -0
  44. package/dist/columnExpressions/mixins/TemporalExpr.d.ts +4 -30
  45. package/dist/columnExpressions/mixins/TemporalExpr.js +28 -29
  46. package/dist/columnExpressions/mixins/WindowExpr.d.ts +27 -49
  47. package/dist/columnExpressions/mixins/WindowExpr.js +144 -274
  48. package/dist/columnExpressions/utils.d.ts +4 -0
  49. package/dist/columnExpressions/utils.js +45 -0
  50. package/dist/dataframe/constants.d.ts +3 -0
  51. package/dist/dataframe/constants.js +4 -1
  52. package/dist/dataframe/dataframe.d.ts +27 -10
  53. package/dist/dataframe/dataframe.js +461 -220
  54. package/dist/dataframe/grouped/grouped.d.ts +2 -3
  55. package/dist/dataframe/grouped/grouped.js +17 -16
  56. package/dist/dataframe/types.d.ts +65 -1
  57. package/dist/dataframe/utils.d.ts +11 -3
  58. package/dist/dataframe/utils.js +101 -9
  59. package/dist/datatypes/DataType.d.ts +2 -1
  60. package/dist/datatypes/DataType.js +29 -0
  61. package/dist/datatypes/index.d.ts +2 -2
  62. package/dist/datatypes/types.d.ts +37 -36
  63. package/dist/datatypes/types.js +15 -11
  64. package/dist/exceptions/index.d.ts +2 -0
  65. package/dist/exceptions/index.js +4 -1
  66. package/dist/exceptions/utils.d.ts +1 -0
  67. package/dist/exceptions/utils.js +19 -0
  68. package/dist/functions/concat.d.ts +1 -2
  69. package/dist/functions/concat.js +24 -12
  70. package/dist/functions/index.d.ts +3 -1
  71. package/dist/functions/index.js +7 -15
  72. package/dist/functions/read_csv.d.ts +8 -0
  73. package/dist/functions/read_csv.js +53 -0
  74. package/dist/functions/read_json.d.ts +10 -0
  75. package/dist/functions/read_json.js +21 -0
  76. package/dist/functions/transpose.d.ts +7 -0
  77. package/dist/functions/transpose.js +84 -0
  78. package/dist/index.js +6 -1
  79. package/dist/types.d.ts +31 -5
  80. package/dist/utils/csv.d.ts +77 -0
  81. package/dist/utils/csv.js +313 -0
  82. package/dist/utils/date.js +5 -6
  83. package/dist/utils/guards.d.ts +0 -2
  84. package/dist/utils/guards.js +0 -31
  85. package/dist/utils/index.d.ts +2 -0
  86. package/dist/utils/index.js +2 -0
  87. package/dist/utils/json.d.ts +120 -2
  88. package/dist/utils/json.js +204 -20
  89. package/dist/utils/list.d.ts +173 -1
  90. package/dist/utils/list.js +255 -22
  91. package/dist/utils/number.d.ts +61 -28
  92. package/dist/utils/number.js +248 -70
  93. package/dist/utils/string.d.ts +5 -0
  94. package/dist/utils/string.js +89 -0
  95. package/package.json +5 -1
@@ -3,16 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DataFrame = void 0;
4
4
  const columnExpressions_1 = require("../columnExpressions");
5
5
  const grouped_1 = require("./grouped/grouped");
6
+ const constants_1 = require("./constants");
7
+ const json_1 = require("../utils/json");
6
8
  const datatypes_1 = require("../datatypes");
7
9
  const utils_1 = require("../utils");
8
10
  const exceptions_1 = require("../exceptions");
9
11
  const concat_1 = require("../functions/concat");
10
- const constants_1 = require("./constants");
11
12
  const utils_2 = require("./utils");
12
13
  class DataFrame {
13
14
  _columns;
14
15
  _height;
15
16
  _schema = {};
17
+ static _createDirect(columns, schema, height) {
18
+ (0, exceptions_1.assertHeight)(columns, height);
19
+ const df = Object.create(DataFrame.prototype);
20
+ df._columns = columns;
21
+ df._schema = schema;
22
+ df._height = height;
23
+ return df;
24
+ }
16
25
  constructor(data, schema, height) {
17
26
  if (Array.isArray(data)) {
18
27
  const { columns, height: h } = (0, utils_2.rowsToColumns)(data);
@@ -22,18 +31,8 @@ class DataFrame {
22
31
  return;
23
32
  }
24
33
  if ((0, utils_1.isObj)(data)) {
25
- let firstLength = -1;
26
- for (const [key, col] of Object.entries(data)) {
27
- const colLen = (0, utils_1.isArrayOrTypedArray)(col) ? col.length : 0;
28
- if (firstLength === -1) {
29
- firstLength = colLen;
30
- }
31
- else if (colLen !== firstLength) {
32
- throw new exceptions_1.DataFrameError(`Column height mismatch: Column "${key}" has length ${colLen}, but previous columns have length ${firstLength}`);
33
- }
34
- }
35
34
  this._columns = data;
36
- this._height = height !== undefined ? height : (firstLength === -1 ? 0 : firstLength);
35
+ this._height = (0, exceptions_1.assertHeight)(data, height);
37
36
  schema ? this.applySchema(schema) : this.inferSchema();
38
37
  return;
39
38
  }
@@ -44,10 +43,12 @@ class DataFrame {
44
43
  inferSchema() {
45
44
  const schema = {};
46
45
  const keys = Object.keys(this._columns);
47
- for (const key of keys) {
46
+ const numKeys = keys.length;
47
+ for (let i = 0; i < numKeys; i++) {
48
+ const key = keys[i];
48
49
  schema[key] = (0, utils_2.inferColumnType)(this._columns[key]);
49
50
  }
50
- this._schema = schema;
51
+ this.applySchema(schema);
51
52
  }
52
53
  applySchema(schema) {
53
54
  this._schema = schema;
@@ -56,42 +57,12 @@ class DataFrame {
56
57
  for (const key of keys) {
57
58
  const type = schema[key];
58
59
  const oldCol = this._columns[key];
59
- let newCol = type.allocate ? type.allocate(this._height) : new Array(this._height).fill(null);
60
- if (!oldCol) {
61
- if (this._height > 0 && (0, utils_1.isTypedArray)(newCol)) {
62
- newCol = new Array(this._height).fill(null);
63
- }
64
- newColumns[key] = newCol;
65
- continue;
66
- }
67
- let hasNulls = false;
68
- const coercedVals = new Array(this._height);
69
- for (let i = 0; i < this._height; i++) {
70
- const coerced = type.coerce(oldCol[i]);
71
- coercedVals[i] = coerced;
72
- if (coerced == null) {
73
- hasNulls = true;
74
- }
75
- }
76
- if (hasNulls && (0, utils_1.isTypedArray)(newCol)) {
77
- newCol = new Array(this._height);
78
- }
79
- for (let i = 0; i < this._height; i++) {
80
- newCol[i] = coercedVals[i];
81
- }
82
- newColumns[key] = newCol;
60
+ newColumns[key] = oldCol
61
+ ? (0, utils_2.coerceColumn)(oldCol, type, this._height)
62
+ : (0, utils_2.coerceColumn)(new Array(this._height).fill(null), type, this._height);
83
63
  }
84
64
  this._columns = newColumns;
85
65
  }
86
- getSchema() {
87
- return this._schema;
88
- }
89
- to_dicts() {
90
- return (0, utils_2.columnsToRows)(this._columns, this._height);
91
- }
92
- to_dict() {
93
- return { ...this._columns };
94
- }
95
66
  get columns() {
96
67
  return Object.keys(this._columns);
97
68
  }
@@ -111,7 +82,12 @@ class DataFrame {
111
82
  outSchema[key] = this._schema[key];
112
83
  }
113
84
  }
114
- return new DataFrame(newColumns, outSchema, this._height);
85
+ return DataFrame._createDirect(newColumns, outSchema, this._height);
86
+ }
87
+ drop_nulls(subset) {
88
+ if (this._height === 0)
89
+ return this;
90
+ return this.filter(subset ? new columnExpressions_1.ColumnExpr(subset).is_not_null() : (0, columnExpressions_1.all)().is_not_null());
115
91
  }
116
92
  get dtypes() {
117
93
  const keys = Object.keys(this._columns);
@@ -122,22 +98,59 @@ class DataFrame {
122
98
  }
123
99
  return result;
124
100
  }
101
+ explode(columns, options) {
102
+ const expr = columnExpressions_1.ColumnExpr.toColExpr(columns);
103
+ const colNames = expr.colNames || [expr.colName || expr.outputName];
104
+ const colsToExplode = new Set();
105
+ const numCols = colNames.length;
106
+ for (let i = 0; i < numCols; i++) {
107
+ const name = colNames[i];
108
+ if (!name) {
109
+ throw new exceptions_1.DataFrameError("Expression passed to explode must have a column name.");
110
+ }
111
+ (0, exceptions_1.assertColumnExists)(name, this._columns, "Explode column");
112
+ colsToExplode.add(name);
113
+ }
114
+ const keys = Object.keys(this._columns);
115
+ const selectList = [];
116
+ const numKeys = keys.length;
117
+ for (let i = 0; i < numKeys; i++) {
118
+ const key = keys[i];
119
+ selectList.push(colsToExplode.has(key)
120
+ ? new columnExpressions_1.ColumnExpr(key).list.explode(options)
121
+ : new columnExpressions_1.ColumnExpr(key));
122
+ }
123
+ return this.select(...selectList);
124
+ }
125
+ fill_null(options = {}) {
126
+ if (this._height === 0)
127
+ return this;
128
+ return this.with_columns((0, columnExpressions_1.all)().fill_null(options));
129
+ }
125
130
  filter(...exprs) {
126
131
  if (this._height === 0)
127
- return new DataFrame({}, this._schema, 0);
132
+ return DataFrame._createDirect({}, this._schema, 0);
128
133
  const height = this._height;
129
134
  const keys = Object.keys(this._columns);
130
135
  const numKeys = keys.length;
131
136
  const evaluatedExprs = [];
132
137
  const funcPredicates = [];
133
- for (const expr of exprs) {
138
+ const exprSelectors = [];
139
+ const numExprs = exprs.length;
140
+ for (let i = 0; i < numExprs; i++) {
141
+ const expr = exprs[i];
134
142
  if (typeof expr === "function") {
135
143
  funcPredicates.push(expr);
136
144
  }
137
145
  else {
138
- evaluatedExprs.push(expr.evaluate(this._columns, height));
146
+ exprSelectors.push(expr);
139
147
  }
140
148
  }
149
+ const expandedExprs = (0, columnExpressions_1.resolveColumnSelectors)(exprSelectors, keys, undefined, this._schema, this._columns);
150
+ const numExpanded = expandedExprs.length;
151
+ for (let i = 0; i < numExpanded; i++) {
152
+ evaluatedExprs.push(expandedExprs[i].evaluate(this._columns, height));
153
+ }
141
154
  const matchingIndices = [];
142
155
  let currentIndex = 0;
143
156
  let rowObj = null;
@@ -182,36 +195,21 @@ class DataFrame {
182
195
  }
183
196
  const newColumns = (0, utils_2.gatherColumnsByIndices)(this._columns, matchingIndices);
184
197
  const newHeight = matchingIndices.length;
185
- return new DataFrame(newColumns, this._schema, newHeight);
198
+ return DataFrame._createDirect(newColumns, this._schema, newHeight);
199
+ }
200
+ get_schema() {
201
+ return this._schema;
186
202
  }
187
203
  groupby(keys) {
188
204
  const keysArr = (0, utils_1.toValidArray)(keys);
189
205
  const groups = new Map();
190
206
  const len = this._height;
191
- const keysLen = keysArr.length;
192
- const keysStr = new Array(keysLen);
193
- for (let i = 0; i < keysLen; i++) {
194
- keysStr[i] = String(keysArr[i]);
195
- }
207
+ const keysStr = (0, utils_1.toValidStringArray)(keys);
196
208
  for (let j = 0; j < keysStr.length; j++) {
197
209
  (0, exceptions_1.assertColumnExists)(keysStr[j], this._columns, "Grouping key");
198
210
  }
199
- const singleKey = keysLen === 1 ? keysStr[0] : null;
200
- const col = singleKey ? this._columns[singleKey] : null;
201
211
  for (let i = 0; i < len; i++) {
202
- let hash;
203
- if (singleKey) {
204
- const val = col[i];
205
- hash = val == null ? "" : String(val);
206
- }
207
- else {
208
- const vals = new Array(keysLen);
209
- for (let j = 0; j < keysLen; j++) {
210
- const val = this._columns[keysStr[j]][i];
211
- vals[j] = val == null ? "" : String(val);
212
- }
213
- hash = vals.join(constants_1.KEY_SEPARATOR);
214
- }
212
+ const hash = (0, utils_2.computeRowHash)(this._columns, keysStr, i);
215
213
  let group = groups.get(hash);
216
214
  if (group === undefined) {
217
215
  groups.set(hash, group = []);
@@ -230,34 +228,109 @@ class DataFrame {
230
228
  hstack(other, options = {}) {
231
229
  return this.concat(other, { how: "horizontal", horizontal: options });
232
230
  }
231
+ insert_column(index, name, expr) {
232
+ const colExpr = columnExpressions_1.ColumnExpr.toColExpr(expr).alias(name);
233
+ const keys = Object.keys(this._columns);
234
+ const keysLen = keys.length;
235
+ const selectList = [];
236
+ for (let i = 0; i < keysLen; i++) {
237
+ const k = keys[i];
238
+ if (k !== name) {
239
+ selectList.push(k);
240
+ }
241
+ }
242
+ const targetIndex = Math.max(0, Math.min(index, selectList.length));
243
+ selectList.splice(targetIndex, 0, colExpr);
244
+ return this.select(...selectList);
245
+ }
246
+ item(row, column) {
247
+ const height = this._height;
248
+ const keys = Object.keys(this._columns);
249
+ const width = keys.length;
250
+ if (row === undefined && column === undefined) {
251
+ if (height !== 1 || width !== 1) {
252
+ throw new Error("DataFrame.item() can only be called without arguments if the shape is (1, 1).");
253
+ }
254
+ return this._columns[keys[0]][0];
255
+ }
256
+ if (row === undefined || column === undefined) {
257
+ throw new Error("DataFrame.item() requires both row and column to be specified if not empty.");
258
+ }
259
+ if (row < 0 || row >= height) {
260
+ throw new Error(`Row index ${row} is out of bounds for DataFrame height ${height}.`);
261
+ }
262
+ let colName;
263
+ if (typeof column === "number") {
264
+ if (column < 0 || column >= width) {
265
+ throw new Error(`Column index ${column} is out of bounds for DataFrame width ${width}.`);
266
+ }
267
+ colName = keys[column];
268
+ }
269
+ else {
270
+ colName = column;
271
+ if (this._columns[colName] === undefined) {
272
+ throw new Error(`Column "${colName}" does not exist.`);
273
+ }
274
+ }
275
+ return this._columns[colName][row];
276
+ }
277
+ *iter_columns() {
278
+ const keys = Object.keys(this._columns);
279
+ const keysLen = keys.length;
280
+ const columns = this._columns;
281
+ for (let j = 0; j < keysLen; j++) {
282
+ yield columns[keys[j]];
283
+ }
284
+ }
285
+ *iter_rows({ named = false } = {}) {
286
+ const keys = Object.keys(this._columns);
287
+ const keysLen = keys.length;
288
+ const columns = this._columns;
289
+ const height = this._height;
290
+ const colArrays = new Array(keysLen);
291
+ for (let j = 0; j < keysLen; j++) {
292
+ colArrays[j] = columns[keys[j]];
293
+ }
294
+ if (named) {
295
+ for (let i = 0; i < height; i++) {
296
+ const row = {};
297
+ for (let j = 0; j < keysLen; j++) {
298
+ row[keys[j]] = colArrays[j][i];
299
+ }
300
+ yield row;
301
+ }
302
+ }
303
+ else {
304
+ for (let i = 0; i < height; i++) {
305
+ const row = new Array(keysLen);
306
+ for (let j = 0; j < keysLen; j++) {
307
+ row[j] = colArrays[j][i];
308
+ }
309
+ yield row;
310
+ }
311
+ }
312
+ }
233
313
  join(config) {
234
314
  const { other, on, how = "inner", suffixes = ["", "_right"] } = config;
235
- const joinKeys = (0, utils_1.toValidArray)(on);
236
- for (const key of joinKeys) {
237
- const keyStr = String(key);
315
+ const joinKeysStr = (0, utils_1.toValidStringArray)(on);
316
+ for (let i = 0; i < joinKeysStr.length; i++) {
317
+ const keyStr = joinKeysStr[i];
238
318
  (0, exceptions_1.assertColumnExists)(keyStr, this._columns, "Join key", " in the left DataFrame.");
239
319
  (0, exceptions_1.assertColumnExists)(keyStr, other._columns, "Join key", " in the right DataFrame.");
240
320
  }
241
321
  const [leftSuffix, rightSuffix] = suffixes;
242
322
  const leftKeys = Object.keys(this._columns);
243
323
  const rightKeys = Object.keys(other._columns);
244
- const joinKeySet = new Set(joinKeys);
324
+ const joinKeySet = new Set(joinKeysStr);
245
325
  const leftLen = leftKeys.length;
246
326
  const rightLen = rightKeys.length;
247
327
  const getColumnHashAt = (columns, idx) => {
248
- const len = joinKeys.length;
249
- if (len === 1) {
250
- const val = columns[joinKeys[0]][idx];
251
- return val == null ? null : String(val);
252
- }
253
- const vals = new Array(len);
328
+ const len = joinKeysStr.length;
254
329
  for (let i = 0; i < len; i++) {
255
- const val = columns[joinKeys[i]][idx];
256
- if (val == null)
330
+ if (columns[joinKeysStr[i]][idx] == null)
257
331
  return null;
258
- vals[i] = String(val);
259
332
  }
260
- return vals.join(constants_1.KEY_SEPARATOR);
333
+ return (0, utils_2.computeRowHash)(columns, joinKeysStr, idx);
261
334
  };
262
335
  const rightHash = new Map();
263
336
  const rightHeight = other._height;
@@ -356,87 +429,66 @@ class DataFrame {
356
429
  }
357
430
  }
358
431
  }
359
- return new DataFrame(newColumns, outSchema, outHeight);
432
+ return DataFrame._createDirect(newColumns, outSchema, outHeight);
360
433
  }
361
- limit(n, options = {}) {
362
- const { offset = 0, from = "start" } = options;
434
+ limit(n, { offset = 0, from = "start" } = {}) {
363
435
  const len = this._height;
364
- const safeN = isNaN(n) ? 0 : Math.max(Math.floor(n), 0);
365
- const safeOffset = isNaN(offset) ? 0 : Math.max(Math.floor(offset), 0);
366
- if (safeN === 0 || len === 0 || safeOffset >= len) {
367
- const newColumns = {};
368
- const outSchema = {};
369
- for (const key of Object.keys(this._columns)) {
370
- newColumns[key] = [];
371
- outSchema[key] = this._schema[key];
372
- }
373
- return new DataFrame(newColumns, outSchema, 0);
374
- }
375
- let actualStart = 0;
376
- let actualEnd = 0;
436
+ const safeN = (0, utils_1.clamp)(Math.floor(n), { min: 0, max: len });
437
+ const safeOffset = (0, utils_1.clamp)(Math.floor(offset), { min: 0, max: len });
438
+ let actualStart = safeOffset;
439
+ let actualEnd = Math.min(safeOffset + safeN, len);
377
440
  if (from === "end") {
378
- actualEnd = Math.max(len - safeOffset, 0);
441
+ actualEnd = len - safeOffset;
379
442
  actualStart = Math.max(actualEnd - safeN, 0);
380
443
  }
381
- else {
382
- actualEnd = Math.min(safeOffset + safeN, len);
383
- actualStart = safeOffset;
384
- }
385
- const newHeight = Math.max(actualEnd - actualStart, 0);
444
+ const newHeight = actualEnd - actualStart;
386
445
  const newColumns = {};
387
- for (const key of Object.keys(this._columns)) {
446
+ const keys = Object.keys(this._columns);
447
+ const keysLen = keys.length;
448
+ for (let i = 0; i < keysLen; i++) {
449
+ const key = keys[i];
388
450
  newColumns[key] = this._columns[key].slice(actualStart, actualEnd);
389
451
  }
390
- return new DataFrame(newColumns, this._schema, newHeight);
452
+ return DataFrame._createDirect(newColumns, this._schema, newHeight);
391
453
  }
392
454
  pivot(config) {
393
455
  if (this._height === 0)
394
- return new DataFrame({}, {}, 0);
456
+ return DataFrame._createDirect({}, {}, 0);
395
457
  const { index, columns, values } = config;
396
- const indexArr = (0, utils_1.toValidArray)(index);
397
- const indexLen = indexArr.length;
398
- const indexStr = new Array(indexLen);
399
- for (let i = 0; i < indexLen; i++) {
400
- indexStr[i] = String(indexArr[i]);
458
+ const indexStr = (0, utils_1.toValidStringArray)(index);
459
+ const indexLen = indexStr.length;
460
+ for (let j = 0; j < indexLen; j++) {
461
+ (0, exceptions_1.assertColumnExists)(indexStr[j], this._columns, "Pivot index key");
401
462
  }
402
463
  const colKey = String(columns);
403
464
  const valKey = String(values);
404
- for (const idxKey of indexStr) {
405
- (0, exceptions_1.assertColumnExists)(idxKey, this._columns, "Pivot index key", " in the DataFrame.");
406
- }
407
465
  (0, exceptions_1.assertColumnExists)(colKey, this._columns, "Pivot column key");
408
- (0, exceptions_1.assertColumnExists)(valKey, this._columns, "Pivot values key", " in the DataFrame.");
466
+ (0, exceptions_1.assertColumnExists)(valKey, this._columns, "Pivot values key");
409
467
  const groups = new Map();
468
+ const firstRowIdxs = [];
410
469
  const colNames = new Set();
411
470
  const height = this._height;
412
471
  const pivotCol = this._columns[colKey];
413
472
  const valCol = this._columns[valKey];
414
473
  for (let i = 0; i < height; i++) {
415
- const vals = new Array(indexLen);
416
- for (let j = 0; j < indexLen; j++) {
417
- const val = this._columns[indexStr[j]][i];
418
- vals[j] = val == null ? "" : String(val);
419
- }
420
- const rowKey = vals.join(constants_1.KEY_SEPARATOR);
421
- const pivotColName = String(pivotCol[i]);
422
- colNames.add(pivotColName);
423
- let group = groups.get(rowKey);
424
- if (group === undefined) {
425
- group = { firstIdx: i, indices: [] };
426
- groups.set(rowKey, group);
474
+ const rowKey = (0, utils_2.computeRowHash)(this._columns, indexStr, i);
475
+ colNames.add(String(pivotCol[i]));
476
+ if (groups.get(rowKey) === undefined) {
477
+ groups.set(rowKey, groups.size);
478
+ firstRowIdxs.push(i);
427
479
  }
428
- group.indices.push(i);
429
480
  }
430
481
  const outHeight = groups.size;
431
- const newColumns = {};
482
+ const indexColsDict = {};
432
483
  const outSchema = {};
433
484
  for (let j = 0; j < indexLen; j++) {
434
- const k = indexStr[j];
435
- newColumns[k] = new Array(outHeight);
436
- if (this._schema[k]) {
437
- outSchema[k] = this._schema[k];
485
+ const idxKey = indexStr[j];
486
+ indexColsDict[idxKey] = this._columns[idxKey];
487
+ if (this._schema[idxKey]) {
488
+ outSchema[idxKey] = this._schema[idxKey];
438
489
  }
439
490
  }
491
+ const newColumns = (0, utils_2.gatherColumnsByIndices)(indexColsDict, firstRowIdxs);
440
492
  const allCols = Array.from(colNames);
441
493
  const valType = this._schema[valKey] || datatypes_1.DataTypeRegistry.Utf8;
442
494
  for (let j = 0; j < allCols.length; j++) {
@@ -444,22 +496,13 @@ class DataFrame {
444
496
  newColumns[colName] = new Array(outHeight).fill(null);
445
497
  outSchema[colName] = valType;
446
498
  }
447
- let groupIdx = 0;
448
- for (const group of groups.values()) {
449
- const firstIdx = group.firstIdx;
450
- for (let j = 0; j < indexLen; j++) {
451
- const k = indexStr[j];
452
- newColumns[k][groupIdx] = this._columns[k][firstIdx];
453
- }
454
- const indices = group.indices;
455
- for (let k = 0; k < indices.length; k++) {
456
- const idx = indices[k];
457
- const pivotColName = String(pivotCol[idx]);
458
- newColumns[pivotColName][groupIdx] = valCol[idx];
459
- }
460
- groupIdx++;
499
+ for (let i = 0; i < height; i++) {
500
+ const rowKey = (0, utils_2.computeRowHash)(this._columns, indexStr, i);
501
+ const groupIdx = groups.get(rowKey);
502
+ const pivotColName = String(pivotCol[i]);
503
+ newColumns[pivotColName][groupIdx] = valCol[i];
461
504
  }
462
- return new DataFrame(newColumns, outSchema, outHeight);
505
+ return DataFrame._createDirect(newColumns, outSchema, outHeight);
463
506
  }
464
507
  rename(mapping) {
465
508
  const renameMapping = mapping || {};
@@ -475,7 +518,7 @@ class DataFrame {
475
518
  if (finalKeys.length < originalKeys.length) {
476
519
  throw new exceptions_1.DataFrameError("Rename collision: Multiple columns mapped to the same output name.");
477
520
  }
478
- return new DataFrame(newColumns, outSchema, this._height);
521
+ return DataFrame._createDirect(newColumns, outSchema, this._height);
479
522
  }
480
523
  reverse() {
481
524
  if (this._height === 0)
@@ -487,7 +530,7 @@ class DataFrame {
487
530
  const key = keys[i];
488
531
  newColumns[key] = this._columns[key].slice().reverse();
489
532
  }
490
- return new DataFrame(newColumns, this._schema, this._height);
533
+ return DataFrame._createDirect(newColumns, this._schema, this._height);
491
534
  }
492
535
  get schema() {
493
536
  return this._schema;
@@ -495,24 +538,99 @@ class DataFrame {
495
538
  select(...args) {
496
539
  const exprs = this._normalizeArgs(args);
497
540
  const allKeys = Object.keys(this._columns);
498
- const expandedExprs = (0, columnExpressions_1.resolveColumnSelectors)(exprs, allKeys);
541
+ const expandedExprs = (0, columnExpressions_1.resolveColumnSelectors)(exprs, allKeys, undefined, this._schema, this._columns);
542
+ const numExprs = expandedExprs.length;
543
+ if (numExprs === 0) {
544
+ return DataFrame._createDirect({}, {}, this._height);
545
+ }
499
546
  const newColumns = {};
500
547
  const outSchema = {};
501
- for (const expr of expandedExprs) {
548
+ const evaluatedCols = new Array(numExprs);
549
+ const targetKeys = new Array(numExprs);
550
+ const selectedKeys = new Set();
551
+ let activeRowMap = null;
552
+ for (let i = 0; i < numExprs; i++) {
553
+ const expr = expandedExprs[i];
502
554
  const targetKey = expr.outputName || expr.colName || columnExpressions_1.ALL_COLUMNS_MARKER;
503
- if (targetKey in newColumns) {
555
+ if (selectedKeys.has(targetKey)) {
504
556
  throw new exceptions_1.DataFrameError(`Duplicate column selection: "${targetKey}" is selected multiple times.`);
505
557
  }
506
- newColumns[targetKey] = expr.isWindow
507
- ? (0, utils_2.resolveWindowExpr)(expr, this._columns, this._height)
508
- : expr.evaluate(this._columns, this._height);
558
+ selectedKeys.add(targetKey);
559
+ const col = (0, columnExpressions_1.evaluateExpression)(expr, this._columns, this._height);
560
+ evaluatedCols[i] = col;
561
+ targetKeys[i] = targetKey;
562
+ const rowMap = col && col.rowMap;
563
+ if (rowMap) {
564
+ if (activeRowMap) {
565
+ const len = rowMap.length;
566
+ if (len !== activeRowMap.length) {
567
+ throw new exceptions_1.ShapeError(`Mismatched explode heights: Column "${targetKey}" has length ${len}, but another exploded column has length ${activeRowMap.length}`);
568
+ }
569
+ for (let j = 0; j < len; j++) {
570
+ if (rowMap[j] !== activeRowMap[j]) {
571
+ throw new exceptions_1.ShapeError(`Mismatched explode heights: Column "${targetKey}" has mismatched row lengths compared to another exploded column.`);
572
+ }
573
+ }
574
+ }
575
+ else {
576
+ activeRowMap = rowMap;
577
+ }
578
+ }
579
+ }
580
+ let targetHeight = activeRowMap ? activeRowMap.length : this._height;
581
+ let shouldCollapse = numExprs > 0;
582
+ for (let i = 0; i < numExprs; i++) {
583
+ const expr = expandedExprs[i];
584
+ const isGlobalAgg = expr.aggFn != null && (expr.partitionBy == null || expr.partitionBy.length === 0);
585
+ const isLit = !!expr.isLiteral;
586
+ if (!isGlobalAgg && !isLit) {
587
+ shouldCollapse = false;
588
+ break;
589
+ }
590
+ }
591
+ for (let i = 0; i < numExprs; i++) {
592
+ const targetKey = targetKeys[i];
593
+ let col = evaluatedCols[i];
594
+ const colObj = col;
595
+ const hasRowMap = colObj && colObj.rowMap;
596
+ const len = (0, utils_1.isArrayOrTypedArray)(col) ? col.length : 0;
597
+ const expectedLen = (activeRowMap && !hasRowMap) ? this._height : targetHeight;
598
+ if (len !== expectedLen) {
599
+ throw new exceptions_1.ShapeError(`Column height mismatch: Column "${targetKey}" has length ${len}, but expected ${expectedLen}`);
600
+ }
601
+ if (activeRowMap && !hasRowMap) {
602
+ const mapLen = activeRowMap.length;
603
+ if ((0, utils_1.isTypedArray)(col)) {
604
+ const newCol = new colObj.constructor(mapLen);
605
+ for (let j = 0; j < mapLen; j++) {
606
+ newCol[j] = colObj[activeRowMap[j]];
607
+ }
608
+ col = newCol;
609
+ }
610
+ else {
611
+ const newCol = new Array(mapLen);
612
+ for (let j = 0; j < mapLen; j++) {
613
+ newCol[j] = colObj[activeRowMap[j]];
614
+ }
615
+ col = newCol;
616
+ }
617
+ }
618
+ evaluatedCols[i] = col;
619
+ }
620
+ if (shouldCollapse) {
621
+ targetHeight = 1;
622
+ }
623
+ for (let i = 0; i < numExprs; i++) {
624
+ const expr = expandedExprs[i];
625
+ const targetKey = targetKeys[i];
626
+ const col = evaluatedCols[i];
509
627
  const originalKey = expr.colName || targetKey;
510
- const isPureColSelector = expr instanceof columnExpressions_1.ColumnExpr && expr.ops.length === 0 && !expr.isWindow && !expr.aggFn;
511
- outSchema[targetKey] = (isPureColSelector && this._schema[originalKey])
512
- ? this._schema[originalKey]
513
- : (0, utils_2.inferColumnType)(newColumns[targetKey]);
628
+ const isPureCol = expr instanceof columnExpressions_1.ColumnExpr && expr.ops.length === 0 && !expr.isWindow && !expr.aggFn;
629
+ const type = (isPureCol && this._schema[originalKey]) || (0, utils_2.inferColumnType)(col);
630
+ outSchema[targetKey] = type;
631
+ newColumns[targetKey] = (0, utils_2.coerceColumn)(col, type, targetHeight);
514
632
  }
515
- return new DataFrame(newColumns, outSchema, this._height);
633
+ return DataFrame._createDirect(newColumns, outSchema, targetHeight);
516
634
  }
517
635
  get shape() {
518
636
  return [this.height, this.width];
@@ -532,9 +650,9 @@ class DataFrame {
532
650
  const { by, descending = false, nullsLast = true, custom } = config;
533
651
  const sortKeys = (0, utils_1.toValidArray)(by);
534
652
  for (let i = 0; i < sortKeys.length; i++) {
535
- const keyOrExpr = sortKeys[i];
536
- if (typeof keyOrExpr === "string") {
537
- (0, exceptions_1.assertColumnExists)(keyOrExpr, this._columns, "Sort key");
653
+ const expr = columnExpressions_1.ColumnExpr.toColExpr(sortKeys[i]);
654
+ if (expr.colName) {
655
+ (0, exceptions_1.assertColumnExists)(expr.colName, this._columns, "Sort key");
538
656
  }
539
657
  }
540
658
  const descArray = Array.isArray(descending)
@@ -546,9 +664,7 @@ class DataFrame {
546
664
  const keyOrExpr = sortKeys[i];
547
665
  const isDesc = descArray[i] ? -1 : 1;
548
666
  const customComp = (custom && typeof keyOrExpr === "string") ? custom[keyOrExpr] : null;
549
- const values = keyOrExpr?.evaluate
550
- ? keyOrExpr.evaluate(this._columns, this._height)
551
- : (this._columns[keyOrExpr] || new Array(this._height).fill(null));
667
+ const values = columnExpressions_1.ColumnExpr.toColExpr(keyOrExpr).evaluate(this._columns, this._height);
552
668
  plan[i] = {
553
669
  values,
554
670
  isDesc,
@@ -585,33 +701,103 @@ class DataFrame {
585
701
  return 0;
586
702
  });
587
703
  const newColumns = (0, utils_2.gatherColumnsByIndices)(this._columns, indices);
588
- return new DataFrame(newColumns, this._schema, this._height);
704
+ return DataFrame._createDirect(newColumns, this._schema, this._height);
589
705
  }
590
706
  tail(n = 10) {
591
707
  return this.limit(n, { offset: 0, from: 'end' });
592
708
  }
709
+ to_dict() {
710
+ return { ...this._columns };
711
+ }
712
+ to_dicts() {
713
+ return (0, utils_2.columnsToRows)(this._columns, this._height);
714
+ }
593
715
  to_list(nameOrExpr) {
594
716
  if (this._height === 0)
595
717
  return [];
596
- const isExpr = nameOrExpr && typeof nameOrExpr !== "string" && "evaluate" in nameOrExpr;
597
- let colData;
598
- if (isExpr) {
599
- const expr = nameOrExpr;
600
- colData = expr.evaluate(this._columns, this._height);
718
+ if (nameOrExpr == null) {
719
+ return new Array(this._height).fill(null);
720
+ }
721
+ const expr = columnExpressions_1.ColumnExpr.toColExpr(nameOrExpr);
722
+ const colData = expr.evaluate(this._columns, this._height);
723
+ return Array.isArray(colData) ? colData : Array.from(colData);
724
+ }
725
+ transpose({ include_header: includeHeader = false, header_name: headerName = "column", column_names: colNamesOpt } = {}) {
726
+ if (this._height === 0) {
727
+ const cols = {};
728
+ const schema = {};
729
+ if (includeHeader) {
730
+ cols[headerName] = (0, utils_2.coerceColumn)([], datatypes_1.DataTypeRegistry.Utf8, 0);
731
+ schema[headerName] = datatypes_1.DataTypeRegistry.Utf8;
732
+ }
733
+ return DataFrame._createDirect(cols, schema, 0);
734
+ }
735
+ let dataColumns = this.columns;
736
+ if (typeof colNamesOpt === "string") {
737
+ (0, exceptions_1.assertColumnExists)(colNamesOpt, this._columns, "column_names");
738
+ dataColumns = dataColumns.filter(c => c !== colNamesOpt);
739
+ }
740
+ let newColNames = [];
741
+ if (typeof colNamesOpt === "string") {
742
+ const keyCol = this._columns[colNamesOpt];
743
+ newColNames = new Array(this._height);
744
+ for (let i = 0; i < this._height; i++) {
745
+ const val = keyCol[i];
746
+ if (val == null) {
747
+ throw new exceptions_1.DataFrameError(`Transpose column_names column "${colNamesOpt}" contains null/undefined at index ${i}`);
748
+ }
749
+ newColNames[i] = String(val);
750
+ }
751
+ }
752
+ else if (colNamesOpt != null && typeof colNamesOpt !== "string" && Symbol.iterator in Object(colNamesOpt)) {
753
+ const colNamesArr = Array.from(colNamesOpt);
754
+ if (colNamesArr.length !== this._height) {
755
+ throw new exceptions_1.DataFrameError(`column_names length (${colNamesArr.length}) must match the height of the DataFrame (${this._height})`);
756
+ }
757
+ newColNames = new Array(this._height);
758
+ for (let i = 0; i < this._height; i++) {
759
+ newColNames[i] = String(colNamesArr[i]);
760
+ }
601
761
  }
602
762
  else {
603
- const key = nameOrExpr;
604
- if (key == null) {
605
- return new Array(this._height).fill(null);
763
+ newColNames = new Array(this._height);
764
+ for (let i = 0; i < this._height; i++) {
765
+ newColNames[i] = `column_${i}`;
606
766
  }
607
- (0, exceptions_1.assertColumnExists)(key, this._columns, "Column");
608
- colData = this._columns[key];
609
767
  }
610
- return Array.isArray(colData) ? colData : Array.from(colData);
768
+ const uniqueNames = new Set();
769
+ if (includeHeader) {
770
+ uniqueNames.add(headerName);
771
+ }
772
+ for (let i = 0; i < newColNames.length; i++) {
773
+ const name = newColNames[i];
774
+ if (uniqueNames.has(name)) {
775
+ throw new exceptions_1.DataFrameError(`Duplicate column name in transposed DataFrame: "${name}"`);
776
+ }
777
+ uniqueNames.add(name);
778
+ }
779
+ const numDataCols = dataColumns.length;
780
+ const newCols = {};
781
+ const newSchema = {};
782
+ if (includeHeader) {
783
+ newCols[headerName] = (0, utils_2.coerceColumn)(dataColumns, datatypes_1.DataTypeRegistry.Utf8, numDataCols);
784
+ newSchema[headerName] = datatypes_1.DataTypeRegistry.Utf8;
785
+ }
786
+ for (let i = 0; i < this._height; i++) {
787
+ const colName = newColNames[i];
788
+ const rawVals = new Array(numDataCols);
789
+ for (let j = 0; j < numDataCols; j++) {
790
+ rawVals[j] = this._columns[dataColumns[j]][i];
791
+ }
792
+ const type = (0, utils_2.inferColumnType)(rawVals);
793
+ newCols[colName] = (0, utils_2.coerceColumn)(rawVals, type, numDataCols);
794
+ newSchema[colName] = type;
795
+ }
796
+ return DataFrame._createDirect(newCols, newSchema, numDataCols);
611
797
  }
612
798
  unique(columns) {
613
799
  if (this._height === 0)
614
- return new DataFrame({}, this._schema, 0);
800
+ return DataFrame._createDirect({}, this._schema, 0);
615
801
  const colsArr = (0, utils_1.toValidArray)(columns);
616
802
  const colsStr = colsArr.length === 0
617
803
  ? Object.keys(this._columns)
@@ -621,23 +807,9 @@ class DataFrame {
621
807
  }
622
808
  const seen = new Set();
623
809
  const matchingIndices = [];
624
- const colsLen = colsStr.length;
625
810
  const height = this._height;
626
- const singleCol = colsLen === 1 ? this._columns[colsStr[0]] : null;
627
811
  for (let i = 0; i < height; i++) {
628
- let hash;
629
- if (singleCol) {
630
- const val = singleCol[i];
631
- hash = val == null ? "" : String(val);
632
- }
633
- else {
634
- const vals = new Array(colsLen);
635
- for (let j = 0; j < colsLen; j++) {
636
- const val = this._columns[colsStr[j]][i];
637
- vals[j] = val == null ? "" : String(val);
638
- }
639
- hash = vals.join(constants_1.KEY_SEPARATOR);
640
- }
812
+ const hash = (0, utils_2.computeRowHash)(this._columns, colsStr, i);
641
813
  if (!seen.has(hash)) {
642
814
  seen.add(hash);
643
815
  matchingIndices.push(i);
@@ -645,12 +817,12 @@ class DataFrame {
645
817
  }
646
818
  const newColumns = (0, utils_2.gatherColumnsByIndices)(this._columns, matchingIndices);
647
819
  const newHeight = matchingIndices.length;
648
- return new DataFrame(newColumns, this._schema, newHeight);
820
+ return DataFrame._createDirect(newColumns, this._schema, newHeight);
649
821
  }
650
822
  unpivot(config) {
651
823
  const { idVars, valueVars, varName = "variable", valueName = "value" } = config;
652
- const idVarsStr = (0, utils_1.toValidArray)(idVars).map(String);
653
- const valueVarsStr = (0, utils_1.toValidArray)(valueVars).map(String);
824
+ const idVarsStr = (0, utils_1.toValidStringArray)(idVars);
825
+ const valueVarsStr = (0, utils_1.toValidStringArray)(valueVars);
654
826
  const idVarsLen = idVarsStr.length;
655
827
  const valueVarsLen = valueVarsStr.length;
656
828
  for (const idKey of idVarsStr) {
@@ -685,7 +857,7 @@ class DataFrame {
685
857
  }
686
858
  outSchema[varName] = datatypes_1.DataTypeRegistry.Utf8;
687
859
  outSchema[valueName] = (0, utils_2.inferColumnType)(newColumns[valueName]);
688
- return new DataFrame(newColumns, outSchema, newHeight);
860
+ return DataFrame._createDirect(newColumns, outSchema, newHeight);
689
861
  }
690
862
  vstack(other) {
691
863
  return this.concat(other, { how: "vertical" });
@@ -700,12 +872,16 @@ class DataFrame {
700
872
  if (typeof arg === "string") {
701
873
  exprs.push(new columnExpressions_1.ColumnExpr(arg));
702
874
  }
703
- else if ((0, utils_1.isObj)(arg) && 'evaluate' in arg) {
875
+ else if (columnExpressions_1.ColumnExpr.isColExpr(arg)) {
704
876
  exprs.push(arg);
705
877
  }
706
878
  else if ((0, utils_1.isObj)(arg)) {
707
- for (const [key, val] of Object.entries(arg)) {
708
- if ((0, utils_1.isObj)(val) && 'evaluate' in val) {
879
+ const keys = Object.keys(arg);
880
+ const numKeys = keys.length;
881
+ for (let i = 0; i < numKeys; i++) {
882
+ const key = keys[i];
883
+ const val = arg[key];
884
+ if (columnExpressions_1.ColumnExpr.isColExpr(val)) {
709
885
  exprs.push(val.alias(key));
710
886
  }
711
887
  else {
@@ -719,31 +895,96 @@ class DataFrame {
719
895
  return exprs;
720
896
  }
721
897
  with_columns(...args) {
898
+ if (args.length === 0)
899
+ return this;
722
900
  const exprs = this._normalizeArgs(args);
723
901
  const allKeys = Object.keys(this._columns);
724
- const expandedExprs = (0, columnExpressions_1.resolveColumnSelectors)(exprs, allKeys);
902
+ const expandedExprs = (0, columnExpressions_1.resolveColumnSelectors)(exprs, allKeys, undefined, this._schema, this._columns);
725
903
  const numEntries = expandedExprs.length;
726
- const newColumns = { ...this._columns };
727
- const outSchema = { ...this._schema };
904
+ if (numEntries === 0)
905
+ return this;
906
+ const overrides = new Map();
728
907
  for (let j = 0; j < numEntries; j++) {
729
908
  const expr = expandedExprs[j];
730
909
  const name = expr.outputName || expr.colName || columnExpressions_1.ALL_COLUMNS_MARKER;
731
- if (expr.isWindow) {
732
- newColumns[name] = (0, utils_2.resolveWindowExpr)(expr, this._columns, this._height);
910
+ overrides.set(name, expr);
911
+ }
912
+ const selectList = [];
913
+ const numKeys = allKeys.length;
914
+ for (let i = 0; i < numKeys; i++) {
915
+ const key = allKeys[i];
916
+ selectList.push(overrides.get(key) || new columnExpressions_1.ColumnExpr(key));
917
+ overrides.delete(key);
918
+ }
919
+ for (const expr of overrides.values()) {
920
+ selectList.push(expr);
921
+ }
922
+ return this.select(...selectList);
923
+ }
924
+ with_row_index(name = "index", offset = 0) {
925
+ const expr = (0, columnExpressions_1.seq_range)(offset, {
926
+ mode: "independent",
927
+ dtype: datatypes_1.DataTypeRegistry.UInt32,
928
+ step: 1
929
+ });
930
+ const df = this.insert_column(0, name, expr);
931
+ df._schema[name] = datatypes_1.DataTypeRegistry.UInt32;
932
+ return df;
933
+ }
934
+ write_json(file, { format = "json", replacerOptions } = {}) {
935
+ if (format !== "json" && format !== "ndjson") {
936
+ throw new TypeError(`Unsupported JSON format: "${format}". Expected "json" or "ndjson".`);
937
+ }
938
+ const safeReplacer = replacerOptions?.replacer === null
939
+ ? undefined
940
+ : (0, json_1.createSafeJsonReplacer)(replacerOptions);
941
+ let jsonStr;
942
+ if (format === "ndjson") {
943
+ const dicts = this.to_dicts();
944
+ const len = dicts.length;
945
+ const lines = new Array(len);
946
+ for (let i = 0; i < len; i++) {
947
+ lines[i] = JSON.stringify(dicts[i], safeReplacer);
733
948
  }
734
- else {
735
- newColumns[name] = expr.evaluate(this._columns, this._height);
949
+ jsonStr = lines.join(constants_1.NEWLINE);
950
+ }
951
+ else {
952
+ jsonStr = JSON.stringify(this.to_dicts(), safeReplacer);
953
+ }
954
+ (0, utils_2.writeStringToFileOrStream)(file, jsonStr);
955
+ return jsonStr;
956
+ }
957
+ write_csv(file, options = {}) {
958
+ if (file) {
959
+ if (typeof file === "string") {
960
+ const fs = require("fs");
961
+ const fd = fs.openSync(file, "w");
962
+ try {
963
+ (0, utils_1.stringifyCSV)(this._columns, this._height, {
964
+ ...options,
965
+ onRow: (str) => {
966
+ fs.writeSync(fd, str, null, "utf8");
967
+ }
968
+ });
969
+ }
970
+ finally {
971
+ fs.closeSync(fd);
972
+ }
736
973
  }
737
- const originalKey = expr.colName || name;
738
- const isPureColSelector = expr instanceof columnExpressions_1.ColumnExpr && expr.ops.length === 0 && !expr.isWindow && !expr.aggFn;
739
- if (isPureColSelector && this._schema[originalKey]) {
740
- outSchema[name] = this._schema[originalKey];
974
+ else if (typeof file === "object" && typeof file.write === "function") {
975
+ (0, utils_1.stringifyCSV)(this._columns, this._height, {
976
+ ...options,
977
+ onRow: (str) => {
978
+ file.write(str);
979
+ }
980
+ });
741
981
  }
742
982
  else {
743
- outSchema[name] = (0, utils_2.inferColumnType)(newColumns[name]);
983
+ throw new TypeError("Invalid file argument. Expected a file path string or a writable stream/object with a write method.");
744
984
  }
985
+ return "";
745
986
  }
746
- return new DataFrame(newColumns, outSchema, this._height);
987
+ return (0, utils_1.stringifyCSV)(this._columns, this._height, options);
747
988
  }
748
989
  }
749
990
  exports.DataFrame = DataFrame;