mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-29 04:08:12 +08:00
* Added TS. Updated build and linting config. Added types. * [ts-migrate][.] Rename files from JS/JSX to TS/TSX Co-authored-by: ts-migrate <> * [ts-migrate][.] Run TS Migrate Co-authored-by: ts-migrate <> * Corrected files mangled by ts-migrate. * Updated lint config, minor linting. * Re-enabled Husky. * Updated tests and config. * Reverted webpack devtool config. * Removed obsolete snapshots. * Added annotations snap. * Updated tsconfig includes wrt linting. * Removed ts-migrate. Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>
This commit is contained in:
co-authored by
ts-migrate
Timmy Huang
parent
7328cbdbd5
commit
934cc5c69b
@@ -11,12 +11,12 @@ objects.
|
||||
|
||||
import { memoize } from "./util";
|
||||
|
||||
function hashDataframe(df) {
|
||||
function hashDataframe(df: any) {
|
||||
if (df.isEmpty()) return "";
|
||||
return df.__columnsAccessor.map((c) => c.__id).join(",");
|
||||
return df.__columnsAccessor.map((c: any) => c.__id).join(",");
|
||||
}
|
||||
|
||||
function noop(df) {
|
||||
function noop(df: any) {
|
||||
return df;
|
||||
}
|
||||
|
||||
@@ -73,13 +73,26 @@ Dataframe
|
||||
**/
|
||||
|
||||
class Dataframe {
|
||||
__columns: any;
|
||||
|
||||
__columnsAccessor: any;
|
||||
|
||||
__id: any;
|
||||
|
||||
colIndex: any;
|
||||
|
||||
dims: any;
|
||||
|
||||
length: any;
|
||||
|
||||
rowIndex: any;
|
||||
/**
|
||||
Constructors & factories
|
||||
**/
|
||||
|
||||
constructor(
|
||||
dims,
|
||||
columnarData,
|
||||
dims: any,
|
||||
columnarData: any,
|
||||
rowIndex = null,
|
||||
colIndex = null,
|
||||
__columnsAccessor = [] // private interface
|
||||
@@ -104,9 +117,11 @@ class Dataframe {
|
||||
throw new RangeError("Dataframe dimensions must be positive");
|
||||
}
|
||||
if (!rowIndex) {
|
||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'IdentityInt32Index' is not assignable to typ... Remove this comment to see the full error message
|
||||
rowIndex = new IdentityInt32Index(nRows);
|
||||
}
|
||||
if (!colIndex) {
|
||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'IdentityInt32Index' is not assignable to typ... Remove this comment to see the full error message
|
||||
colIndex = new IdentityInt32Index(nCols);
|
||||
}
|
||||
Dataframe.__errorChecks(dims, columnarData, rowIndex, colIndex);
|
||||
@@ -122,7 +137,12 @@ class Dataframe {
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
static __errorChecks(dims, columnarData, rowIndex, colIndex) {
|
||||
static __errorChecks(
|
||||
dims: any,
|
||||
columnarData: any,
|
||||
rowIndex: any,
|
||||
colIndex: any
|
||||
) {
|
||||
const [nRows, nCols] = dims;
|
||||
|
||||
/* check for expected types */
|
||||
@@ -160,7 +180,7 @@ class Dataframe {
|
||||
}
|
||||
}
|
||||
|
||||
static __compileColumn(column, getRowByOffset, getRowByLabel) {
|
||||
static __compileColumn(column: any, getRowByOffset: any, getRowByLabel: any) {
|
||||
/*
|
||||
Each column accessor is a function which will lookup data by
|
||||
index (ie, is equivalent to dataframe.get(row, col), where 'col'
|
||||
@@ -195,12 +215,12 @@ class Dataframe {
|
||||
const __id = __getMemoId();
|
||||
|
||||
/* get value by row label */
|
||||
const get = function get(rlabel) {
|
||||
const get = function get(rlabel: any) {
|
||||
return column[getRowByOffset(rlabel)];
|
||||
};
|
||||
|
||||
/* get value by row offset */
|
||||
const iget = function iget(roffset) {
|
||||
const iget = function iget(roffset: any) {
|
||||
return column[roffset];
|
||||
};
|
||||
|
||||
@@ -210,12 +230,12 @@ class Dataframe {
|
||||
};
|
||||
|
||||
/* test for row label inclusion in column */
|
||||
const has = function has(rlabel) {
|
||||
const has = function has(rlabel: any) {
|
||||
const offset = getRowByOffset(rlabel);
|
||||
return offset >= 0 && offset < length;
|
||||
};
|
||||
|
||||
const ihas = function ihas(offset) {
|
||||
const ihas = function ihas(offset: any) {
|
||||
return offset >= 0 && offset < length;
|
||||
};
|
||||
|
||||
@@ -226,7 +246,7 @@ class Dataframe {
|
||||
NOTE: not found return is DIFFERENT than the default Array.indexOf as
|
||||
-1 is a plausible Dataframe row/col label.
|
||||
*/
|
||||
const indexOf = function indexOf(value) {
|
||||
const indexOf = function indexOf(value: any) {
|
||||
const offset = column.indexOf(value);
|
||||
if (offset === -1) {
|
||||
return undefined;
|
||||
@@ -250,11 +270,12 @@ class Dataframe {
|
||||
Create histogram bins for this column. Memoized.
|
||||
*/
|
||||
const _memoHistoCat = memoize(_histogramCategorical, hashCategorical);
|
||||
const histogramCategorical = (by) => _memoHistoCat(get, by);
|
||||
const histogramCategorical = (by: any) => _memoHistoCat(get, by);
|
||||
let histogram = null;
|
||||
if (isTypedArray(column)) {
|
||||
const mFn = memoize(histogramContinuous, hashContinuous);
|
||||
histogram = (bins, domain, by) => mFn(get, bins, domain, by);
|
||||
histogram = (bins: any, domain: any, by: any) =>
|
||||
mFn(get, bins, domain, by);
|
||||
} else {
|
||||
histogram = histogramCategorical;
|
||||
}
|
||||
@@ -274,7 +295,7 @@ class Dataframe {
|
||||
return get;
|
||||
}
|
||||
|
||||
__compile(accessors) {
|
||||
__compile(accessors: any) {
|
||||
/*
|
||||
Compile data accessors for each column.
|
||||
|
||||
@@ -282,7 +303,7 @@ class Dataframe {
|
||||
*/
|
||||
const getRowByOffset = this.rowIndex.getOffset.bind(this.rowIndex);
|
||||
const getRowByLabel = this.rowIndex.getLabel.bind(this.rowIndex);
|
||||
this.__columnsAccessor = this.__columns.map((column, idx) => {
|
||||
this.__columnsAccessor = this.__columns.map((column: any, idx: any) => {
|
||||
if (accessors[idx]) {
|
||||
return accessors[idx];
|
||||
}
|
||||
@@ -295,6 +316,7 @@ class Dataframe {
|
||||
/*
|
||||
Clone this dataframe
|
||||
*/
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
[...this.__columns],
|
||||
@@ -304,7 +326,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
withCol(label, colData, withRowIndex = null) {
|
||||
withCol(label: any, colData: any, withRowIndex = null) {
|
||||
/*
|
||||
Create a new DF, which is `this` plus the new column. Example:
|
||||
const newDf = df.withCol("foo", [1,2,3]);
|
||||
@@ -337,6 +359,7 @@ class Dataframe {
|
||||
columns.push(colData);
|
||||
const colIndex = this.colIndex.withLabel(label);
|
||||
const columnsAccessor = [...this.__columnsAccessor];
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
dims,
|
||||
columns,
|
||||
@@ -346,7 +369,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
withColsFrom(dataframe, labels) {
|
||||
withColsFrom(dataframe: any, labels: any) {
|
||||
/*
|
||||
return a new dataframe containing all columns from both `this` and the
|
||||
provided dataframe argument.
|
||||
@@ -410,7 +433,9 @@ class Dataframe {
|
||||
|
||||
// otherwise, bulid a new dataframe combining columns from both
|
||||
|
||||
const srcOffsets = srcLabels.map((l) => dataframe.colIndex.getOffset(l));
|
||||
const srcOffsets = srcLabels.map((l: any) =>
|
||||
dataframe.colIndex.getOffset(l)
|
||||
);
|
||||
|
||||
// check for label collisions
|
||||
if (dstLabels.some(this.hasCol, this)) {
|
||||
@@ -422,14 +447,15 @@ class Dataframe {
|
||||
const { rowIndex } = this;
|
||||
const columns = [
|
||||
...this.__columns,
|
||||
...srcOffsets.map((i) => dataframe.__columns[i]),
|
||||
...srcOffsets.map((i: any) => dataframe.__columns[i]),
|
||||
];
|
||||
const colIndex = this.colIndex.withLabels(dstLabels);
|
||||
const columnsAccessor = [
|
||||
...this.__columnsAccessor,
|
||||
...srcOffsets.map((i) => dataframe.__columnsAccessor[i]),
|
||||
...srcOffsets.map((i: any) => dataframe.__columnsAccessor[i]),
|
||||
];
|
||||
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
dims,
|
||||
columns,
|
||||
@@ -441,10 +467,11 @@ class Dataframe {
|
||||
|
||||
withColsFromAll(dataframes = []) {
|
||||
dataframes = Array.isArray(dataframes) ? dataframes : [dataframes];
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
return dataframes.reduce((acc, df) => acc.withColsFrom(df), this);
|
||||
}
|
||||
|
||||
dropCol(label) {
|
||||
dropCol(label: any) {
|
||||
/*
|
||||
Create a new dataframe, omitting one columns.
|
||||
|
||||
@@ -470,6 +497,7 @@ class Dataframe {
|
||||
const colIndex = this.colIndex.dropLabel(label);
|
||||
const columnsAccessor = [...this.__columnsAccessor];
|
||||
columnsAccessor.splice(coffset, 1);
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
dims,
|
||||
columns,
|
||||
@@ -479,7 +507,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
renameCol(oldLabel, newLabel) {
|
||||
renameCol(oldLabel: any, newLabel: any) {
|
||||
/*
|
||||
Accelerator for dropping a column and then adding it again with a new label
|
||||
*/
|
||||
@@ -494,6 +522,7 @@ class Dataframe {
|
||||
columnsAccessor.push(columnsAccessor[coffset]);
|
||||
columnsAccessor.splice(coffset, 1);
|
||||
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
columns,
|
||||
@@ -503,7 +532,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
replaceColData(label, newColData) {
|
||||
replaceColData(label: any, newColData: any) {
|
||||
/*
|
||||
Accelerator for dropping a column then adding it again with same
|
||||
label and different values.
|
||||
@@ -514,6 +543,7 @@ class Dataframe {
|
||||
const columnsAccessor = [...this.__columnsAccessor];
|
||||
columnsAccessor[coffset] = null;
|
||||
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
columns,
|
||||
@@ -525,14 +555,16 @@ class Dataframe {
|
||||
|
||||
static empty(rowIndex = null, colIndex = null) {
|
||||
const dims = [
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
rowIndex ? rowIndex.size() : 0,
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
colIndex ? colIndex.size() : 0,
|
||||
];
|
||||
if (dims[0] && dims[1]) throw new Error("not an empty dataframe");
|
||||
return new Dataframe(dims, new Array(dims[1]), rowIndex, colIndex);
|
||||
}
|
||||
|
||||
static create(dims, columnarData) {
|
||||
static create(dims: any, columnarData: any) {
|
||||
/*
|
||||
Create a dataframe from raw columnar data. All column arrays
|
||||
must have the same length. Identity indexing will be used.
|
||||
@@ -543,7 +575,7 @@ class Dataframe {
|
||||
return new Dataframe(dims, columnarData, null, null);
|
||||
}
|
||||
|
||||
__subset(newRowIndex, newColIndex) {
|
||||
__subset(newRowIndex: any, newColIndex: any) {
|
||||
const dims = [...this.dims];
|
||||
|
||||
/* subset columns */
|
||||
@@ -563,7 +595,7 @@ class Dataframe {
|
||||
let { rowIndex } = this;
|
||||
if (newRowIndex) {
|
||||
const rowOffsets = this.rowIndex.getOffsets(newRowIndex.labels());
|
||||
__columns = __columns.map((col) => {
|
||||
__columns = __columns.map((col: any) => {
|
||||
const newCol = new col.constructor(rowOffsets.length);
|
||||
for (let i = 0, l = rowOffsets.length; i < l; i += 1) {
|
||||
newCol[i] = col[rowOffsets[i]];
|
||||
@@ -585,7 +617,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
subset(rowLabels, colLabels = null, withRowIndex = null) {
|
||||
subset(rowLabels: any, colLabels = null, withRowIndex = null) {
|
||||
/*
|
||||
Subset by row/col labels.
|
||||
|
||||
@@ -607,7 +639,7 @@ class Dataframe {
|
||||
return this.__subset(rowIndex, colIndex);
|
||||
}
|
||||
|
||||
isubset(rowOffsets, colOffsets = null, withRowIndex = null) {
|
||||
isubset(rowOffsets: any, colOffsets = null, withRowIndex = null) {
|
||||
/*
|
||||
Subset by row/col offset.
|
||||
|
||||
@@ -631,7 +663,7 @@ class Dataframe {
|
||||
return this.__subset(rowIndex, colIndex);
|
||||
}
|
||||
|
||||
isubsetMask(rowMask, colMask = null, withRowIndex = null) {
|
||||
isubsetMask(rowMask: any, colMask = null, withRowIndex = null) {
|
||||
/*
|
||||
Subset on row/column based upon a truthy/falsey array (a mask).
|
||||
|
||||
@@ -643,13 +675,14 @@ class Dataframe {
|
||||
const [nRows, nCols] = this.dims;
|
||||
if (
|
||||
(rowMask && rowMask.length !== nRows) ||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
(colMask && colMask.length !== nCols)
|
||||
) {
|
||||
throw new RangeError("boolean arrays must match row/col dimensions");
|
||||
}
|
||||
|
||||
/* convert masks to lists - method wastes space, but is fast */
|
||||
const toList = (mask, maxSize) => {
|
||||
const toList = (mask: any, maxSize: any) => {
|
||||
if (!mask) {
|
||||
return null;
|
||||
}
|
||||
@@ -665,6 +698,7 @@ class Dataframe {
|
||||
};
|
||||
const rowOffsets = toList(rowMask, nRows);
|
||||
const colOffsets = toList(colMask, nCols);
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'Int32Array | null' is not assign... Remove this comment to see the full error message
|
||||
return this.isubset(rowOffsets, colOffsets, withRowIndex);
|
||||
}
|
||||
|
||||
@@ -677,7 +711,7 @@ class Dataframe {
|
||||
return [...this.__columnsAccessor];
|
||||
}
|
||||
|
||||
col(columnLabel) {
|
||||
col(columnLabel: any) {
|
||||
/*
|
||||
Return accessor bound to a column. Allows random row access
|
||||
based upon the row indexing. Returns undefined if the
|
||||
@@ -697,7 +731,7 @@ class Dataframe {
|
||||
return this.__columnsAccessor[coff];
|
||||
}
|
||||
|
||||
icol(columnOffset) {
|
||||
icol(columnOffset: any) {
|
||||
/*
|
||||
Return column accessor by offset.
|
||||
*/
|
||||
@@ -706,7 +740,7 @@ class Dataframe {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
at(r, c) {
|
||||
at(r: any, c: any) {
|
||||
/*
|
||||
Access a single value, for a row/col label pair.
|
||||
|
||||
@@ -723,7 +757,7 @@ class Dataframe {
|
||||
return this.__columns[coff][roff];
|
||||
}
|
||||
|
||||
iat(r, c) {
|
||||
iat(r: any, c: any) {
|
||||
/*
|
||||
Access a single value, for a row/col offset (integer) position.
|
||||
|
||||
@@ -736,7 +770,7 @@ class Dataframe {
|
||||
return this.__columns[c][r];
|
||||
}
|
||||
|
||||
has(r, c) {
|
||||
has(r: any, c: any) {
|
||||
/*
|
||||
Test if row/col labels exist in the dataframe - returns true/false
|
||||
*/
|
||||
@@ -746,7 +780,7 @@ class Dataframe {
|
||||
return coff >= 0 && coff < nCols && roff >= 0 && roff < nRows;
|
||||
}
|
||||
|
||||
ihas(r, c) {
|
||||
ihas(r: any, c: any) {
|
||||
/*
|
||||
Test if row/col offset (integer) position exists in the
|
||||
dataframe - returns true/false
|
||||
@@ -762,7 +796,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
hasCol(c) {
|
||||
hasCol(c: any) {
|
||||
/*
|
||||
Test if col label exists - return true/false
|
||||
*/
|
||||
@@ -784,19 +818,20 @@ class Dataframe {
|
||||
add these as useful.
|
||||
****/
|
||||
|
||||
mapColumns(callback) {
|
||||
mapColumns(callback: any) {
|
||||
/*
|
||||
map all columns in the dataframe, returning a new dataframe comprised of the
|
||||
return values, with the same index as the original dataframe.
|
||||
|
||||
callback MUST not modify the column, but instead return a mutated copy.
|
||||
*/
|
||||
const columns = this.__columns.map((colData, colIdx) =>
|
||||
const columns = this.__columns.map((colData: any, colIdx: any) =>
|
||||
callback(colData, colIdx, this)
|
||||
);
|
||||
const columnsAccessor = columns.map((c, idx) =>
|
||||
const columnsAccessor = columns.map((c: any, idx: any) =>
|
||||
this.__columns[idx] === c ? this.__columnsAccessor[idx] : undefined
|
||||
);
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
columns,
|
||||
@@ -3,7 +3,7 @@ Dataframe histogram
|
||||
*/
|
||||
import { isTypedArray } from "./util";
|
||||
|
||||
function _histogramContinuous(column, bins, min, max) {
|
||||
function _histogramContinuous(column: any, bins: any, min: any, max: any) {
|
||||
const valBins = new Array(bins).fill(0);
|
||||
if (!column) {
|
||||
return valBins;
|
||||
@@ -21,7 +21,13 @@ function _histogramContinuous(column, bins, min, max) {
|
||||
return valBins;
|
||||
}
|
||||
|
||||
function _histogramContinuousBy(column, bins, min, max, by) {
|
||||
function _histogramContinuousBy(
|
||||
column: any,
|
||||
bins: any,
|
||||
min: any,
|
||||
max: any,
|
||||
by: any
|
||||
) {
|
||||
const byMap = new Map();
|
||||
if (!column || !by) {
|
||||
return byMap;
|
||||
@@ -46,7 +52,7 @@ function _histogramContinuousBy(column, bins, min, max, by) {
|
||||
return byMap;
|
||||
}
|
||||
|
||||
function _histogramCategorical(column) {
|
||||
function _histogramCategorical(column: any) {
|
||||
const valMap = new Map();
|
||||
if (!column) {
|
||||
return valMap;
|
||||
@@ -63,7 +69,7 @@ function _histogramCategorical(column) {
|
||||
return valMap;
|
||||
}
|
||||
|
||||
function _histogramCategoricalBy(column, by) {
|
||||
function _histogramCategoricalBy(column: any, by: any) {
|
||||
const byMap = new Map();
|
||||
if (!column || !by) {
|
||||
return byMap;
|
||||
@@ -90,7 +96,7 @@ function _histogramCategoricalBy(column, by) {
|
||||
/*
|
||||
Count category occupancy. Optional group-by category.
|
||||
*/
|
||||
export function histogramCategorical(column, by) {
|
||||
export function histogramCategorical(column: any, by: any) {
|
||||
if (by && isTypedArray(by)) {
|
||||
throw new Error("Group by column must be categorical");
|
||||
}
|
||||
@@ -102,7 +108,7 @@ export function histogramCategorical(column, by) {
|
||||
/*
|
||||
Memoization hash for histogramCategorical()
|
||||
*/
|
||||
export function hashCategorical(column, by) {
|
||||
export function hashCategorical(column: any, by: any) {
|
||||
if (by) {
|
||||
return `${column.__id}:${by.__id}`;
|
||||
}
|
||||
@@ -113,7 +119,12 @@ export function hashCategorical(column, by) {
|
||||
Bin counts for continuous/scalar values, with optional group-by category.
|
||||
Values outside domain are ignored.
|
||||
*/
|
||||
export function histogramContinuous(column, bins = 40, domain = [0, 1], by) {
|
||||
export function histogramContinuous(
|
||||
column: any,
|
||||
bins = 40,
|
||||
domain = [0, 1],
|
||||
by: any
|
||||
) {
|
||||
if (by && isTypedArray(by)) {
|
||||
throw new Error("Group by column must be categorical");
|
||||
}
|
||||
@@ -126,7 +137,12 @@ export function histogramContinuous(column, bins = 40, domain = [0, 1], by) {
|
||||
/*
|
||||
Memoization hash for histogramContinuous
|
||||
*/
|
||||
export function hashContinuous(column, bins = "", domain = [0, 0], by) {
|
||||
export function hashContinuous(
|
||||
column: any,
|
||||
bins = "",
|
||||
domain = [0, 0],
|
||||
by: any
|
||||
) {
|
||||
const [min, max] = domain;
|
||||
if (by) {
|
||||
return `${column.__id}:${bins}:${min}:${max}:${by.__id}`;
|
||||
@@ -10,7 +10,7 @@ import { __getMemoId } from "./util";
|
||||
/*
|
||||
Private utility functions
|
||||
*/
|
||||
function extent(tarr) {
|
||||
function extent(tarr: any) {
|
||||
let min = 0x7fffffff;
|
||||
let max = ~min; // eslint-disable-line no-bitwise -- Establishes 0 of same size
|
||||
for (let i = 0, l = tarr.length; i < l; i += 1) {
|
||||
@@ -26,10 +26,12 @@ function extent(tarr) {
|
||||
}
|
||||
|
||||
class IdentityInt32Index {
|
||||
maxOffset: any;
|
||||
|
||||
/*
|
||||
identity/noop index, with small assumptions that labels are int32
|
||||
*/
|
||||
constructor(maxOffset) {
|
||||
constructor(maxOffset: any) {
|
||||
this.maxOffset = maxOffset;
|
||||
}
|
||||
|
||||
@@ -46,31 +48,31 @@ class IdentityInt32Index {
|
||||
return k;
|
||||
}
|
||||
|
||||
getOffset(i) {
|
||||
getOffset(i: any) {
|
||||
// label to offset
|
||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
||||
}
|
||||
|
||||
getOffsets(arr) {
|
||||
getOffsets(arr: any) {
|
||||
// labels to offsets
|
||||
return arr.map((i) => this.getOffset(i));
|
||||
return arr.map((i: any) => this.getOffset(i));
|
||||
}
|
||||
|
||||
getLabel(i) {
|
||||
getLabel(i: any) {
|
||||
// offset to label
|
||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
||||
}
|
||||
|
||||
getLabels(arr) {
|
||||
getLabels(arr: any) {
|
||||
// offsets to labels
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
return arr.map((i: any) => this.getLabel(i));
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.maxOffset;
|
||||
}
|
||||
|
||||
__promote(labelArray) {
|
||||
__promote(labelArray: any) {
|
||||
/*
|
||||
time/space decision - based on the resulting density
|
||||
*/
|
||||
@@ -84,10 +86,11 @@ class IdentityInt32Index {
|
||||
if (density < 0.1) {
|
||||
return new KeyIndex(labelArray);
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number[]' is not assignable to p... Remove this comment to see the full error message
|
||||
return new DenseInt32Index(labelArray, [minLabel, maxLabel]);
|
||||
}
|
||||
|
||||
subset(labels) {
|
||||
subset(labels: any) {
|
||||
/* validate subset */
|
||||
const { maxOffset } = this;
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
@@ -99,12 +102,12 @@ class IdentityInt32Index {
|
||||
}
|
||||
|
||||
/* identity index - labels are offsets */
|
||||
isubset(offsets) {
|
||||
isubset(offsets: any) {
|
||||
return this.subset(offsets);
|
||||
}
|
||||
|
||||
/* identity index - labels are offsets */
|
||||
isubsetMask(mask) {
|
||||
isubsetMask(mask: any) {
|
||||
let count = 0;
|
||||
if (mask.length !== this.maxOffset) {
|
||||
throw new RangeError("mask has invalid length for index");
|
||||
@@ -120,18 +123,18 @@ class IdentityInt32Index {
|
||||
return this.subset(labels);
|
||||
}
|
||||
|
||||
withLabel(label) {
|
||||
withLabel(label: any) {
|
||||
if (label === this.maxOffset) {
|
||||
return new IdentityInt32Index(label + 1);
|
||||
}
|
||||
return this.__promote([...this.labels(), label]);
|
||||
}
|
||||
|
||||
withLabels(labels) {
|
||||
withLabels(labels: any) {
|
||||
return this.__promote([...this.labels(), ...labels]);
|
||||
}
|
||||
|
||||
dropLabel(label) {
|
||||
dropLabel(label: any) {
|
||||
if (label === this.maxOffset - 1) {
|
||||
return new IdentityInt32Index(label);
|
||||
}
|
||||
@@ -142,20 +145,38 @@ class IdentityInt32Index {
|
||||
}
|
||||
|
||||
class DenseInt32Index {
|
||||
__id: any;
|
||||
|
||||
getLabel: any;
|
||||
|
||||
getLabels: any;
|
||||
|
||||
getOffset: any;
|
||||
|
||||
getOffsets: any;
|
||||
|
||||
index: any;
|
||||
|
||||
minLabel: any;
|
||||
|
||||
rindex: any;
|
||||
|
||||
/*
|
||||
DenseInt32Index indexes integer labels, and uses Int32Array typed arrays
|
||||
for both forward and reverse indexing. This means that the min/max range
|
||||
of the forward index labels must be known a priori (so that the index
|
||||
array can be pre-allocated).
|
||||
*/
|
||||
constructor(labels, labelRange = null) {
|
||||
constructor(labels: any, labelRange = null) {
|
||||
if (labels.constructor !== Int32Array) {
|
||||
labels = new Int32Array(labels);
|
||||
}
|
||||
|
||||
if (!labelRange) {
|
||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'number[]' is not assignable to type 'null'.
|
||||
labelRange = extent(labels);
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2488) FIXME: Type 'null' must have a '[Symbol.iterator]()' meth... Remove this comment to see the full error message
|
||||
const [minLabel, maxLabel] = labelRange;
|
||||
const labelSpaceSize = maxLabel - minLabel + 1;
|
||||
const index = new Int32Array(labelSpaceSize).fill(-1);
|
||||
@@ -173,22 +194,22 @@ class DenseInt32Index {
|
||||
|
||||
__compile() {
|
||||
const { minLabel, index, rindex } = this;
|
||||
this.getOffset = function getOffset(l) {
|
||||
this.getOffset = function getOffset(l: any) {
|
||||
if (!Number.isInteger(l)) return undefined;
|
||||
const offset = index[l - minLabel];
|
||||
return offset === -1 ? undefined : offset;
|
||||
};
|
||||
|
||||
this.getOffsets = function getOffsets(arr) {
|
||||
return arr.map((i) => this.getOffset(i));
|
||||
this.getOffsets = function getOffsets(arr: any) {
|
||||
return arr.map((i: any) => this.getOffset(i));
|
||||
};
|
||||
|
||||
this.getLabel = function getLabel(i) {
|
||||
this.getLabel = function getLabel(i: any) {
|
||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
||||
};
|
||||
|
||||
this.getLabels = function getLabels(arr) {
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
this.getLabels = function getLabels(arr: any) {
|
||||
return arr.map((i: any) => this.getLabel(i));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -200,7 +221,7 @@ class DenseInt32Index {
|
||||
return this.rindex.length;
|
||||
}
|
||||
|
||||
__promote(labelArray) {
|
||||
__promote(labelArray: any) {
|
||||
/*
|
||||
time/space decision - if we are going to use less than 10% of the
|
||||
dense index space, switch to a KeyIndex (which is slower, but uses
|
||||
@@ -213,10 +234,11 @@ class DenseInt32Index {
|
||||
if (density < 0.1) {
|
||||
return new KeyIndex(labelArray);
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number[]' is not assignable to p... Remove this comment to see the full error message
|
||||
return new DenseInt32Index(labelArray, [minLabel, maxLabel]);
|
||||
}
|
||||
|
||||
subset(labels) {
|
||||
subset(labels: any) {
|
||||
/* validate subset */
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
const label = labels[i];
|
||||
@@ -227,7 +249,7 @@ class DenseInt32Index {
|
||||
return this.__promote(labels);
|
||||
}
|
||||
|
||||
isubset(offsets) {
|
||||
isubset(offsets: any) {
|
||||
/* validate subset */
|
||||
const { rindex } = this;
|
||||
const maxOffset = rindex.length;
|
||||
@@ -241,7 +263,7 @@ class DenseInt32Index {
|
||||
return this.__promote(labels);
|
||||
}
|
||||
|
||||
isubsetMask(mask) {
|
||||
isubsetMask(mask: any) {
|
||||
const { rindex } = this;
|
||||
if (mask.length !== rindex.length)
|
||||
throw new RangeError("mask has invalid length for index");
|
||||
@@ -257,15 +279,15 @@ class DenseInt32Index {
|
||||
return this.__promote(labels);
|
||||
}
|
||||
|
||||
withLabel(label) {
|
||||
withLabel(label: any) {
|
||||
return this.__promote([...this.labels(), label]);
|
||||
}
|
||||
|
||||
withLabels(labels) {
|
||||
withLabels(labels: any) {
|
||||
return this.__promote([...this.labels(), ...labels]);
|
||||
}
|
||||
|
||||
dropLabel(label) {
|
||||
dropLabel(label: any) {
|
||||
const labelArray = [...this.labels()];
|
||||
labelArray.splice(labelArray.indexOf(label), 1);
|
||||
return this.__promote(labelArray);
|
||||
@@ -273,17 +295,31 @@ class DenseInt32Index {
|
||||
}
|
||||
|
||||
class KeyIndex {
|
||||
__id: any;
|
||||
|
||||
getLabel: any;
|
||||
|
||||
getLabels: any;
|
||||
|
||||
getOffset: any;
|
||||
|
||||
getOffsets: any;
|
||||
|
||||
index: any;
|
||||
|
||||
rindex: any;
|
||||
|
||||
/*
|
||||
KeyIndex indexes arbitrary JS primitive types, and uses a Map()
|
||||
as its core data structure.
|
||||
*/
|
||||
constructor(labels) {
|
||||
constructor(labels: any) {
|
||||
const index = new Map();
|
||||
if (labels === undefined) {
|
||||
labels = [];
|
||||
}
|
||||
const rindex = labels;
|
||||
labels.forEach((v, i) => {
|
||||
labels.forEach((v: any, i: any) => {
|
||||
index.set(v, i);
|
||||
});
|
||||
|
||||
@@ -300,20 +336,20 @@ class KeyIndex {
|
||||
|
||||
__compile() {
|
||||
const { index, rindex } = this;
|
||||
this.getOffset = function getOffset(k) {
|
||||
this.getOffset = function getOffset(k: any) {
|
||||
return index.get(k);
|
||||
};
|
||||
|
||||
this.getOffsets = function getOffsets(arr) {
|
||||
return arr.map((l) => this.getOffset(l));
|
||||
this.getOffsets = function getOffsets(arr: any) {
|
||||
return arr.map((l: any) => this.getOffset(l));
|
||||
};
|
||||
|
||||
this.getLabel = function getLabel(i) {
|
||||
this.getLabel = function getLabel(i: any) {
|
||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
||||
};
|
||||
|
||||
this.getLabels = function getLabels(arr) {
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
this.getLabels = function getLabels(arr: any) {
|
||||
return arr.map((i: any) => this.getLabel(i));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -325,7 +361,7 @@ class KeyIndex {
|
||||
return this.rindex.length;
|
||||
}
|
||||
|
||||
subset(labels) {
|
||||
subset(labels: any) {
|
||||
/* validate subset */
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
const label = labels[i];
|
||||
@@ -338,7 +374,7 @@ class KeyIndex {
|
||||
return new KeyIndex(labels);
|
||||
}
|
||||
|
||||
isubset(offsets) {
|
||||
isubset(offsets: any) {
|
||||
const { rindex } = this;
|
||||
const maxOffset = rindex.length;
|
||||
const labels = new Array(offsets.length);
|
||||
@@ -352,7 +388,7 @@ class KeyIndex {
|
||||
return new KeyIndex(labels);
|
||||
}
|
||||
|
||||
isubsetMask(mask) {
|
||||
isubsetMask(mask: any) {
|
||||
const { rindex } = this;
|
||||
if (mask.length !== rindex.length)
|
||||
throw new RangeError("mask has invalid length for index");
|
||||
@@ -368,15 +404,15 @@ class KeyIndex {
|
||||
return new KeyIndex(labels);
|
||||
}
|
||||
|
||||
withLabel(label) {
|
||||
withLabel(label: any) {
|
||||
return new KeyIndex([...this.rindex, label]);
|
||||
}
|
||||
|
||||
withLabels(labels) {
|
||||
withLabels(labels: any) {
|
||||
return new KeyIndex([...this.rindex, ...labels]);
|
||||
}
|
||||
|
||||
dropLabel(label) {
|
||||
dropLabel(label: any) {
|
||||
const idx = this.rindex.indexOf(label);
|
||||
const labelArray = [...this.rindex];
|
||||
labelArray.splice(idx, 1);
|
||||
@@ -384,7 +420,7 @@ class KeyIndex {
|
||||
}
|
||||
}
|
||||
|
||||
function isLabelIndex(i) {
|
||||
function isLabelIndex(i: any) {
|
||||
return (
|
||||
i instanceof IdentityInt32Index ||
|
||||
i instanceof DenseInt32Index ||
|
||||
@@ -10,9 +10,10 @@ import quantile from "../quantile";
|
||||
import { sortArray } from "../typedCrossfilter/sort";
|
||||
|
||||
// [ 0, 0.01, 0.02, ..., 1.0]
|
||||
// @ts-expect-error ts-migrate(6133) FIXME: 'v' is declared but its value is never read.
|
||||
const centileNames = new Array(101).fill(0).map((v, idx) => idx / 100);
|
||||
|
||||
export function summarizeContinuous(col) {
|
||||
export function summarizeContinuous(col: any) {
|
||||
let min;
|
||||
let max;
|
||||
let nan = 0;
|
||||
@@ -63,7 +64,7 @@ export function summarizeContinuous(col) {
|
||||
};
|
||||
}
|
||||
|
||||
export function summarizeCategorical(col) {
|
||||
export function summarizeCategorical(col: any) {
|
||||
const categoryCounts = new Map();
|
||||
if (col) {
|
||||
for (let r = 0, l = col.length; r < l; r += 1) {
|
||||
@@ -4,14 +4,14 @@ Private utility code for dataframe
|
||||
|
||||
export { isTypedArray, isArrayOrTypedArray } from "../typeHelpers";
|
||||
|
||||
export function callOnceLazy(f) {
|
||||
export function callOnceLazy(f: any) {
|
||||
/*
|
||||
call function once, and save the result, regardless of arguments (this is not
|
||||
the same as typical memoization).
|
||||
*/
|
||||
let value;
|
||||
let value: any;
|
||||
let calledOnce = false;
|
||||
const result = function result(...args) {
|
||||
const result = function result(...args: any[]) {
|
||||
if (!calledOnce) {
|
||||
value = f(...args);
|
||||
calledOnce = true;
|
||||
@@ -21,7 +21,7 @@ export function callOnceLazy(f) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function memoize(fn, hashFn, maxResultsCached = -1) {
|
||||
export function memoize(fn: any, hashFn: any, maxResultsCached = -1) {
|
||||
/*
|
||||
function memoization, with user-provided hash. hashFn must return a
|
||||
key which will be unique as a Map key (ie, obeys "sameValueZero" algorithm
|
||||
@@ -29,7 +29,7 @@ export function memoize(fn, hashFn, maxResultsCached = -1) {
|
||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality
|
||||
*/
|
||||
const cache = new Map();
|
||||
const wrap = function wrap(...args) {
|
||||
const wrap = function wrap(...args: any[]) {
|
||||
const key = hashFn(...args);
|
||||
if (cache.has(key)) {
|
||||
return cache.get(key);
|
||||
Reference in New Issue
Block a user