Skip to content

Commit

Permalink
nodejs: minor update to constructor types (#2361)
Browse files Browse the repository at this point in the history
* node: update types

* update tests

* update tests
  • Loading branch information
universalmind303 committed Jan 12, 2022
1 parent 3de5edf commit 475cf3c
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 105 deletions.
7 changes: 1 addition & 6 deletions nodejs-polars/__tests__/series.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe("from lists", () => {
expect(actual).toEqual(expected);
});
test("string", () => {
const expected = [[], ["a"], [null], ["b", "c"]];
const expected = [[], [null], ["a"], [null], ["b", "c"]];
const actual = pl.Series(expected).toArray();
expect(actual).toEqual(expected);
});
Expand Down Expand Up @@ -801,11 +801,6 @@ describe("series proxy & metadata", () => {
expect(two).toStrictEqual(2);
expect(nine).toStrictEqual(9);
});
test("set", () => {
const s = pl.Series([1, 2, 3]);
s[0] = s[2];
expect(s[0]).toStrictEqual(s[2]);
});
});
describe("StringFunctions", () => {
it.each`
Expand Down
1 change: 1 addition & 0 deletions nodejs-polars/benches/list-operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const countries100k = Array.from({length: 100000}, () => chance.country());
const ints100kDS = pl.Series("ints", ints100k);
const strings100kDS = pl.Series("strings", strings100k);
const countries100kDS = pl.Series("countries", countries100k);

const ints1M = Array.from({length: 1000000}, () => chance.integer({min: -1000, max: 1000}));
const strings1M = Array.from({length: 1000000}, () => chance.word());
const countries1M = Array.from({length: 1000000}, () => chance.country());
Expand Down
177 changes: 91 additions & 86 deletions nodejs-polars/polars/dataframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,83 @@ import {col} from "./lazy/functions";

const inspect = Symbol.for("nodejs.util.inspect.custom");

/**
*
A DataFrame is a two-dimensional data structure that represents data as a table
with rows and columns.
Parameters
----------
@param data - Object, Array, or Series
Two-dimensional data in various forms. object must contain Arrays.
Array may contain Series or other Arrays.
@param columns - Array of str, default undefined
Column labels to use for resulting DataFrame. If specified, overrides any
labels already present in the data. Must match data dimensions.
@param orient - 'col' | 'row' default undefined
Whether to interpret two-dimensional data as columns or as rows. If None,
the orientation is inferred by matching the columns and data dimensions. If
this does not yield conclusive results, column orientation is used.
Examples
--------
Constructing a DataFrame from an object :
```
data = {'a': [1n, 2n], 'b': [3, 4]}
df = pl.DataFrame(data)
df
shape: (2, 2)
╭─────┬─────╮
│ a ┆ b │
│ --- ┆ --- │
│ u64 ┆ i64 │
╞═════╪═════╡
│ 1 ┆ 3 │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 2 ┆ 4 │
╰─────┴─────╯
```
Notice that the dtype is automatically inferred as a polars Int64:
```
df.dtypes
['UInt64', `Int64']
```
In order to specify dtypes for your columns, initialize the DataFrame with a list
of Series instead:
```
data = [pl.Series('col1', [1, 2], pl.Float32),
... pl.Series('col2', [3, 4], pl.Int64)]
df2 = pl.DataFrame(series)
df2
shape: (2, 2)
╭──────┬──────╮
│ col1 ┆ col2 │
│ --- ┆ --- │
│ f32 ┆ i64 │
╞══════╪══════╡
│ 1 ┆ 3 │
├╌╌╌╌╌╌┼╌╌╌╌╌╌┤
│ 2 ┆ 4 │
╰──────┴──────╯
```
Constructing a DataFrame from a list of lists, row orientation inferred:
```
data = [[1, 2, 3], [4, 5, 6]]
df4 = pl.DataFrame(data, ['a', 'b', 'c'])
df4
shape: (2, 3)
╭─────┬─────┬─────╮
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1 ┆ 2 ┆ 3 │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4 ┆ 5 ┆ 6 │
╰─────┴─────┴─────╯
```
*/
export interface DataFrame extends Arithmetic<DataFrame> {
/** @ignore */
_df: JsDataFrame
Expand Down Expand Up @@ -1715,91 +1791,16 @@ export const dfWrapper = (_df: JsDataFrame): DataFrame => {

};


/**
*
A DataFrame is a two-dimensional data structure that represents data as a table
with rows and columns.
Parameters
----------
@param data - Object, Array, or Series
Two-dimensional data in various forms. object must contain Arrays.
Array may contain Series or other Arrays.
@param columns - Array of str, default undefined
Column labels to use for resulting DataFrame. If specified, overrides any
labels already present in the data. Must match data dimensions.
@param orient - 'col' | 'row' default undefined
Whether to interpret two-dimensional data as columns or as rows. If None,
the orientation is inferred by matching the columns and data dimensions. If
this does not yield conclusive results, column orientation is used.
Examples
--------
Constructing a DataFrame from an object :
```
data = {'a': [1n, 2n], 'b': [3, 4]}
df = pl.DataFrame(data)
df
shape: (2, 2)
╭─────┬─────╮
│ a ┆ b │
│ --- ┆ --- │
│ u64 ┆ i64 │
╞═════╪═════╡
│ 1 ┆ 3 │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 2 ┆ 4 │
╰─────┴─────╯
```
Notice that the dtype is automatically inferred as a polars Int64:
```
df.dtypes
['UInt64', `Int64']
```
In order to specify dtypes for your columns, initialize the DataFrame with a list
of Series instead:
```
data = [pl.Series('col1', [1, 2], pl.Float32),
... pl.Series('col2', [3, 4], pl.Int64)]
df2 = pl.DataFrame(series)
df2
shape: (2, 2)
╭──────┬──────╮
│ col1 ┆ col2 │
│ --- ┆ --- │
│ f32 ┆ i64 │
╞══════╪══════╡
│ 1 ┆ 3 │
├╌╌╌╌╌╌┼╌╌╌╌╌╌┤
│ 2 ┆ 4 │
╰──────┴──────╯
```
Constructing a DataFrame from a list of lists, row orientation inferred:
```
data = [[1, 2, 3], [4, 5, 6]]
df4 = pl.DataFrame(data, ['a', 'b', 'c'])
df4
shape: (2, 3)
╭─────┬─────┬─────╮
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1 ┆ 2 ┆ 3 │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4 ┆ 5 ┆ 6 │
╰─────┴─────┴─────╯
```
*/
function _DataFrame(): DataFrame
function _DataFrame(data: Record<string, any>): DataFrame
function _DataFrame(data: Record<string, any>[]): DataFrame
function _DataFrame(data: Series<any>[]): DataFrame
function _DataFrame(data: any[][]): DataFrame
function _DataFrame(data: any[][], options: {columns?: any[], orient?: "row" | "col"}): DataFrame
function _DataFrame(data?: Record<string, any[]> | Record<string, any>[] | any[][] | Series<any>[], options?: {columns?: any[], orient?: "row" | "col"}): DataFrame {
export interface DataFrameConstructor {
(): DataFrame
(data: Record<string, any>): DataFrame
(data: Record<string, any>[]): DataFrame
(data: Series<any>[]): DataFrame
(data: any[][]): DataFrame
(data: any[][], options: {columns?: any[], orient?: "row" | "col"}): DataFrame
isDataFrame(arg: any): arg is DataFrame;
}
function DataFrameConstructor(data?, options?): DataFrame {

if(!data) {
return dfWrapper(objToDF({}));
Expand All @@ -1825,4 +1826,8 @@ function objToDF(obj: Record<string, Array<any>>): any {
}

const isDataFrame = (ty: any): ty is DataFrame => isExternal(ty?._df);
export const DataFrame = Object.assign(_DataFrame, {isDataFrame});
export namespace pl {
export const DataFrame: DataFrameConstructor = Object.assign(DataFrameConstructor, {isDataFrame});
}

export const DataFrame: DataFrameConstructor = Object.assign(DataFrameConstructor, {isDataFrame});
27 changes: 27 additions & 0 deletions nodejs-polars/polars/datatypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,33 @@ export const DTYPE_TO_FFINAME: Record<DataType, string> = {
[DataType.Categorical]: "categorical",
};

export const iterToTypedArray = (dtype: DataType, iterator: any): Iterable<any> => {
switch (dtype) {
case DataType.Int8:
return Int8Array.from(iterator);
case DataType.Int16:
return Int16Array.from(iterator);
case DataType.Int32:
return Int32Array.from(iterator);
case DataType.Int64:
return BigInt64Array.from(iterator);
case DataType.UInt8:
return Uint8Array.from(iterator);
case DataType.UInt16:
return Uint16Array.from(iterator);
case DataType.UInt32:
return Uint32Array.from(iterator);
case DataType.UInt64:
return BigUint64Array.from(iterator);
case DataType.Float32:
return Float32Array.from(iterator);
case DataType.Float64:
return Float64Array.from(iterator);
default:
return iterator;
}
};

const POLARS_TYPE_TO_CONSTRUCTOR: Record<string, string> = {
Float32: "new_opt_f32",
Float64: "new_opt_f64",
Expand Down
1 change: 1 addition & 0 deletions nodejs-polars/polars/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace pl {
export type WhenThenThen = _when.WhenThenThen;
export type FillNullStrategy = _FillNullStrategy;
export import Config = cfg.Config;
export import Int8 = DataType.Int8
export import Int16 = DataType.Int16
export import Int32 = DataType.Int32;
export import Int64 = DataType.Int64;
Expand Down
36 changes: 23 additions & 13 deletions nodejs-polars/polars/series.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import pli from "./internals/polars_internal";
import { arrayToJsSeries } from "./internals/construction";
import { DataType, DtypeToPrimitive, DTYPE_TO_FFINAME, Optional } from "./datatypes";
import { DataType, DtypeToPrimitive, DTYPE_TO_FFINAME, iterToTypedArray, Optional } from "./datatypes";
import {DataFrame, dfWrapper} from "./dataframe";
import {StringFunctions} from "./series/string";
import {ListFunctions} from "./series/list";
import {DateTimeFunctions} from "./series/datetime";
import {InvalidOperationError, todo} from "./error";
import {RankMethod, RollingOptions} from "./utils";
import {RankMethod} from "./utils";
import {col} from "./lazy/functions";
import {isExternal} from "util/types";
import {Arithmetic, Comparison, Cumulative, Rolling} from "./shared_traits";
Expand All @@ -28,17 +28,15 @@ export interface Series<T> extends
Arithmetic<Series<T>>,
Comparison<Series<boolean>>,
Cumulative<Series<T>> {
[n: number]: T
/** @ignore */
_series: JsSeries;
name: string
dtype: DataType
length: number
str: StringFunctions
lst: ListFunctions<T>
date: DateTimeFunctions
[inspect](): string;
[Symbol.iterator](): Generator<T, void, any>;
[Symbol.iterator](): IterableIterator<T>;
inner(): JsSeries
bitand(other: Series<any>): Series<T>
bitor(other: Series<any>): Series<T>
Expand Down Expand Up @@ -1553,20 +1551,32 @@ export const seriesWrapper = <T>(_s: JsSeries): Series<T> => {
});
};

function _Series<V extends ArrayLike<any>>(values: V): ValueOrNever<V>
function _Series<V extends ArrayLike<any>>(name: string, values: V): ValueOrNever<V>
function _Series<T extends DataType, U extends ArrayLikeDataType<T>>(name: string, values: U, dtype: T): Series<DtypeToPrimitive<T>>
function _Series<T extends DataType, U extends boolean, V extends ArrayLikeOrDataType<T, U>>(name: string, values: V, dtype?: T, strict?: U): Series<DataTypeOrValue<T, U>>
function _Series(arg0: any, arg1?: any, dtype?: any, strict?: any) {
export interface SeriesConstructor {
<V extends ArrayLike<any>>(values: V): ValueOrNever<V>
<V extends ArrayLike<any>>(name: string, values: V): ValueOrNever<V>
<T extends DataType, U extends ArrayLikeDataType<T>>(name: string, values: U, dtype: T): Series<DtypeToPrimitive<T>>
<T extends DataType, U extends boolean, V extends ArrayLikeOrDataType<T, U>>(name: string, values: V, dtype?: T, strict?: U): Series<DataTypeOrValue<T, U>>
isSeries(arg: any): arg is Series<any>;
}

const SeriesConstructor = (arg0: any, arg1?: any, dtype?: any, strict?: any) => {
if(typeof arg0 === "string") {
const _s = arrayToJsSeries(arg0, arg1, dtype, strict);

return seriesWrapper(_s);
}

return _Series("", arg0);
return SeriesConstructor("", arg0);

};

}
const isSeries = <T>(anyVal: any): anyVal is Series<T> => isExternal(anyVal?._series);

export const Series = Object.assign(_Series, {isSeries});
const fromNonNull = <T>(name: string, iterable: Iterable<T>, dtype: DataType): Series<T> => {
const typedarray = iterToTypedArray(dtype, iterable);

return pli.series.new_from_typed_array({ name, values:typedarray});

};

export const Series: SeriesConstructor = Object.assign(SeriesConstructor, {isSeries, fromNonNull});
1 change: 1 addition & 0 deletions nodejs-polars/polars/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const range = (start: number, end: number) => {
export const isDataFrameArray = (ty: any): ty is DataFrame[] => Array.isArray(ty) && isExternal(ty[0]?._df);
export const isSeriesArray = <T>(ty: any): ty is Series<T>[] => Array.isArray(ty) && isExternal(ty[0]?._series);
export const isExprArray = (ty: any): ty is Expr[] => Array.isArray(ty) && isExternal(ty[0]?._expr);
export const isIterator = <T>(ty: any): ty is Iterable<T> => ty !== null && typeof ty[Symbol.iterator] === "function";
export const regexToString = (r: string | RegExp): string => {
if(isRegExp(r)) {
return r.source;
Expand Down

0 comments on commit 475cf3c

Please sign in to comment.