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.
- package/README.md +83 -34
- package/dist/api.d.ts +16 -8
- package/dist/api.js +11 -3
- package/dist/columnExpressions/ColumnExpr.d.ts +26 -364
- package/dist/columnExpressions/ColumnExpr.js +199 -3
- package/dist/columnExpressions/ExprBase.d.ts +8 -11
- package/dist/columnExpressions/ExprBase.js +20 -61
- package/dist/columnExpressions/constants.d.ts +2 -0
- package/dist/columnExpressions/constants.js +3 -1
- package/dist/columnExpressions/functions/coalesce.js +8 -4
- package/dist/columnExpressions/functions/element.d.ts +5 -0
- package/dist/columnExpressions/functions/element.js +11 -0
- package/dist/columnExpressions/functions/implode.d.ts +3 -0
- package/dist/columnExpressions/functions/implode.js +7 -0
- package/dist/columnExpressions/functions/lit.d.ts +3 -1
- package/dist/columnExpressions/functions/lit.js +8 -13
- package/dist/columnExpressions/functions/repeat.d.ts +47 -0
- package/dist/columnExpressions/functions/repeat.js +131 -0
- package/dist/columnExpressions/functions/seq_range.d.ts +31 -0
- package/dist/columnExpressions/functions/seq_range.js +91 -0
- package/dist/columnExpressions/functions/when.js +8 -4
- package/dist/columnExpressions/index.d.ts +5 -2
- package/dist/columnExpressions/index.js +5 -48
- package/dist/columnExpressions/mixins/AggregationExpr.d.ts +25 -50
- package/dist/columnExpressions/mixins/AggregationExpr.js +69 -165
- package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +41 -66
- package/dist/columnExpressions/mixins/ArithmeticExpr.js +126 -138
- package/dist/columnExpressions/mixins/BooleanExpr.d.ts +40 -0
- package/dist/columnExpressions/mixins/BooleanExpr.js +67 -0
- package/dist/columnExpressions/mixins/ComparisonExpr.d.ts +31 -60
- package/dist/columnExpressions/mixins/ComparisonExpr.js +231 -370
- package/dist/columnExpressions/mixins/ListExpr.d.ts +15 -39
- package/dist/columnExpressions/mixins/ListExpr.js +124 -148
- package/dist/columnExpressions/mixins/LogicalExpr.d.ts +7 -33
- package/dist/columnExpressions/mixins/LogicalExpr.js +48 -49
- package/dist/columnExpressions/mixins/ManipulationExpr.d.ts +6 -31
- package/dist/columnExpressions/mixins/ManipulationExpr.js +61 -25
- package/dist/columnExpressions/mixins/NumericExpr.d.ts +92 -0
- package/dist/columnExpressions/mixins/NumericExpr.js +259 -0
- package/dist/columnExpressions/mixins/StringExpr.d.ts +5 -30
- package/dist/columnExpressions/mixins/StringExpr.js +37 -49
- package/dist/columnExpressions/mixins/StructExpr.d.ts +16 -0
- package/dist/columnExpressions/mixins/StructExpr.js +139 -0
- package/dist/columnExpressions/mixins/TemporalExpr.d.ts +4 -30
- package/dist/columnExpressions/mixins/TemporalExpr.js +28 -29
- package/dist/columnExpressions/mixins/WindowExpr.d.ts +27 -49
- package/dist/columnExpressions/mixins/WindowExpr.js +144 -274
- package/dist/columnExpressions/utils.d.ts +4 -0
- package/dist/columnExpressions/utils.js +45 -0
- package/dist/dataframe/constants.d.ts +3 -0
- package/dist/dataframe/constants.js +4 -1
- package/dist/dataframe/dataframe.d.ts +27 -10
- package/dist/dataframe/dataframe.js +461 -220
- package/dist/dataframe/grouped/grouped.d.ts +2 -3
- package/dist/dataframe/grouped/grouped.js +17 -16
- package/dist/dataframe/types.d.ts +65 -1
- package/dist/dataframe/utils.d.ts +11 -3
- package/dist/dataframe/utils.js +101 -9
- package/dist/datatypes/DataType.d.ts +2 -1
- package/dist/datatypes/DataType.js +29 -0
- package/dist/datatypes/index.d.ts +2 -2
- package/dist/datatypes/types.d.ts +37 -36
- package/dist/datatypes/types.js +15 -11
- package/dist/exceptions/index.d.ts +2 -0
- package/dist/exceptions/index.js +4 -1
- package/dist/exceptions/utils.d.ts +1 -0
- package/dist/exceptions/utils.js +19 -0
- package/dist/functions/concat.d.ts +1 -2
- package/dist/functions/concat.js +24 -12
- package/dist/functions/index.d.ts +3 -1
- package/dist/functions/index.js +7 -15
- package/dist/functions/read_csv.d.ts +8 -0
- package/dist/functions/read_csv.js +53 -0
- package/dist/functions/read_json.d.ts +10 -0
- package/dist/functions/read_json.js +21 -0
- package/dist/functions/transpose.d.ts +7 -0
- package/dist/functions/transpose.js +84 -0
- package/dist/index.js +6 -1
- package/dist/types.d.ts +31 -5
- package/dist/utils/csv.d.ts +77 -0
- package/dist/utils/csv.js +313 -0
- package/dist/utils/date.js +5 -6
- package/dist/utils/guards.d.ts +0 -2
- package/dist/utils/guards.js +0 -31
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/json.d.ts +120 -2
- package/dist/utils/json.js +204 -20
- package/dist/utils/list.d.ts +173 -1
- package/dist/utils/list.js +255 -22
- package/dist/utils/number.d.ts +61 -28
- package/dist/utils/number.js +248 -70
- package/dist/utils/string.d.ts +5 -0
- package/dist/utils/string.js +89 -0
- 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 =
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
236
|
-
for (
|
|
237
|
-
const keyStr =
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
256
|
-
if (val == null)
|
|
330
|
+
if (columns[joinKeysStr[i]][idx] == null)
|
|
257
331
|
return null;
|
|
258
|
-
vals[i] = String(val);
|
|
259
332
|
}
|
|
260
|
-
return
|
|
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
|
|
432
|
+
return DataFrame._createDirect(newColumns, outSchema, outHeight);
|
|
360
433
|
}
|
|
361
|
-
limit(n,
|
|
362
|
-
const { offset = 0, from = "start" } = options;
|
|
434
|
+
limit(n, { offset = 0, from = "start" } = {}) {
|
|
363
435
|
const len = this._height;
|
|
364
|
-
const safeN =
|
|
365
|
-
const safeOffset =
|
|
366
|
-
|
|
367
|
-
|
|
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 =
|
|
441
|
+
actualEnd = len - safeOffset;
|
|
379
442
|
actualStart = Math.max(actualEnd - safeN, 0);
|
|
380
443
|
}
|
|
381
|
-
|
|
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
|
-
|
|
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
|
|
452
|
+
return DataFrame._createDirect(newColumns, this._schema, newHeight);
|
|
391
453
|
}
|
|
392
454
|
pivot(config) {
|
|
393
455
|
if (this._height === 0)
|
|
394
|
-
return
|
|
456
|
+
return DataFrame._createDirect({}, {}, 0);
|
|
395
457
|
const { index, columns, values } = config;
|
|
396
|
-
const
|
|
397
|
-
const indexLen =
|
|
398
|
-
|
|
399
|
-
|
|
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"
|
|
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
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
|
482
|
+
const indexColsDict = {};
|
|
432
483
|
const outSchema = {};
|
|
433
484
|
for (let j = 0; j < indexLen; j++) {
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
if (this._schema[
|
|
437
|
-
outSchema[
|
|
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
|
|
448
|
-
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
555
|
+
if (selectedKeys.has(targetKey)) {
|
|
504
556
|
throw new exceptions_1.DataFrameError(`Duplicate column selection: "${targetKey}" is selected multiple times.`);
|
|
505
557
|
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
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
|
|
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
|
|
536
|
-
if (
|
|
537
|
-
(0, exceptions_1.assertColumnExists)(
|
|
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
|
|
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
|
|
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
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
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
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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.
|
|
653
|
-
const valueVarsStr = (0, utils_1.
|
|
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
|
|
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 (
|
|
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
|
-
|
|
708
|
-
|
|
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
|
-
|
|
727
|
-
|
|
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
|
-
|
|
732
|
-
|
|
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
|
-
|
|
735
|
-
|
|
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
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
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
|
-
|
|
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
|
|
987
|
+
return (0, utils_1.stringifyCSV)(this._columns, this._height, options);
|
|
747
988
|
}
|
|
748
989
|
}
|
|
749
990
|
exports.DataFrame = DataFrame;
|