diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 5c36c43b..c74850d4 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - node-version: [12.x, 14.x] + node-version: [18.x, 20.x] steps: - uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 211887f2..1a4e73cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ .editorconfig -node_modules \ No newline at end of file +node_modules +test/fixtures/* +test/samples/* +*.xlsx + +testsss diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..42b1f616 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,212 @@ +# Contributing Guide + +### Contributing to danfojs + +**Table of contents:** + +* [TL;DR](#tldr) +* [Where to start?](#where-to-start) +* [Project Structure](#project-structure) +* [Development Setup](#development-setup) + * [Prerequisites](#prerequisites) + * [Installation](#installation) + * [Building](#building) + * [Testing](#testing) +* [Working with Git](#working-with-git) +* [Documentation Guidelines](#documentation-guidelines) +* [Making Changes](#making-changes) +* [Creating Pull Requests](#creating-pull-requests) + +## TL;DR + +All contributions, bug reports, bug fixes, documentation improvements, enhancements, and ideas are welcome. + +Quick setup for experienced contributors: + +```bash +git clone https://github.com/javascriptdata/danfojs.git +cd danfojs +yarn install +yarn build +yarn test +``` + +## Where to start? + +For first-time contributors: + +1. Look for issues labeled ["good first issue"](https://github.com/javascriptdata/danfojs/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) +2. Read through our [Documentation](https://danfo.jsdata.org/getting-started) + + +## Project Structure + +The project is organized into three main packages: + +- **danfojs-base**: Core functionality shared between browser and Node.js versions +- **danfojs-browser**: Browser-specific implementation +- **danfojs-node**: Node.js-specific implementation + +Most new features should be added to **danfojs-base** unless they are environment-specific. + +## Development Setup + +### Prerequisites + +- Node.js (v16.x or later) +- Yarn package manager +- Git + +### Installation + +1. Fork the repository on GitHub +2. Clone your fork locally: + ```bash + git clone https://github.com/YOUR_USERNAME/danfojs.git + cd danfojs + ``` + +3. Install dependencies: + ```bash + yarn install + ``` + +### Building + +Build all packages: +```bash +yarn build +``` + +Build specific package: +```bash +cd src/danfojs-browser +yarn build +``` + +Watch mode for development: +```bash +yarn dev +``` + +### Testing + +Run all tests: +```bash +yarn test +``` + +Run specific test file: +```bash +yarn test tests/core/frame.test.js +``` + +Run tests matching a pattern: +```bash +yarn test -g "DataFrame.add" +``` + +Run tests in watch mode: +```bash +yarn test --watch +``` + +## Working with Git + +1. Create a new branch: + ```bash + git checkout -b feature/your-feature-name + ``` + +2. Make your changes and commit: + ```bash + git add . + git commit -m "feat: add new feature" + ``` + + We follow [Conventional Commits](https://www.conventionalcommits.org/) for commit messages: + - `feat:` for new features + - `fix:` for bug fixes + - `docs:` for documentation changes + - `test:` for adding tests + - `refactor:` for code refactoring + +3. Push to your fork: + ```bash + git push origin feature/your-feature-name + ``` + +## Documentation Guidelines + +Good documentation includes: + +1. JSDoc comments for all public methods +2. Clear parameter descriptions +3. Return value documentation +4. Usage examples + +Example: +```javascript +/** + * Add two series of the same length + * @param {Series} series1 - First series to add + * @param {Series} series2 - Second series to add + * @returns {Series} New series containing the sum + * + * @example + * const s1 = new Series([1, 2, 3]) + * const s2 = new Series([4, 5, 6]) + * const result = add_series(s1, s2) + * // result: Series([5, 7, 9]) + */ +function add_series(series1, series2) { + // Implementation +} +``` + +For methods with multiple options, use an options object: + +```javascript +/** + * Join two or more dataframes + * @param {Object} options - Join options + * @param {DataFrame[]} options.df_list - Array of DataFrames to join + * @param {number} options.axis - Join axis (0: index, 1: columns) + * @param {string} options.by_column - Column to join on + * @returns {DataFrame} Joined DataFrame + */ +function join_df(options) { + // Implementation +} +``` + +## Making Changes + +1. Write tests for new functionality +2. Ensure all tests pass +3. Update documentation if needed +4. Add an entry to CHANGELOG.md +5. Run linter: `yarn lint` + +## Creating Pull Requests + +1. Push your changes to your fork +2. Go to the [danfojs repository](https://github.com/javascriptdata/danfojs) +3. Click "Pull Request" +4. Fill out the PR template: + - Clear description of changes + - Link to related issue + - Screenshots/examples if relevant + - Checklist of completed items + +Your PR will be reviewed by maintainers. Address any feedback and update your PR accordingly. + +--- + +## Need Help? + + +- Check our [Documentation](https://danfo.jsdata.org) +- Ask in GitHub Issues + +Thank you for contributing to danfojs! 🎉 diff --git a/README.md b/README.md index 962bb15f..280c8724 100644 --- a/README.md +++ b/README.md @@ -46,142 +46,155 @@ easy and intuitive. It is heavily inspired by [Pandas](https://pandas.pydata.org - Robust data preprocessing functions like [OneHotEncoders](https://danfo.jsdata.org/api-reference/general-functions/danfo.onehotencoder), [LabelEncoders](https://danfo.jsdata.org/api-reference/general-functions/danfo.labelencoder), and scalers like [StandardScaler](https://danfo.jsdata.org/api-reference/general-functions/danfo.standardscaler) and [MinMaxScaler](https://danfo.jsdata.org/api-reference/general-functions/danfo.minmaxscaler) are supported on DataFrame and Series +## Installation +There are three ways to install and use Danfo.js in your application +* For Nodejs applications, you can install the [__danfojs-node__]() version via package managers like yarn and/or npm: -To use Danfo.js via script tags, copy and paste the CDN below to the body of your HTML file +```bash +npm install danfojs-node + +or + +yarn add danfojs-node +``` +For client-side applications built with frameworks like React, Vue, Next.js, etc, you can install the [__danfojs__]() version: + +```bash +npm install danfojs + +or + +yarn add danfojs +``` + +For use directly in HTML files, you can add the latest script tag from [JsDelivr](https://www.jsdelivr.com/package/npm/danfojs) to your HTML file: ```html - + ``` See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) -### Example Usage in the Browser - -> See the example below in [Code Sandbox](https://codepen.io/risingodegua/pen/bGwPGMG) +### Quick Examples +* [Danfojs with HTML and vanilla JavaScript on CodePen](https://codepen.io/risingodegua/pen/bGpwyYW) +* [Danfojs with React on Code Sandbox](https://codesandbox.io/s/using-danfojs-in-react-dwpv54?file=/src/App.js) +* [Danfojs on ObservableHq](https://observablehq.com/@risingodegua/using-danfojs-on-observablehq) +* [Danfojs in Nodejs on Replit](https://replit.com/@RisingOdegua/Danfojs-in-Nodejs) +### Example Usage in the Browser ```html - - - - - + + + + Document - - - + +
- - - + + ``` Output in Browser: ![](assets/browser-out.gif) -## How to install -Danfo.js is hosted on NPM, and can installed via package managers like npm and yarn - -```sh -npm install danfojs-node -``` - ### Example usage in Nodejs ```javascript +const dfd = require("danfojs-node"); -const dfd = require("danfojs-node") - -const file_url = "https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv" -dfd.read_csv(file_url) - .then(df => { - //prints the first five columns - df.head().print() +const file_url = + "https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv"; +dfd + .readCSV(file_url) + .then((df) => { + //prints the first five columns + df.head().print(); - // Calculate descriptive statistics for all numerical columns - df.describe().print() + // Calculate descriptive statistics for all numerical columns + df.describe().print(); - //prints the shape of the data - console.log(df.shape); + //prints the shape of the data + console.log(df.shape); - //prints all column names - console.log(df.columns); + //prints all column names + console.log(df.columns); - // //prints the inferred dtypes of each column - df.ctypes.print() + // //prints the inferred dtypes of each column + df.ctypes.print(); - //selecting a column by subsetting - df['Name'].print() + //selecting a column by subsetting + df["Name"].print(); - //drop columns by names - cols_2_remove = ['Age', 'Pclass'] - df_drop = df.drop({ columns: cols_2_remove, axis: 1 }) - df_drop.print() + //drop columns by names + let cols_2_remove = ["Age", "Pclass"]; + let df_drop = df.drop({ columns: cols_2_remove, axis: 1 }); + df_drop.print(); + //select columns by dtypes + let str_cols = df_drop.selectDtypes(["string"]); + let num_cols = df_drop.selectDtypes(["int32", "float32"]); + str_cols.print(); + num_cols.print(); - //select columns by dtypes - let str_cols = df_drop.select_dtypes(["string"]) - let num_cols = df_drop.select_dtypes(["int32", "float32"]) - str_cols.print() - num_cols.print() + //add new column to Dataframe + let new_vals = df["Fare"].round(1); + df_drop.addColumn("fare_round", new_vals, { inplace: true }); + df_drop.print(); - //add new column to Dataframe + df_drop["fare_round"].round(2).print(5); - let new_vals = df['Fare'].round(1) - df_drop.addColumn({ column: "fare_round", values: new_vals, inplace: true }) - df_drop.print() + //prints the number of occurence each value in the column + df_drop["Survived"].valueCounts().print(); - df_drop['fare_round'].round(2).print(5) + //print the last ten elementa of a DataFrame + df_drop.tail(10).print(); - //prints the number of occurence each value in the column - df_drop['Survived'].value_counts().print() - - //print the last ten elementa of a DataFrame - df_drop.tail(10).print() - - //prints the number of missing values in a DataFrame - df_drop.isna().sum().print() - - }).catch(err => { - console.log(err); - }) + //prints the number of missing values in a DataFrame + df_drop.isNa().sum().print(); + }) + .catch((err) => { + console.log(err); + }); ``` Output in Node Console: ![](assets/node-rec.gif) - -> If you want to use Danfo in frontend frameworks like React/Vue, read this [guide](https://danfo.jsdata.org/examples/using-danfojs-in-react) - ## Notebook support -* You can use Danfo.js on Dnotebooks playground [here](https://playnotebook.jsdata.org/demo) * VsCode nodejs notebook extension now supports Danfo.js. See guide [here](https://marketplace.visualstudio.com/items?itemName=donjayamanne.typescript-notebook) +* ObservableHQ Notebooks. See example notebook [here](https://observablehq.com/@risingodegua/using-danfojs-on-observablehq) #### [See the Official Getting Started Guide](https://danfo.jsdata.org/getting-started) @@ -190,10 +203,7 @@ The official documentation can be found [here](https://danfo.jsdata.org) ## Danfo.js Official Book -![image](https://user-images.githubusercontent.com/29900845/134811659-25ff6b05-8e0d-415f-a60c-03ab1d33fd71.jpeg) - - -We recently published a book titled "Building Data Driven Applications with Danfo.js". Read more about it [here](https://danfo.jsdata.org/building-data-driven-applications-with-danfo.js-book) +We published a book titled "Building Data Driven Applications with Danfo.js". Read more about it [here](https://danfo.jsdata.org/building-data-driven-applications-with-danfo.js-book) ## Discussion and Development Development discussions take place [here](https://github.com/opensource9ja/danfojs/discussions). diff --git a/danfojs-browser/src/core/concat.js b/danfojs-browser/src/core/concat.js deleted file mode 100644 index 0d3d28ad..00000000 --- a/danfojs-browser/src/core/concat.js +++ /dev/null @@ -1,219 +0,0 @@ -import DataFrame from './frame'; -// import { utils } from "../shared/utils"; -import Series from './series'; - - -export class Concat { - constructor(kwargs) { - - - // check if keys exist in kwargs - // utils.__in_object(kwargs, "df_list", "df_list not found: specify the list of dataframe"); - // utils.__in_object(kwargs, "axis", "axis not found: specify the axis"); - - let df_list = null; //set the df_list to null - let axis = null; // set axis to null - let indexes = null; - - //check if df_list is an array - if (Array.isArray(kwargs["df_list"])) { - - df_list = kwargs["df_list"]; - } else { - throw new Error("df_list must be an Array of dataFrames/Series"); - } - - //check if axis is int and is either 0 or 1 - if (typeof kwargs["axis"] === "number") { - - if (kwargs["axis"] == 0 || kwargs["axis"] == 1) { - - axis = kwargs["axis"]; - } else { - axis = 1; - // throw new Error("Invalid axis: axis must be 0 or 1") - } - - } else { - throw new Error("axis must be a number"); - } - - - let df_object = Object.assign({}, df_list); // convert the array to object - - if (axis == 1) { - - let columns = []; - let duplicate_col_count = {}; - let max_length = 0; - let a_key = Object.keys(df_object)[0]; - indexes = df_object[a_key].index; - for (let key in df_object) { - - let column = df_object[key].columns; - let length = df_object[key].values.length; - - if (length > max_length) { - max_length = length; - } - - for (let index in column) { - - let col_name = column[index]; - if (col_name in duplicate_col_count) { - - let count = duplicate_col_count[col_name]; - let name = `${col_name}_${count + 1}`; - - columns.push(name); - - duplicate_col_count[col_name] = count + 1; - } else { - - columns.push(col_name); - duplicate_col_count[col_name] = 1; - } - } - - - } - - let data = new Array(max_length); - - for (let key in df_list) { - - let values = df_list[key].values; - - for (let index = 0; index < values.length; index++) { - - let val = values[index]; - if (typeof data[index] === "undefined") { - - if (Array.isArray(val)){ - data[index] = val; - } else { - data[index] = [ val ]; - } - - } else { - if (Array.isArray(val)){ - data[index].push(...val); - } else { - data[index].push(val); - } - - } - } - - if (values.length < max_length) { - let column_length = df_list[key].columns.length; - let null_array = Array(column_length); - - for (let col = 0; col < column_length; col++) { - null_array[col] = NaN; - } - - if (typeof data[max_length - 1] === "undefined") { - data[max_length - 1] = null_array; - } else { - data[max_length - 1].push(...null_array); - } - } - } - - let df = new DataFrame(data, { columns: columns, index: indexes }); //convert to dataframe - return df; - } else { - //concatenate base on axis 0 - let columns = []; - let row_indexes = []; - let col_i = 0; - for (let key in df_list) { - let column = df_list[key].columns; - columns.push(...column); - indexes = df_list[key].index; - let r_index = indexes.map((val) => { - return `${val}_row${col_i}`; - }); - row_indexes.push(...r_index); - col_i += 1; - } - - let column_set = new Set(columns); - - columns = Array.from(column_set); - - let data = []; - - for (let key in df_list) { - - let value = df_list[key].values; - - // let col_length = value[0].length - - let df_columns = df_list[key].columns; - - let not_exist = []; - for (let col_index in columns) { - let col_name = columns[col_index]; - - let is_index = df_columns.indexOf(col_name); - - if (is_index == -1) { - not_exist.push(col_name); - } - } - if (not_exist.length > 0) { - for (let i = 0; i < value.length; i++) { - let row_value = value[i]; - - let new_arr = Array(columns.length); - for (let j = 0; j < columns.length; j++) { - - let col_name = columns[j]; - if (not_exist.includes(col_name)) { - - new_arr[j] = NaN; - } else { - let index = df_columns.indexOf(col_name); - if (Array.isArray(row_value)){ - new_arr[j] = row_value[index]; - } else { - new_arr[j] = row_value; - } - - } - - } - data.push(new_arr); - } - } else { - data.push(...value); - } - - } - - if (Array.isArray(data[0])){ - let df = new DataFrame(data, { columns: columns, index: row_indexes }); - return df; - } else { - let sf = new Series(data, { index: row_indexes }); - return sf; - } - - - } - - } -} - - -/** -* Concatenate pandas objects along a particular axis with optional set logic along the other axes. -* @param {kwargs} {df_list: List of DataFrame to concatenate together axis: 0 for row axis and 1 for index axis -* @returns {DataFrame} -*/ -export const concat = (kwargs) => { - let concat_sf = new Concat(kwargs); - return concat_sf; -}; diff --git a/danfojs-browser/src/core/date_range.js b/danfojs-browser/src/core/date_range.js deleted file mode 100644 index b1805173..00000000 --- a/danfojs-browser/src/core/date_range.js +++ /dev/null @@ -1,289 +0,0 @@ -import { utils } from "../shared/utils"; - -/** - * Generate date range between a specified set of date - * @param {kwargs} kwargs { - * start : string - * end : string - * period: int - * freq : string - * } - * @returns Array - */ -export class date_range { - constructor(kwargs){ - - this.offset = null; - - if (utils.keyInObject(kwargs, "start")){ - this.start = kwargs["start"]; - } else { - this.start = null; - } - - if (utils.keyInObject(kwargs, "end")){ - this.end = kwargs["end"]; - } else { - this.end = null; - } - - if (utils.keyInObject(kwargs, "period")){ - this.period = kwargs["period"]; - } else { - this.period = null; - } - - if (utils.keyInObject(kwargs, "freq")){ - this.freq = kwargs["freq"]; - } else { - this.freq = "D"; - } - - this.freq_list = [ "M", "D", "s", "H", "m", "Y" ]; - - if (this.freq.length == 1){ - if (!this.freq_list.includes(this.freq)){ - throw new Error(`invalid freq ${this.freq}`); - } - } else { - this.offset = parseInt(this.freq.slice(0, -1)); - if (!Number.isFinite(this.offset)){ - throw new Error(`invalid freq offset ${this.freq.slice(0, -1)}`); - } - this.freq = this.freq.slice(-1); - if (!this.freq_list.includes(this.freq)){ - throw new Error(`invalid freq ${this.freq}`); - } - } - - let rslt = this.range(this.start, this.end, this.period, this.offset); - return rslt; - - } - - range(start, end, period, offset = null){ - - let start_date = null; - let end_date = null; - let start_range = null; - let end_range = null; - if (start && end){ - start_date = new Date(start); - start_range = this.freq_type(start_date, this.freq); - end_date = new Date(end); - end_range = this.freq_type(end_date, this.freq); - - //check if the end year is greater than start year - let start_year = start_date.getFullYear(); - let end_year = end_date.getFullYear(); - if ((start_year < end_year)){ - // end_range = start_range + end_range - if (this.freq == "M"){ - end_range = this.month_end(start_date, end_date); - } else if (this.freq == "D"){ - end_range = this.day_end(start_date, end_date) - start_range; - - } - } - - let range_array = utils.range(start_range, end_range); - - if (offset){ - range_array = this.offset_count(range_array, offset); - } - - if (this.freq == "M"){ - range_array = this.month_range(range_array); - } - - let date_range = range_array.map((x) => { - return this.set_dateProps(start_date, this.freq, x); - }); - date_range[date_range.length - 1] = end_date; - - let date_string = this.toLocalString(date_range); - - return date_string; - } else if (start && !(end)){ - start_date = new Date(start); - start_range = this.freq_type(start_date, this.freq); - end_range = offset ? ((period * offset) - 1) : period - 1; - - if (start_range > end_range){ - end_range = end_range + start_range; - } - let range_array = utils.range(start_range, end_range); - - - if (offset){ - range_array = this.offset_count(range_array, offset); - } - - let date_range = range_array.map((x) => { - return this.set_dateProps(start_date, this.freq, x); - }); - - let date_string = this.toLocalString(date_range); - return date_string; - - } else if (end && !(start)){ - end_date = new Date(end); - end_range = this.freq_type(end_date, this.freq); - start_range = (end_range - period) + 1; - - let range_array = utils.range(start_range, end_range); - - if (offset){ - range_array = this.offset_count(range_array, offset); - } - - let date_range = range_array.map((x) => { - return this.set_dateProps(end_date, this.freq, x); - }); - - let date_string = this.toLocalString(date_range); - return date_string; - } - } - - freq_type(date, ftype){ - - let rslt = null; - switch (ftype){ - - case "M": - rslt = date.getMonth(); - break; - case "Y": - rslt = date.getFullYear(); - break; - case "s": - rslt = date.getSeconds(); - break; - case "D": - rslt = date.getDate(); - break; - case "H": - rslt = date.getHours(); - break; - case "m": - rslt = date.getMinutes(); - break; - } - return rslt; - } - - offset_count(d_array, offset){ - - let r_array = []; - - for (let i = 0; i < d_array.length; i += offset){ - r_array.push(d_array[i]); - } - return r_array; - } - - set_dateProps(date, ftype, val){ - - let new_date = new Date(date.valueOf()); - switch (ftype){ - - case "M": - if (val.length == 2){ - - new_date.setYear(new_date.getFullYear() + val[0]); - new_date.setMonth(parseInt(val[1])); - } else { - new_date.setMonth(val); - } - - break; - case "Y": - new_date.setYear(val); - break; - case "s": - new_date.setSeconds(val); - break; - case "D": - new_date.setDate(val); - break; - case "H": - new_date.setHours(val); - break; - case "m": - new_date.setMinutes(val); - break; - } - return new_date; - } - - toLocalString(d_array){ - - let r_array = d_array.map((x) => { - - return x.toLocaleString(); - }); - - return r_array; - } - - month_end(start_date, end_date){ - - let end_month = end_date.getMonth(); - - let diff_year = end_date.getFullYear() - start_date.getFullYear(); - - let end_range = (12 * diff_year) + end_month; - - return end_range; - } - - month_range(range){ - - let minus = null; - let y_val = 0; - let d_range = range.map((x) => { - - if (x > 11){ - if (x % 12 == 0){ - minus = x; - y_val = x / 12; - return [ y_val, (x - minus) ]; - } else { - return [ y_val, (x - minus) ]; - } - - } - return [ y_val, x ]; - }); - - return d_range; - } - - day_end(start_date, end_date){ - - let month_end = this.month_end(start_date, end_date); - let range = utils.range(start_date.getMonth(), month_end); - let m_range = this.month_range(range); - - // let s_date = new Date(start_date.getFullYear(),start_date.getMonth(),0) - let sum = 0; - for (let i = 0; i < m_range.length; i++){ - - let val = m_range[i]; - - let d_date = null; - if (i === m_range.length - 1) { - d_date = new Date(start_date.getFullYear() + val[0], val[1], end_date.getDate()).getDate(); - } else { - d_date = new Date(start_date.getFullYear() + val[0], val[1], 0).getDate(); - - } - - sum += d_date; - - } - return sum; - - } -} diff --git a/danfojs-browser/src/core/frame.js b/danfojs-browser/src/core/frame.js deleted file mode 100644 index 6b2f6321..00000000 --- a/danfojs-browser/src/core/frame.js +++ /dev/null @@ -1,2392 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { variance, std, median, mode, mean } from 'mathjs'; -import { DATA_TYPES } from '../shared/defaults'; -import { scalar, tensor2d, data as tfData } from '@tensorflow/tfjs'; -import { _genericMathOp } from "./math.ops"; -import ErrorThrower from "../shared/errors"; -import { _iloc, _loc } from "./indexing"; -import { utils } from "../shared/utils"; -import NDframe from "./generic"; -import { table } from "table"; -import Series from './series'; -import dummyEncode from "./get_dummies"; -import { GroupBy } from "./groupby"; -import { Plot } from "../plotting/plot"; - - -// const utils = new Utils(); - -/** - * Two-dimensional ndarray with axis labels. - * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. - * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. - * @param data 2D Array, JSON, Tensor, Block of data. - * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * @param options.columns Array of column names. If not specified, column names are auto generated. - * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. - * @param options.config General configuration object for extending or setting NDframe behavior. - */ -/* @ts-ignore */ //COMMENT OUT WHEN METHODS HAVE BEEN IMPLEMENTED -export default class DataFrame extends NDframe { - constructor(data, options) { - const { index, columns, dtypes, config } = { index: undefined, columns: undefined, dtypes: undefined, config: undefined, ...options }; - super({ data, index, columns, dtypes, config, isSeries: false }); - this.$setInternalColumnDataProperty(); - } - - /** - * Maps all column names to their corresponding data, and return them objects. - * This makes column subsetting works. E.g this can work ==> `df["col1"]` - * @param column Optional, a single column name to map - */ - $setInternalColumnDataProperty(column) { - const self = this; - if (column && typeof column === "string") { - Object.defineProperty(self, column, { - get() { - return self.$getColumnData(column); - }, - set(arr) { - self.$setColumnData(column, arr); - } - }); - } else { - const columns = this.columns; - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - Object.defineProperty(this, column, { - get() { - return self.$getColumnData(column); - }, - set(arr) { - self.$setColumnData(column, arr); - } - }); - } - } - - } - - /** - * Returns the column data from the DataFrame by column name. - * @param column column name to get the column data - * @param returnSeries Whether to return the data in series format or not. Defaults to true - */ - $getColumnData(column, returnSeries = true) { - const columnIndex = this.columns.indexOf(column); - - if (columnIndex == -1) { - ErrorThrower.throwColumnNotFoundError(this); - } - - const dtypes = [this.$dtypes[columnIndex]]; - const index = [...this.$index]; - const columns = [column]; - const config = { ...this.$config }; - - if (this.$config.isLowMemoryMode) { - const data = []; - for (let i = 0; i < this.values.length; i++) { - const row = this.values[i]; - data.push(row[columnIndex]); - } - if (returnSeries) { - return new Series(data, { - dtypes, - index, - columns, - config - }); - } else { - return data; - } - - } else { - const data = this.$dataIncolumnFormat[columnIndex]; - if (returnSeries) { - return new Series(data, { - dtypes, - index, - columns, - config - }); - } else { - return data; - } - } - - } - - - /** - * Updates the internal column data via column name. - * @param column The name of the column to update. - * @param arr The new column data - */ - $setColumnData(column, arr) { - - const columnIndex = this.$columns.indexOf(column); - - if (columnIndex == -1) { - throw new Error(`ParamError: column ${column} not found in ${this.$columns}. If you need to add a new column, use the df.addColumn method. `); - } - - let colunmValuesToAdd; - - if (arr instanceof Series) { - colunmValuesToAdd = arr.values; - } else if (Array.isArray(arr)) { - colunmValuesToAdd = arr; - } else { - throw new Error("ParamError: specified value not supported. It must either be an Array or a Series of the same length"); - } - - if (colunmValuesToAdd.length !== this.shape[0]) { - ErrorThrower.throwColumnLengthError(this, colunmValuesToAdd.length); - } - - if (this.$config.isLowMemoryMode) { - //Update row ($data) array - for (let i = 0; i < this.$data.length; i++) { - (this.$data)[i][columnIndex] = colunmValuesToAdd[i]; - } - //Update the dtypes - this.$dtypes[columnIndex] = utils.inferDtype(colunmValuesToAdd)[0]; - } else { - //Update row ($data) array - for (let i = 0; i < this.values.length; i++) { - (this.$data)[i][columnIndex] = colunmValuesToAdd[i]; - } - //Update column ($dataIncolumnFormat) array since it's available in object - (this.$dataIncolumnFormat)[columnIndex] = arr; - - //Update the dtypes - this.$dtypes[columnIndex] = utils.inferDtype(colunmValuesToAdd)[0]; - } - - } - - /** - * Return data with missing values removed from a specified axis - * @param axis 0 or 1. If 0, column-wise, if 1, row-wise - */ - $getDataByAxisWithMissingValuesRemoved(axis) { - const oldValues = this.$getDataArraysByAxis(axis); - const cleanValues = []; - for (let i = 0; i < oldValues.length; i++) { - const values = oldValues[i]; - cleanValues.push(utils.removeMissingValuesFromArray(values)); - } - return cleanValues; - } - - /** - * Return data aligned to the specified axis. Transposes the array if needed. - * @param axis 0 or 1. If 0, column-wise, if 1, row-wise - */ - $getDataArraysByAxis(axis) { - axis = axis === 0 ? 1 : 0; - if (axis === 1) { - return this.values; - } else { - let dfValues; - if (this.config.isLowMemoryMode) { - dfValues = utils.transposeArray(this.values); - } else { - dfValues = this.$dataIncolumnFormat; - } - return dfValues; - } - } - - /* - * checks if DataFrame is compactible for arithmetic operation - * compatible Dataframe must have only numerical dtypes - **/ - $frameIsNotCompactibleForArithmeticOperation() { - const dtypes = this.dtypes; - const str = (element) => element == "string"; - return dtypes.some(str); - } - - /** - * Return Tensors in the right axis for math operations. - * @param other DataFrame or Series or number or array - * @param axis 0 or 1. If 0, column-wise, if 1, row-wise - * */ - $getTensorsForArithmeticOperationByAxis( - other, - axis - ) { - axis = axis === 0 ? 1 : 0; - if (typeof other === "number") { - return [this.tensor, scalar(other)]; - } else if (other instanceof DataFrame) { - return [this.tensor, other.tensor]; - } else if (other instanceof Series) { - if (axis === 1) { - return [this.tensor, tensor2d(other.values, [other.shape[0], 1])]; - } else { - return [this.tensor, tensor2d(other.values, [other.shape[0], 1]).transpose()]; - } - } else if (Array.isArray(other)) { - if (axis === 1) { - return [this.tensor, tensor2d(other, [other.length, 1])]; - } else { - return [this.tensor, tensor2d(other, [other.length, 1]).transpose()]; - } - } else { - throw new Error("ParamError: Invalid type for other parameter. other must be one of Series, DataFrame or number."); - } - - } - - /** - * Returns the dtype for a given column name - * @param column - */ - $getColumnDtype(column) { - const columnIndex = this.columns.indexOf(column); - if (columnIndex === -1) { - throw Error(`ColumnNameError: Column "${column}" does not exist`); - } - return this.dtypes[columnIndex]; - } - - $logicalOps(tensors, operation) { - let newValues = []; - - switch (operation) { - case 'gt': - newValues = tensors[0].greater(tensors[1]).arraySync(); - break; - case 'lt': - newValues = tensors[0].less(tensors[1]).arraySync(); - break; - case 'ge': - newValues = tensors[0].greaterEqual(tensors[1]).arraySync(); - break; - case 'le': - newValues = tensors[0].lessEqual(tensors[1]).arraySync(); - break; - case 'eq': - newValues = tensors[0].equal(tensors[1]).arraySync(); - break; - case 'ne': - newValues = tensors[0].notEqual(tensors[1]).arraySync(); - break; - - } - - const newData = utils.mapIntegersToBooleans(newValues, 2); - return new DataFrame( - newData, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - $MathOps(tensors, operation, inplace) { - let tensorResult; - - switch (operation) { - case 'add': - tensorResult = tensors[0].add(tensors[1]); - break; - case 'sub': - tensorResult = tensors[0].sub(tensors[1]); - break; - case 'pow': - tensorResult = tensors[0].pow(tensors[1]); - break; - case 'div': - tensorResult = tensors[0].div(tensors[1]); - break; - case 'mul': - tensorResult = tensors[0].mul(tensors[1]); - break; - case 'mod': - tensorResult = tensors[0].mod(tensors[1]); - break; - } - - if (inplace) { - const newData = tensorResult.arraySync(); - this.$setValues(newData); - } else { - return new DataFrame( - tensorResult, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - - } - } - - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc(args) { - const { rows, columns } = { rows: undefined, columns: undefined, ...args }; - return _iloc({ ndFrame: this, rows, columns }); - } - - - /** - * Access a group of rows and columns by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc(args) { - const { rows, columns } = args; - return _loc({ ndFrame: this, rows, columns }); - } - - /** - * Prints DataFrame to console as a formatted grid of row and columns. - */ - toString() { - const maxRow = this.config.getMaxRow; - const maxColToDisplayInConsole = this.config.getTableMaxColInConsole; - - // let data; - const dataArr = []; - const colLen = this.columns.length; - - let header = []; - - if (colLen > maxColToDisplayInConsole) { - //truncate displayed columns to fit in the console - let firstFourcolNames = this.columns.slice(0, 4); - let lastThreecolNames = this.columns.slice(colLen - 4); - //join columns with truncate ellipse in the middle - header = ["", ...firstFourcolNames, "...", ...lastThreecolNames]; - - let subIdx; - let firstHalfValues; - let lastHalfValueS; - - if (this.values.length > maxRow) { - //slice Object to show [max_rows] - let dfSubset1 = this.iloc({ - rows: [`0:${maxRow}`], - columns: ["0:4"] - }); - - let dfSubset2 = this.iloc({ - rows: [`0:${maxRow}`], - columns: [`${colLen - 4}:`] - }); - - subIdx = this.index.slice(0, maxRow); - firstHalfValues = dfSubset1.values; - lastHalfValueS = dfSubset2.values; - - } else { - let dfSubset1 = this.iloc({ columns: ["0:4"] }); - let dfSubset2 = this.iloc({ columns: [`${colLen - 4}:`] }); - - subIdx = this.index.slice(0, maxRow); - firstHalfValues = dfSubset1.values; - lastHalfValueS = dfSubset2.values; - } - - // merge subset - for (let i = 0; i < subIdx.length; i++) { - const idx = subIdx[i]; - const row = [idx, ...firstHalfValues[i], "...", ...lastHalfValueS[i]]; - dataArr.push(row); - } - - } else { - //display all columns - header = ["", ...this.columns]; - let subIdx; - let values; - if (this.values.length > maxRow) { - //slice Object to show a max of [max_rows] - let data = this.iloc({ rows: [`0:${maxRow}`] }); - subIdx = data.index; - values = data.values; - } else { - values = this.values; - subIdx = this.index; - } - - // merge subset - for (let i = 0; i < subIdx.length; i++) { - const idx = subIdx[i]; - const row = [idx, ...values[i]]; - dataArr.push(row); - } - } - - - const columnsConfig = {}; - columnsConfig[0] = { width: 10 }; //set column width for index column - - for (let index = 1; index < header.length; index++) { - columnsConfig[index] = { width: 17, truncate: 16 }; - } - - const tableData = [header, ...dataArr]; //Adds the column names to values before printing - - return table(tableData, { columns: columnsConfig, ...this.config.getTableDisplayConfig }); - } - - /** - * Returns the first n values in a DataFrame - * @param rows The number of rows to return - */ - head(rows = 5) { - if (rows > this.shape[0]) { - throw new Error("ParamError of rows cannot be greater than available rows in data"); - } - if (rows <= 0) { - throw new Error("ParamError of rows cannot be less than 1"); - } - - return this.iloc({ rows: [`0:${rows}`] }); - } - - /** - * Returns the last n values in a DataFrame - * @param rows The number of rows to return - */ - tail(rows = 5) { - if (rows > this.shape[0]) { - throw new Error("ParamError of rows cannot be greater than available rows in data"); - } - if (rows <= 0) { - throw new Error("ParamError of rows cannot be less than 1"); - } - rows = this.shape[0] - rows; - return this.iloc({ rows: [`${rows}:`] }); - } - - /** - * Gets n number of random rows in a dataframe. Sample is reproducible if seed is provided. - * @param num The number of rows to return. Default to 5. - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - async sample(num = 5, options) { - const { seed } = { seed: 1, ...options }; - - if (num > this.shape[0]) { - throw new Error("ParamError: Sample size cannot be bigger than number of rows"); - } - if (num <= 0) { - throw new Error("ParamError: Sample size cannot be less than 1"); - } - - const shuffledIndex = await tfData.array(this.index).shuffle(num, `${seed}`).take(num).toArray(); - const df = this.iloc({ rows: shuffledIndex }); - return df; - } - - /** - * Return Addition of DataFrame and other, element-wise (binary operator add). - * @param other DataFrame, Series, Array or Scalar number to add - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: add operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "add", inplace); - } - - /** - * Return substraction between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to substract from DataFrame - * @param options.axis 0 or 1. If 0, compute the subtraction column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: sub operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "sub", inplace); - - - } - /** - * Return multiplciation between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to multiply with. - * @param options.axis 0 or 1. If 0, compute the multiplication column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mul operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "mul", inplace); - - - } - - /** - * Return division of DataFrame with other. - * @param other DataFrame, Series, Array or Scalar number to divide with. - * @param options.axis 0 or 1. If 0, compute the division column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: div operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "div", inplace); - - - } - - /** - * Return DataFrame raised to the power of other. - * @param other DataFrame, Series, Array or Scalar number to to raise to. - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: pow operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "pow", inplace); - - - } - - /** - * Return modulus between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to modulus with. - * @param options.axis 0 or 1. If 0, compute the mod column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mod operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "mod", inplace); - - } - - /** - * Return mean of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mean column-wise, if 1, row-wise. Defaults to 1 - */ - mean(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mean operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const meanArr = newData.map((arr) => arr.reduce((a, b) => a + b, 0) / arr.length); - if (axis === 1) { - return new Series(meanArr, { index: this.columns }); - } else { - return new Series(meanArr, { index: this.index }); - } - } - - /** - * Return median of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the median column-wise, if 1, row-wise. Defaults to 1 - */ - median(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: median operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const medianArr = newData.map((arr) => median(arr)); - if (axis === 1) { - return new Series(medianArr, { index: this.columns }); - } else { - return new Series(medianArr, { index: this.index }); - } - - } - - /** - * Return mode of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mode column-wise, if 1, row-wise. Defaults to 1 - * @param options.keep If there are more than one modes, returns the mode at position [keep]. Defaults to 0 - */ - mode(options) { - const { axis, keep } = { axis: 1, keep: 0, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mode operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const modeArr = newData.map((arr) => { - const tempMode = mode(arr); - if (tempMode.length === 1) { - return tempMode[0]; - } else { - return tempMode[keep]; - } - }); - if (axis === 1) { - return new Series(modeArr, { index: this.columns }); - } else { - return new Series(modeArr, { index: this.index }); - } - } - - /** - * Return minimum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the minimum value column-wise, if 1, row-wise. Defaults to 1 - */ - min(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: min operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - - const minArr = newData.map((arr) => { - let smallestValue = arr[0]; - for (let i = 0; i < arr.length; i++) { - smallestValue = smallestValue < arr[i] ? smallestValue : arr[i]; - } - return smallestValue; - }); - - if (axis === 1) { - return new Series(minArr, { index: this.columns }); - } else { - return new Series(minArr, { index: this.index }); - } - - } - - /** - * Return maximum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the maximum column-wise, if 1, row-wise. Defaults to 1 - */ - max(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: max operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - - const maxArr = newData.map((arr) => { - let biggestValue = arr[0]; - for (let i = 0; i < arr.length; i++) { - biggestValue = biggestValue > arr[i] ? biggestValue : arr[i]; - } - return biggestValue; - }); - - if (axis === 1) { - return new Series(maxArr, { index: this.columns }); - } else { - return new Series(maxArr, { index: this.index }); - } - - } - - /** - * Return standard deviation of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the standard deviation column-wise, if 1, row-wise. Defaults to 1 - */ - std(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: std operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const stdArr = newData.map((arr) => std(arr)); - - if (axis === 1) { - return new Series(stdArr, { index: this.columns }); - } else { - return new Series(stdArr, { index: this.index }); - } - - } - - /** - * Return variance of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the variance column-wise, if 1, add row-wise. Defaults to 1 - */ - var(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: var operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const varArr = newData.map((arr) => variance(arr)); - if (axis === 1) { - return new Series(varArr, { index: this.columns }); - } else { - return new Series(varArr, { index: this.index }); - } - } - - /** - * Get Less than of dataframe and other, element-wise (binary operator lt). - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - lt(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: lt operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "lt"); - } - - /** - * Returns "greater than" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - gt(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: gt operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "gt"); - } - - /** - * Returns "equals to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - eq(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: eq operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "eq"); - } - - /** - * Returns "not equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ne(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: ne operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "ne"); - } - - /** - * Returns "less than or equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - le(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: le operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "le"); - } - - /** - * Returns "greater than or equal to" between dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ge(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: ge operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "ge"); - } - - /** - * Return number of non-null elements in a Series - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - count(options) { - const { axis } = { axis: 1, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const countArr = newData.map((arr) => arr.length); - if (axis === 1) { - return new Series(countArr, { index: this.columns }); - } else { - return new Series(countArr, { index: this.index }); - } - } - - /** - * Return the sum of values across an axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - sum(options) { - const { axis } = { axis: 1, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const result = this.$getDataByAxisWithMissingValuesRemoved(axis); - const sumArr = result.map((innerArr) => { - return innerArr.reduce((a, b) => Number(a) + Number(b), 0); - }); - if (axis === 1) { - return new Series(sumArr, { - index: [...this.columns] - }); - } else { - return new Series(sumArr, { - index: [...this.index] - }); - } - - } - - /** - * Return the absolute value of elements in a DataFrame. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options) { - const { inplace } = { inplace: false, ...options }; - - const newData = (this.values).map((arr) => arr.map((val) => Math.abs(val))); - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - /** - * Rounds all element in the DataFrame to specified number of decimal places. - * @param dp Number of decimal places to round to. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp = 1, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: round operation is not supported for string dtypes"); - } - - if (typeof dp !== "number") { - throw Error("ParamError: dp must be a number"); - } - - const newData = utils.round(this.values, dp, false); - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame( - newData, - { - index: [...this.index], - columns: [...this.columns], - config: { ...this.config } - }); - } - } - - /** - * Returns cumulative product accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumprod(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("prod", axis, inplace); - } - - /** - * Returns cumulative sum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumsum(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("sum", axis, inplace); - } - - /** - * Returns cumulative minimum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummin(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("min", axis, inplace); - } - - /** - * Returns cumulative maximum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummax(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("max", axis, inplace); - } - - /** - * Internal helper function for cumulative operation on DataFrame - */ - cumOps(ops, axis, inplace) { - if (this.dtypes.includes("string")) ErrorThrower.throwStringDtypeOperationError(ops); - - const result = this.$getDataByAxisWithMissingValuesRemoved(axis); - - let newData = result.map((sData) => { - let tempval = sData[0]; - const data = [tempval]; - - for (let i = 1; i < sData.length; i++) { - let currVal = sData[i]; - switch (ops) { - case "max": - if (currVal > tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "min": - if (currVal < tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "sum": - tempval = (tempval) + (currVal); - data.push(tempval); - break; - case "prod": - tempval = (tempval) * (currVal); - data.push(tempval); - break; - - } - } - return data; - }); - - if (axis === 1) { - newData = utils.transposeArray(newData); - } - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - /** - * Generate descriptive statistics for all numeric columns - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - * @returns {Series} - */ - describe() { - const numericColumnNames = this.columns.filter((name) => this.$getColumnDtype(name) !== "string"); - const index = ["count", "mean", "std", "min", "median", "max", "variance"]; - const statsObject = {}; - for (let i = 0; i < numericColumnNames.length; i++) { - const colName = numericColumnNames[i]; - const $count = (this.$getColumnData(colName)).count(); - const $mean = mean(this.$getColumnData(colName, false)); - const $std = std(this.$getColumnData(colName, false)); - const $min = (this.$getColumnData(colName)).min(); - const $median = median(this.$getColumnData(colName, false)); - const $max = (this.$getColumnData(colName)).max(); - const $variance = variance(this.$getColumnData(colName, false)); - - const stats = [$count, $mean, $std, $min, $median, $max, $variance]; - statsObject[colName] = stats; - - } - - const df = new DataFrame(statsObject, { index }); - return df; - } - - /** - * Drops all rows or columns with missing values (NaN) - * @param axis 0 or 1. If 0, drop columns with NaNs, if 1, drop rows with NaNs - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(axis = 1, options) { - const { inplace } = { inplace: false, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newIndex = []; - - if (axis == 0) { - const newData = []; - - const dfValues = this.values; - for (let i = 0; i < dfValues.length; i++) { - const values = dfValues[i]; - if (!values.includes(NaN) && !values.includes(undefined) && !values.includes(null)) { - newData.push(values); - newIndex.push(this.index[i]); - } - } - - if (inplace) { - this.$setValues(newData, false); - this.$setIndex(newIndex); - } else { - return new DataFrame( - newData, - { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - } else { - const newColumnNames = []; - const newDtypes = []; - let dfValues = []; - - if (this.config.isLowMemoryMode) { - dfValues = utils.transposeArray(this.values); - } else { - dfValues = this.$dataIncolumnFormat; - } - const tempColArr = []; - - for (let i = 0; i < dfValues.length; i++) { - const values = dfValues[i]; - if (!values.includes(NaN)) { - tempColArr.push(values); - newColumnNames.push(this.columns[i]); - newDtypes.push(this.dtypes[i]); - } - } - - const newData = utils.transposeArray(tempColArr); - - if (inplace) { - this.$setValues(newData, false, false); - this.$setColumnNames(newColumnNames); - this.$setDtypes(newDtypes); - } else { - return new DataFrame( - newData, - { - index: [...this.index], - columns: newColumnNames, - dtypes: newDtypes, - config: { ...this.config } - }); - } - } - - } - - /** - * Adds a new column to the DataFrame. If column exists, then the column values is replaced. - * @param column The name of the column to add or replace. - * @param values An array of values to be inserted into the DataFrame. Must be the same length as the columns - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - addColumn(options) { - const { column, values, inplace } = { inplace: false, ...options }; - - if (!column) { - throw new Error("ParamError: column must be specified"); - } - - if (!values) { - throw new Error("ParamError: values must be specified"); - } - - const columnIndex = this.$columns.indexOf(column); - - if (columnIndex === -1) { - let colunmValuesToAdd; - - if (values instanceof Series) { - colunmValuesToAdd = values.values; - } else if (Array.isArray(values)) { - colunmValuesToAdd = values; - } else { - throw new Error("ParamError: specified value not supported. It must either be an Array or a Series of the same length"); - } - - if (colunmValuesToAdd.length !== this.shape[0]) { - ErrorThrower.throwColumnLengthError(this, colunmValuesToAdd.length); - } - - const newData = []; - const oldValues = this.$data; - for (let i = 0; i < oldValues.length; i++) { - const innerArr = [...oldValues[i]]; - innerArr.push(colunmValuesToAdd[i]); - newData.push(innerArr); - } - - if (inplace) { - this.$setValues(newData, true, false); - this.$setColumnNames([...this.columns, column]); - this.$setInternalColumnDataProperty(column); - - } else { - const df = new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns, column], - dtypes: [...this.dtypes, utils.inferDtype(colunmValuesToAdd)[0]], - config: { ...this.$config } - }); - return df; - } - } else { - this.$setColumnData(column, values); - } - - } - - /** - * Makes a new copy of a DataFrame - */ - copy() { - let df = new DataFrame([...this.$data], { - columns: [...this.columns], - index: [...this.index], - dtypes: [...this.dtypes], - config: { ...this.$config } - }); - return df; - } - - /** - * Return a boolean same-sized object indicating where elements are empty (NaN, undefined, null). - * NaN, undefined and null values gets mapped to true, and everything else gets mapped to false. - */ - isna() { - const newData = []; - for (let i = 0; i < this.values.length; i++) { - const valueArr = this.values[i]; - const tempData = valueArr.map((value) => { - if (utils.isEmpty(value)) { - return true; - } else { - return false; - } - }); - newData.push(tempData); - } - - const df = new DataFrame(newData, - { - index: [...this.index], - columns: [...this.columns], - config: { ...this.config } - }); - return df; - } - - /** - * Replace all empty elements with a specified value. Replace params expect columns array to map to values array. - * @param columns The list of column names to be replaced - * @param options.values The list of values to use for replacement. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(values, options) { - let { columns, inplace } = { inplace: false, ...options }; - - if (!values && typeof values !== "boolean") { - throw Error('ParamError: value must be specified'); - } - - if (Array.isArray(values)) { - if (!Array.isArray(columns)) { - throw Error('ParamError: value is an array, hence columns must also be an array of same length'); - } - - if (values.length !== columns.length) { - throw Error('ParamError: specified column and values must have the same length'); - } - - columns.forEach((col) => { - if (!this.columns.includes(col)) { - throw Error( - `ValueError: Specified column "${col}" must be one of ${this.columns}` - ); - } - }); - } - - const newData = []; - const oldValues = [...this.values]; - - if (!columns) { - //Fill all columns - for (let i = 0; i < oldValues.length; i++) { - const valueArr = [...oldValues[i]]; - - const tempArr = valueArr.map((innerVal) => { - if (utils.isEmpty(innerVal)) { - const replaceWith = Array.isArray(values) ? values[i] : values; - return replaceWith; - } else { - return innerVal; - } - }); - newData.push(tempArr); - } - - } else { - //Fill specific columns - const tempData = [...this.values]; - - for (let i = 0; i < tempData.length; i++) { - const valueArr = tempData[i]; - - for (let i = 0; i < columns.length; i++) { //B - const columnIndex = this.columns.indexOf(columns[i]); - const replaceWith = Array.isArray(values) ? values[i] : values; - valueArr[columnIndex] = utils.isEmpty(valueArr[columnIndex]) ? replaceWith : valueArr[columnIndex]; - } - newData.push(valueArr); - } - } - - if (inplace) { - this.$setValues(newData); - } else { - const df = new DataFrame(newData, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - } - - /** - * Drop columns or rows with missing values. Missing values are NaN, undefined or null. - * @param options.columns Array of column names to drop - * @param options.index Array of index to drop - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop(options) { - let { columns, index, inplace } = { inplace: false, ...options }; - - if (!columns && !index) { - throw Error('ParamError: Must specify one of columns or index'); - } - - if (columns && index) { - throw Error('ParamError: Can only specify one of columns or index'); - } - - if (columns) { - const columnIndices = []; - - if (typeof columns === "string") { - columnIndices.push(this.columns.indexOf(columns)); - } else if (Array.isArray(columns)) { - for (let column of columns) { - if (this.columns.indexOf(column) === -1) { - throw Error(`ParamError: specified column "${column}" not found in columns`); - } - columnIndices.push(this.columns.indexOf(column)); - } - - } else { - throw Error('ParamError: columns must be an array of column names or a string of column name'); - } - - let newRowData = []; - let newColumnNames = []; - let newDtypes = []; - - for (let i = 0; i < this.values.length; i++) { - const tempInnerArr = []; - const innerArr = this.values[i]; - for (let j = 0; j < innerArr.length; j++) { - if (!(columnIndices.includes(j))) { - tempInnerArr.push(innerArr[j]); - } - } - newRowData.push(tempInnerArr); - } - - for (let i = 0; i < this.columns.length; i++) { - const element = this.columns[i]; - if (!(columns.includes(element))) { - newColumnNames.push(element); - newDtypes.push(this.dtypes[i]); - } - } - - if (inplace) { - this.$setValues(newRowData, true, false); - this.$setColumnNames(newColumnNames); - } else { - const df = new DataFrame(newRowData, - { - index: [...this.index], - columns: newColumnNames, - dtypes: newDtypes, - config: { ...this.config } - }); - return df; - } - - } - - if (index) { - const rowIndices = []; - - if (typeof index === "string" || typeof index === "number" || typeof index === "boolean") { - rowIndices.push(this.index.indexOf(index)); - } else if (Array.isArray(index)) { - for (let indx of index) { - if (this.index.indexOf(indx) === -1) { - throw Error(`ParamError: specified index "${indx}" not found in indices`); - } - rowIndices.push(this.index.indexOf(indx)); - } - } else { - throw Error('ParamError: index must be an array of indices or a scalar index'); - } - - let newRowData = []; - let newIndex = []; - - for (let i = 0; i < this.values.length; i++) { - const innerArr = this.values[i]; - if (!(rowIndices.includes(i))) { - newRowData.push(innerArr); - } - } - - for (let i = 0; i < this.index.length; i++) { - const indx = this.index[i]; - if (!(index.includes(indx))) { - newIndex.push(indx); - } - } - - if (inplace) { - this.$setValues(newRowData, false); - this.$setIndex(newIndex); - } else { - const df = new DataFrame(newRowData, - { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - } - - } - - /** - * Sorts a Dataframe by a specified column values - * @param options.column Column name to sort by - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options) { - const { by, ascending, inplace } = { by: undefined, ascending: true, inplace: false, ...options }; - - if (!by) { - throw Error(`ParamError: must specify a column to sort by`); - } - - if (this.columns.indexOf(by) === -1) { - throw Error(`ParamError: specified column "${by}" not found in columns`); - } - - const columnValues = this.$getColumnData(by, false); - const index = [...this.index]; - - const objToSort = columnValues.map((value, i) => { - return { index: index[i], value }; - }); - - const sortedObjectArr = utils.sortObj(objToSort, ascending); - const sortedIndex = sortedObjectArr.map((obj) => obj.index); - - const newDf = _loc({ ndFrame: this, rows: sortedIndex }); - - if (inplace) { - this.$setValues(newDf.values); - this.$setIndex(newDf.index); - } else { - return newDf; - } - - } - - /** - * Sets the index of the DataFrame to the specified index. - * @param options.index An array of index values to set - * @param options.column A column name to set the index to - * @param options.drop Whether to drop the column whose index was set. Defaults to false - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options) { - const { index, column, drop, inplace } = { drop: false, inplace: false, ...options }; - - if (!index && !column) { - throw new Error("ParamError: must specify either index or column"); - } - - let newIndex = []; - - if (index) { - if (!Array.isArray(index)) { - throw Error(`ParamError: index must be an array`); - } - - if (index.length !== this.values.length) { - throw Error(`ParamError: index must be the same length as the number of rows`); - } - newIndex = index; - } - - if (column) { - if (this.columns.indexOf(column) === -1) { - throw Error(`ParamError: column not found in column names`); - } - - newIndex = this.$getColumnData(column, false); - } - - if (drop) { - const dfDropped = this.drop({ columns: [column] }); - - const newData = dfDropped.values; - const newColumns = dfDropped.columns; - const newDtypes = dfDropped.dtypes; - - if (inplace) { - this.$setValues(newData, true, false); - this.$setIndex(newIndex); - this.$setColumnNames(newColumns); - } else { - const df = new DataFrame(newData, - { - index: newIndex, - columns: newColumns, - dtypes: newDtypes, - config: { ...this.config } - }); - return df; - } - } else { - if (inplace) { - this.$setIndex(newIndex); - } else { - const df = new DataFrame(this.values, - { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - } - - } - - /** - * Resets the index of the DataFrame to the default index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - reset_index(options) { - const { inplace } = { inplace: false, ...options }; - - if (inplace) { - this.$resetIndex(); - } else { - const df = new DataFrame(this.values, - { - index: this.index.map((_, i) => i), - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - - } - - /** - * Apply a function along an axis of the DataFrame. To apply a function element-wise, use `applyMap`. - * Objects passed to the function are Series values whose - * index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1) - * @param callable Function to apply to each column or row - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - */ - apply(callable, options) { - const { axis } = { axis: 1, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error(`ParamError: axis must be 0 or 1`); - } - - const valuesForFunc = this.$getDataByAxisWithMissingValuesRemoved(axis); - - const result = valuesForFunc.map((row) => { - return callable(row); - }); - - if (axis === 1) { - if (utils.is1DArray(result)) { - return new Series(result, { - index: [...this.columns] - }); - } else { - return new DataFrame(result, { - index: [...this.columns], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } else { - if (utils.is1DArray(result)) { - return new Series(result, { - index: [...this.index] - }); - } else { - return new DataFrame(result, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - } - - /** - * Apply a function to a Dataframe values element-wise. - * @param callable Function to apply to each column or row - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply_map(callable, options) { - const { inplace } = { inplace: false, ...options }; - - const newData = this.values.map((row) => { - const tempData = row.map((val) => { - return callable(val); - }); - return tempData; - }); - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - /** - * Returns the specified column data as a Series object. - * @param column The name of the column to return - */ - column(column) { - return this.$getColumnData(column); - } - - /** - * Return a subset of the DataFrame’s columns based on the column dtypes. - * @param include An array of dtypes or strings to be included. - */ - select_dtypes(include) { - const supportedDtypes = ["float32", "int32", "string", "boolean", 'undefined']; - - if (Array.isArray(include) === false) { - throw Error(`ParamError: include must be an array`); - } - - include.forEach((dtype) => { - if (supportedDtypes.indexOf(dtype) === -1) { - throw Error(`ParamError: include must be an array of valid dtypes`); - } - }); - const newColumnNames = []; - - for (let i = 0; i < this.dtypes.length; i++) { - if (include.includes(this.dtypes[i])) { - newColumnNames.push(this.columns[i]); - } - } - return this.loc({ columns: newColumnNames }); - - } - - /** - * Returns the transposes the DataFrame. - **/ - transpose(options) { - const { inplace } = { inplace: false, ...options }; - const newData = utils.transposeArray(this.values); - const newColNames = [...this.index.map((i) => i.toString())]; - - if (inplace) { - this.$setValues(newData, false, false); - this.$setIndex([...this.columns]); - this.$setColumnNames(newColNames); - } else { - return new DataFrame(newData, { - index: [...this.columns], - columns: newColNames, - config: { ...this.config } - }); - } - } - - /** - * Returns the Transpose of the DataFrame. Similar to `transpose`, but does not change the original DataFrame. - **/ - get T() { - const newData = utils.transposeArray(this.values); - return new DataFrame(newData, { - index: [...this.columns], - columns: [...this.index.map((i) => i.toString())], - config: { ...this.config } - }); - } - - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.columns An array of column names you want to replace. If not provided replace accross all columns. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace( - oldValue, - newValue, - options - ) { - const { columns, inplace } = { inplace: false, ...options }; - - if (!oldValue && typeof oldValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'oldValue' to replace`); - } - - if (!newValue && typeof newValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'newValue' to replace with`); - } - - let newData = []; - - if (columns) { - if (!Array.isArray(columns)) { - throw Error(`Params Error: column must be an array of column(s)`); - } - const columnIndex = []; - - columns.forEach((column) => { - const _indx = this.columns.indexOf(column); - if (_indx === -1) { - throw Error(`Params Error: column not found in columns`); - } - columnIndex.push(_indx); - }); - - newData = (this.values).map(([...row]) => { - for (const colIndx of columnIndex) { - if (row[colIndx] === oldValue) { - row[colIndx] = newValue; - } - } - return row; - }); - } else { - newData = (this.values).map(([...row]) => { - return row.map(((cell) => { - if (cell === oldValue) { - return newValue; - } else { - return cell; - } - })); - }); - } - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - - /** - * Cast the values of a column to specified data type - * @param column The name of the column to cast - * @param dtype Data type to cast to. One of [float32, int32, string, boolean] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(options) { - const { inplace, column, dtype } = { inplace: false, ...options }; - const columnIndex = this.columns.indexOf(column); - - if (columnIndex === -1) { - throw Error(`Params Error: column not found in columns`); - } - - if (!(DATA_TYPES.includes(dtype))) { - throw Error(`dtype ${dtype} not supported. dtype must be one of ${DATA_TYPES}`); - } - - const data = this.values; - - const newData = data.map((row) => { - if (dtype === "float32") { - row[columnIndex] = Number(row[columnIndex]); - return row; - } else if (dtype === "int32") { - row[columnIndex] = parseInt(row[columnIndex]); - return row; - } else if (dtype === "string") { - row[columnIndex] = row[columnIndex].toString(); - return row; - } else if (dtype === "boolean") { - row[columnIndex] = Boolean(row[columnIndex]); - return row; - } - }); - - if (inplace) { - this.$setValues(newData); - } else { - const newDtypes = [...this.dtypes]; - newDtypes[columnIndex] = dtype; - - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: newDtypes, - config: { ...this.config } - }); - } - } - - /** - * Return the number of unique elements in a across the specified axis. - * To get the values use `.unique()` instead. - * @param axis The axis to count unique elements across. Defaults to 1 - */ - nunique(axis = 1) { - if ([0, 1].indexOf(axis) === -1) { - throw Error(`ParamError: axis must be 0 or 1`); - } - const data = this.$getDataArraysByAxis(axis); - const newData = data.map((row) => new Set(row).size); - - if (axis === 0) { - return new Series(newData, { - index: [...this.columns], - dtypes: ["int32"] - }); - } else { - return new Series(newData, { - index: [...this.index], - dtypes: ["int32"] - }); - } - } - - /** - * Renames a column or index. - * @param mapper An object that maps each column or index in the DataFrame to a new value - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.axis The axis to perform the operation on. Defaults to 1 - */ - rename(options) { - const { mapper, axis, inplace } = { axis: 1, inplace: false, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error(`ParamError: axis must be 0 or 1`); - } - - if (axis === 1) { - const colsAdded = []; - const newColumns = this.columns.map((col) => { - if (mapper[col] !== undefined) { - colsAdded.push(mapper[col]); - return mapper[col]; - } else { - return col; - } - }); - - if (inplace) { - this.$setColumnNames(newColumns); - for (const col of colsAdded) { - this.$setInternalColumnDataProperty(col); - } - } else { - return new DataFrame([...this.values], { - index: [...this.index], - columns: newColumns, - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } else { - const newIndex = this.index.map((col) => { - if (mapper[col] !== undefined) { - return mapper[col]; - } else { - return col; - } - }); - - if (inplace) { - this.$setIndex(newIndex); - } else { - return new DataFrame([...this.values], { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - } - - /** - * Sorts the Dataframe by the index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - */ - sort_index(options) { - const { ascending, inplace } = { ascending: true, inplace: false, ...options }; - - const indexPosition = utils.range(0, this.index.length - 1); - const index = [...this.index]; - - const objToSort = index.map((idx, i) => { - return { index: indexPosition[i], value: idx }; - }); - - const sortedObjectArr = utils.sortObj(objToSort, ascending); - let sortedIndex = sortedObjectArr.map((obj) => obj.index); - const newData = sortedIndex.map((i) => (this.values)[i]); - sortedIndex = sortedIndex.map((i) => index[i]); - - if (inplace) { - this.$setValues(newData); - this.$setIndex(sortedIndex); - } else { - return new DataFrame(newData, { - index: sortedIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - } - - /** - * Add new rows to the end of the DataFrame. - * @param newValues Array, Series or DataFrame to append to the DataFrame - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append( - newValues, - index, - options - ) { - const { inplace } = { inplace: false, ...options }; - - if (!newValues) { - throw Error(`ParamError: newValues must be a Series, DataFrame or Array`); - } - - if (!index) { - throw Error(`ParamError: index must be specified`); - } - - let rowsToAdd = []; - if (newValues instanceof Series) { - - if (newValues.values.length !== this.shape[1]) { - throw Error(`ValueError: length of newValues must be the same as the number of columns.`); - } - rowsToAdd = [newValues.values]; - - } else if (newValues instanceof DataFrame) { - - if (newValues.shape[1] !== this.shape[1]) { - throw Error(`ValueError: length of newValues must be the same as the number of columns.`); - } - rowsToAdd = newValues.values; - - } else if (Array.isArray(newValues)) { - - if (utils.is1DArray(newValues)) { - rowsToAdd = [newValues]; - } else { - rowsToAdd = newValues; - } - - if ((rowsToAdd[0]).length !== this.shape[1]) { - throw Error(`ValueError: length of newValues must be the same as the number of columns.`); - } - - } else { - throw Error(`ValueError: newValues must be a Series, DataFrame or Array`); - } - - - let indexInArrFormat = []; - if (!Array.isArray(index)) { - indexInArrFormat = [index]; - } else { - indexInArrFormat = index; - } - - if (rowsToAdd.length !== indexInArrFormat.length) { - throw Error(`ParamError: index must contain the same number of values as newValues`); - } - - const newData = [...this.values]; - const newIndex = [...this.index]; - - rowsToAdd.forEach((row, i) => { - newData.push(row); - newIndex.push(indexInArrFormat[i]); - }); - - if (inplace) { - this.$setValues(newData); - this.$setIndex(newIndex); - } else { - return new DataFrame(newData, { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - } - - /** - * Queries the DataFrame for rows that meet the boolean criteria. - * @param options - * - `column` A column name to query with. - * - `is` A logical operator. Can be one of the following: [">", "<", "<=", ">=", "==", "!="] - * - `to` A value to query with. - * - `condition` An array of boolean mask, one for each row in the DataFrame. Rows where the value are true will be returned. - * If specified, then other parameters are ignored. - * - `inplace` Boolean indicating whether to perform the operation inplace or not. Defaults to false - **/ - query(options) { - const { inplace, condition, column, is, to } = { inplace: false, ...options }; - - if (condition) { - const result = _iloc({ - ndFrame: this, - rows: condition - }); - - if (inplace) { - this.$setValues(result.values, false, false); - this.$setIndex(result.index); - return; - } else { - return result; - } - - } - - const operators = [">", "<", "<=", ">=", "==", "!="]; - - let columnIndex, operator, value; - - if (column) { - if (this.columns.includes(column)) { - columnIndex = this.columns.indexOf(column); - } else { - throw new Error(`ParamError: column ${column} not found in column names`); - } - } else { - throw new Error(`ParamError: specify a column name to query`); - } - - if (is) { - if (operators.includes(is)) { - operator = is; - } else { - throw new Error(`ParamError: specified operato ${is} is not a supported. operator must be one of ${operators}`); - } - } else { - throw new Error(`ParamError: specify an operator to apply. operator must be one of ${operators}`); - } - - if (to) { - value = to; - } else { - throw new Error("ParamError: specify a value to query by"); - } - - let data = this.values; - let index = this.index; - let newData = []; - let newIndex = []; - - for (var i = 0; i < data.length; i++) { - let dataValue = data[i]; - let elem = dataValue[columnIndex]; - //use eval function for easy operation - //eval() takes in a string expression e.g eval('2>5') - if (eval(`elem${operator}value`)) { - newData.push(dataValue); - newIndex.push(index[i]); - } - } - - if (inplace) { - this.$setValues(newData, false, false); - this.$setIndex(newIndex); - return; - } else { - return new DataFrame(newData, { - index: newIndex, - columns: this.columns, - config: { ...this.config } - }); - } - } - - /** - * Returns the data types for each column as a Series. - */ - get ctypes() { - return new Series(this.dtypes, { index: this.columns }); - } - - /** - * One-hot encode specified columns in the DataFrame. If columns are not specified, all columns of dtype string will be encoded. - * @param options Options for the operation. The following options are available: - * - `columns`: A single column name or an array of column names to encode. Defaults to all columns of dtype string. - * - `prefix`: Prefix to add to the column names. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * - `inplace` indicating whether to perform the operation inplace or not. Defaults to false - * @returns A DataFrame with the one-hot encoded columns. - * @example - * df.getDummies({ columns: ['a', 'b'] }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-', inplace: true }) - * df.getDummies({ columns: ['a', 'b'], prefix: ['col1', 'col2'], prefixSeparator: '-', inplace: true }) - */ - get_dummies(options) { - const { inplace } = { inplace: false, ...options }; - - const encodedDF = dummyEncode(this, options); - if (inplace) { - this.$setValues(encodedDF.values, false, false); - this.$setColumnNames(encodedDF.columns); - } else { - return encodedDF; - } - - } - - /** - * Make plots of Series or DataFrame. - * Uses the Plotly as backend, so supports Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @returns {Class} Plot class that expoese different plot type - */ - plot(div) { - const plt = new Plot(this, div); - return plt; - } - - /** - * - * @param {col} col is a list of columns - */ - groupby(col) { - const len = this.shape[0]; - const columns = this.columns; - const col_index = col.map((val) => columns.indexOf(val)); - const col_dtype = this.dtypes.filter((val, index) => { - return col_index.includes(index); - }); - - const self = this; - const data = col.map( - (column_name) => { - if (!(columns.includes(column_name))) - throw new Error(`column ${column_name} does not exist`); - const column_data = self.column(column_name).values; - return column_data; - } - ); - - const unique_columns = data.map((column_data) => utils.unique(column_data)); - - function getRecursiveDict(uniq_columns) { - const first_uniq_columns = uniq_columns[0]; - const remaining_columns = uniq_columns.slice(1); - const c_dict = {}; - if (!remaining_columns.length) - first_uniq_columns.forEach((col_value) => c_dict[col_value] = []); - else - first_uniq_columns.forEach((col_value) => c_dict[col_value] = getRecursiveDict(remaining_columns)); - return c_dict; - } - const col_dict = getRecursiveDict(unique_columns); - - return new GroupBy( - col_dict, - col, - this.values, - columns, - col_dtype - ).group(); - } - -} diff --git a/danfojs-browser/src/core/generic.js b/danfojs-browser/src/core/generic.js deleted file mode 100644 index 2c0e6c6d..00000000 --- a/danfojs-browser/src/core/generic.js +++ /dev/null @@ -1,451 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -import { utils } from "../shared/utils"; -import Configs from "../shared/config"; -import ErrorThrower from '../shared/errors'; -import { BASE_CONFIG, DATA_TYPES } from '../shared/defaults'; -import { toCSV, toJSON, toExcel } from "../io"; -import { Tensor, tensor1d, tensor2d } from "@tensorflow/tfjs"; - -// const utils = new Utils(); - -/** - * N-Dimension data structure. Stores multi-dimensional - * data in a size-mutable, labeled data structure. Analogous to the Python Pandas DataFrame. - * - * @param Object - * - * data: 1D or 2D Array, JSON, Tensor, Block of data. - * - * index: Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * - * columns: Array of column names. If not specified, column names are auto generated. - * - * dtypes: Array of data types for each the column. If not specified, dtypes inferred. - * - * config: General configuration object for NDframe - * - * @returns NDframe - */ -export default class NDframe { - - constructor({ data, index, columns, dtypes, config, isSeries }) { - this.$isSeries = isSeries; - if (config) { - this.$config = new Configs({ ...BASE_CONFIG, ...config }); - } else { - this.$config = new Configs(BASE_CONFIG); - } - - if (data instanceof Tensor) { - data = data.arraySync(); - } - - if (data === undefined || (Array.isArray(data) && data.length === 0)) { - this.loadArrayIntoNdframe({ data: [], index: [], columns: [], dtypes: [] }); - } else if (utils.is1DArray(data)) { - this.loadArrayIntoNdframe({ data, index, columns, dtypes }); - } else { - - if (Array.isArray(data) && utils.isObject(data[0])) { - this.loadObjectIntoNdframe({ data, type: 1, index, columns, dtypes }); - - } else if (utils.isObject(data)) { - this.loadObjectIntoNdframe({ data, type: 2, index, columns, dtypes }); - - } else if ( - Array.isArray((data)[0]) || - utils.isNumber((data)[0]) || - utils.isString((data)[0]) - ) { - this.loadArrayIntoNdframe({ data, index, columns, dtypes }); - } else { - throw new Error("File format not supported!"); - } - } - } - - /** - * Internal function to load array of data into NDFrame - * @param data The array of data to load into NDFrame - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - loadArrayIntoNdframe({ data, index, columns, dtypes }) { - // this.$data = utils.replaceUndefinedWithNaN(data, this.$isSeries); - this.$data = data; - if (!this.$config.isLowMemoryMode) { - //In NOT low memory mode, we transpose the array and save in column format. - //This makes column data retrieval run in constant time - this.$dataIncolumnFormat = utils.transposeArray(data); - } - this.$setIndex(index); - this.$setDtypes(dtypes); - this.$setColumnNames(columns); - } - - /** - * Internal function to format and load a Javascript object or object of arrays into NDFrame. - * @param data Object or object of arrays. - * @param type The type of the object. There are two recognized types: - * - * - type 1 object are in JSON format `[{a: 1, b: 2}, {a: 30, b: 20}]`. - * - * - type 2 object are of the form `{a: [1,2,3,4], b: [30,20, 30, 20}]}` - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - loadObjectIntoNdframe({ data, type, index, columns, dtypes }) { - if (type === 1 && Array.isArray(data)) { - const _data = (data).map((item) => { - return Object.values(item); - }); - - let _columnNames; - - if (columns) { - _columnNames = columns; - } else { - _columnNames = Object.keys((data)[0]); - } - - this.loadArrayIntoNdframe({ data: _data, index, columns: _columnNames, dtypes }); - - } else { - const [_data, _colNames] = utils.getRowAndColValues(data); - let _columnNames; - - if (columns) { - _columnNames = columns; - } else { - _columnNames = _colNames; - } - this.loadArrayIntoNdframe({ data: _data, index, columns: _columnNames, dtypes }); - } - } - - /** - * Converts and returns the data in the NDframe as a Tensorflow.js Tensor. - */ - get tensor() { - if (this.$isSeries) { - return tensor1d(this.$data); - } else { - return tensor2d(this.$data); - } - } - - /** - * Returns the dtypes of the columns - */ - get dtypes() { - return this.$dtypes; - } - - /** - * Internal function to set the Dtypes of the NDFrame from an array. This function - * performs the necessary checks. - */ - $setDtypes(dtypes) { - if (this.$isSeries) { - if (dtypes) { - if (this.$data.length != 0 && dtypes.length != 1) { - ErrorThrower.throwDtypesLengthError(this, dtypes); - } - - if (!(DATA_TYPES.includes(`${dtypes[0]}`))) { - ErrorThrower.throwDtypeNotSupportedError(dtypes[0]); - } - - this.$dtypes = dtypes; - } else { - this.$dtypes = utils.inferDtype(this.$data); - } - - } else { - if (dtypes) { - if (this.$data.length != 0 && dtypes.length != this.shape[1]) { - ErrorThrower.throwDtypesLengthError(this, dtypes); - } - - if (this.$data.length == 0 && dtypes.length == 0) { - this.$dtypes = dtypes; - } else { - dtypes.forEach((dtype) => { - if (!(DATA_TYPES.includes(dtype))) { - ErrorThrower.throwDtypeNotSupportedError(dtype); - } - }); - - this.$dtypes = dtypes; - - } - - } else { - this.$dtypes = utils.inferDtype(this.$data); - } - } - } - - /** - * Returns the dimension of the data. Series have a dimension of 1, - * while DataFrames have a dimension of 2. - */ - get ndim() { - if (this.$isSeries) { - return 1; - } else { - return 2; - } - } - - /** - * Returns the axis labels of the NDFrame. - */ - get axis() { - return { - index: this.$index, - columns: this.$columns - }; - } - - /** - * Returns the configuration object of the NDFrame. - */ - get config() { - return this.$config; - - } - - /** - * Internal function to set the configuration of the ndframe - */ - $setConfig(config) { - this.$config = config; - } - - /** - * Returns the indices of the NDFrame - */ - get index() { - return this.$index; - - } - - /** - * Internal function to set the index of the NDFrame with the specified - * array of indices. Performs all necessary checks to ensure that the - * index is valid. - */ - $setIndex(index) { - if (index) { - - if (this.$data.length != 0 && index.length != this.shape[0]) { - ErrorThrower.throwIndexLengthError(this, index); - } - if (Array.from(new Set(index)).length !== this.shape[0]) { - ErrorThrower.throwIndexDuplicateError(); - } - - this.$index = index; - } else { - this.$index = utils.range(0, this.shape[0] - 1); //generate index - } - } - - /** - * Internal function to reset the index of the NDFrame using a range of indices. - */ - $resetIndex() { - this.$index = utils.range(0, this.shape[0] - 1); - } - - /** - * Returns the column names of the NDFrame - */ - get columns() { - return this.$columns; - } - - /** - * Internal function to set the column names for the NDFrame. This function - * performs a check to ensure that the column names are unique, and same length as the - * number of columns in the data. - */ - $setColumnNames(columns) { - - if (this.$isSeries) { - if (columns) { - if (this.$data.length != 0 && columns.length != 1 && typeof columns != 'string') { - ErrorThrower.throwColumnNamesLengthError(this, columns); - } - this.$columns = columns; - } else { - this.$columns = ["0"]; - } - } else { - if (columns) { - - if (this.$data.length != 0 && columns.length != this.shape[1]) { - - ErrorThrower.throwColumnNamesLengthError(this, columns); - } - if (Array.from(new Set(columns)).length !== this.shape[1]) { - ErrorThrower.throwColumnDuplicateError(); - } - - this.$columns = columns; - } else { - this.$columns = (utils.range(0, this.shape[1] - 1)).map((val) => `${val}`); //generate columns - } - } - } - - /** - * Returns the shape of the NDFrame. Shape is determined by [row lenght, column length] - */ - get shape() { - if (this.$data.length === 0) return [0, 0]; - if (this.$isSeries) { - return [this.$data.length, 1]; - } else { - const rowLen = (this.$data).length; - const colLen = (this.$data[0]).length; - return [rowLen, colLen]; - } - - } - - /** - * Returns the underlying data in Array row format. - */ - get values() { - return this.$data; - } - - /** - * Updates the internal $data property to the specified value - * @param values An array of values to set - * @param checkLength Whether to check the length of the new values and the existing row length - * @param checkColumnLength Whether to check the length of the new values and the existing column length - * */ - $setValues(values, checkLength = true, checkColumnLength = true) { - if (this.$isSeries) { - if (checkLength && values.length != this.shape[0]) { - ErrorThrower.throwRowLengthError(this, values.length); - } - - this.$data = values; - this.$dtypes = utils.inferDtype(values); //Dtype may change depeneding on the value set - - if (!this.$config.isLowMemoryMode) { - this.$dataIncolumnFormat = values; - } - - } else { - if (checkLength && values.length != this.shape[0]) { - ErrorThrower.throwRowLengthError(this, values.length); - } - - if (checkColumnLength) { - values.forEach((value) => { - if ((value).length != this.shape[1]) { - ErrorThrower.throwColumnLengthError(this, values.length); - } - }); - } - - this.$data = values; - this.$dtypes = utils.inferDtype(values); - - if (!this.$config.isLowMemoryMode) { - this.$dataIncolumnFormat = utils.transposeArray(values); - } - - } - - } - - /** - * Returns the underlying data in Array column format. - */ - get getColumnData() { - if (this.config.isLowMemoryMode) { - return utils.transposeArray(this.values); - } else { - return this.$dataIncolumnFormat; - } - } - - /** - * Returns the size of the NDFrame object - * - */ - get size() { - return this.shape[0] * this.shape[1]; - } - - /** - * Converts a DataFrame or Series to CSV. - * @param options Configuration object. Supports the following options: - * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - */ - to_csv(options) { - return toCSV(this, options); - } - - /** - * Converts a DataFrame or Series to JSON. - * @param options Configuration object. Supported options: - * - `fileName`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - */ - to_json(options) { - return toJSON(this, options); - } - - - /** - * Converts a DataFrame or Series to Excel Sheet. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. - */ - to_excel(options) { - return toExcel(this, options); - } - - /** - * Pretty prints a DataFrame or Series to the console - */ - print() { - console.log(this + ""); - } -} diff --git a/danfojs-browser/src/core/get_dummies.js b/danfojs-browser/src/core/get_dummies.js deleted file mode 100644 index dd4297e1..00000000 --- a/danfojs-browser/src/core/get_dummies.js +++ /dev/null @@ -1,151 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import DataFrame from "./frame"; -import Series from "./series"; -import { utils } from "../shared/utils"; - - -/** - * Generate one-hot encoding for categorical columns in an Array, Series or Dataframe. - * @param data Series or Dataframe - * @param columns Columns to encode - * @param prefix Prefix for the new columns - * @param prefixSeparator Separator for the prefix and the column name - * @returns Encoded Dataframe - * @example - * import { DataFrame, DummyEncoder }from 'danfojs'; - * const df = new DataFrame([[1,2,3], [4,5,6]], { columns: ['a', 'b', 'c'] }); - * const df2 = new DummyEncoder({data: df, columns: ['a', 'b'], prefix: 'enc', prefixSeparator: '#'}).encode(); - * df2.print(); - */ -function dummyEncode(data, options) { - let { columns, prefix, prefixSeparator } = { prefixSeparator: "_", ...options }; - - if (!data) { - throw new Error('ParamError: data must be one of Array, Series or DataFrame'); - } - - if (data instanceof Series || data instanceof DataFrame) { - if (!columns) { - const colsWithStringDtype = []; - data.dtypes.forEach((dtype, index) => { - if (dtype === "string") { - colsWithStringDtype.push(data.columns[index]); - } - }); - columns = colsWithStringDtype; - } - } else { - throw new Error('ParamError: data must be one of Array, Series or DataFrame'); - } - - - if (typeof columns === "string") { - columns = [columns]; - if (Array.isArray(prefix) && prefix.length === 1) { - prefix = prefix; - } else if (typeof prefix === "string") { - prefix = [prefix]; - } else { - throw new Error('ParamError: prefix must be a string, or an array of same length as columns'); - } - - if (Array.isArray(prefixSeparator) && prefixSeparator.length === 1) { - prefixSeparator = prefixSeparator; - } else if (typeof prefixSeparator === "string") { - prefixSeparator = [prefixSeparator]; - } else { - throw new Error('ParamError: prefix must be a string, or an array of same length as columns'); - } - } else if (Array.isArray(columns)) { - if (prefix) { - if (Array.isArray(prefix) && prefix.length !== columns.length) { - throw new Error(`ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "${prefix}"}`); - } - - if (typeof prefix === "string") { - prefix = columns.map((_) => prefix); - } - } - - if (prefixSeparator) { - if (Array.isArray(prefixSeparator) && prefixSeparator.length !== columns.length) { - throw new Error(`ParamError: prefixSeparator and data array must be of the same length. If you need to use the same prefix separator, then pass a string param instead. e.g {prefixSeparator: "${prefixSeparator}"}`); - } - - if (typeof prefixSeparator === "string") { - prefixSeparator = columns.map((_) => prefixSeparator); - } - } - - } else { - throw new Error('ParamError: columns must be a string or an array of strings'); - } - - if (data instanceof Series) { - const colData = data.values; - const newColumnNames = []; - const uniqueValues = Array.from(new Set(colData)); - const oneHotArr = utils.zeros(colData.length, uniqueValues.length); - - for (let i = 0; i < colData.length; i++) { - const index = uniqueValues.indexOf(colData[i]); - oneHotArr[i][index] = 1; - } - - for (let i = 0; i < uniqueValues.length; i++) { - const prefixToAdd = prefix ? prefix[0] : i; - newColumnNames.push(`${prefixToAdd}${prefixSeparator[0]}${uniqueValues[i]}`); - - } - - return new DataFrame(oneHotArr, { columns: newColumnNames }); - - } else { - - const dfWithSelectedColumnsDropped = data.drop({ columns }); - let newData = dfWithSelectedColumnsDropped.values; - const newColumnNames = dfWithSelectedColumnsDropped.columns; - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - const colData = data.column(column).values; - - const uniqueValues = Array.from(new Set(colData)); - const oneHotArr = utils.zeros(colData.length, uniqueValues.length); - - for (let j = 0; j < colData.length; j++) { - const index = uniqueValues.indexOf(colData[j]); - oneHotArr[j][index] = 1; - const prefixToAdd = prefix ? prefix[i] : column; - const newColName = `${prefixToAdd}${prefixSeparator[i]}${colData[j]}`; - - if (!newColumnNames.includes(newColName)) { - newColumnNames.push(newColName); - } - } - - for (let k = 0; k < newData.length; k++) { - newData[k] = [...newData[k], ...oneHotArr[k]]; - - } - - } - - return new DataFrame(newData, { columns: newColumnNames }); - } - -} - -export default dummyEncode; diff --git a/danfojs-browser/src/core/groupby.js b/danfojs-browser/src/core/groupby.js deleted file mode 100644 index 2718319c..00000000 --- a/danfojs-browser/src/core/groupby.js +++ /dev/null @@ -1,349 +0,0 @@ -import DataFrame from "./frame"; -import { utils } from "../shared/utils"; -import Series from "./series"; -import { concat } from "./concat"; - -/** - * The class performs all groupby operation on a dataframe - * involveing all aggregate funciton - * @param {col_dict} col_dict Object of unique keys in the group by column - * @param {key_col} key_col Array contains the column names - * @param {data} Array the dataframe data - * @param {column_name} Array of all column name in the dataframe. - */ -export class GroupBy { - constructor(col_dict, key_col, data, column_name, col_dtype) { - - this.key_col = key_col; - this.col_dict = col_dict; - this.data = data; - this.column_name = column_name; - this.data_tensors = {}; //store the tensor version of the groupby data - this.col_dtype = col_dtype; - - } - - /** - * Group the dataframe by the column by - * creating an object to store the grouping - * @returns Groupby data structure - */ - group(){ - for (const value of this.data){ - const col_indexes = this.key_col.map((key) => this.column_name.indexOf(key)); - const col_values = col_indexes.map((idx) => value[idx]); - - let sub_col_dict = this.col_dict; - for (const col_value of col_values){ - if (!(col_value in sub_col_dict)) - break; - if (col_value === col_values[col_values.length - 1]) - sub_col_dict[col_value].push(value); - else - sub_col_dict = sub_col_dict[col_value]; - } - } - - const self = this; - function dfs(sub_col_dict, sub_data_tensors){ - for (const [ key, value ] of Object.entries(sub_col_dict)){ - if (Array.isArray(value)) { - if (value.length === 0) - delete sub_col_dict[key]; - else - sub_data_tensors[key] = new DataFrame(value, { columns:self.column_name }); - } else { - if (!(key in sub_data_tensors)) - sub_data_tensors[key] = {}; - dfs(value, sub_data_tensors[key]); - } - } - } - dfs(this.col_dict, this.data_tensors); - - return this; - } - - /** - * obtain the column for each group - * @param {col_name} col_name [Array]--> array of column names - * @return Groupby data structure - */ - col(col_names){ - this.selected_column = col_names; // store col_names for use later in .apply - if (Array.isArray(col_names)){ - - for (let i = 0; i < col_names.length; i++){ - - let col_name = col_names[i]; - if (!this.column_name.includes(col_name)){ - throw new Error(`Column ${col_name} does not exist in groups`); - } - } - } else { - throw new Error(`Col_name must be an array of column`); - } - - const group_col = {}; - function dfs(sub_data_tensors, sub_group_col) { - for (const [ key, value ] of Object.entries(sub_data_tensors)){ - if (value instanceof DataFrame) { - sub_group_col[key] = col_names.map((col_name) => value.column(col_name)); - } else { - sub_group_col[key] = {}; - dfs(value, sub_group_col[key]); - } - } - } - dfs(this.data_tensors, group_col); - - const gp = new GroupBy( - null, - this.key_col, - null, - col_names, - this.col_dtype - ); - gp.group_col = group_col; - gp.group_col_name = col_names; - return gp; - } - - - /** - * Basic root of all column arithemetic in groups - * @param {operation} operation String - */ - arithemetic(operation){ - const ops_name = [ "mean", "sum", "count", "mode", "std", "var", "cumsum", "cumprod", - "cummax", "cummin" ]; - const ops_map = { - "mean": "mean()", - "sum": "sum()", - "mode": "mode()", - "count": "count()", - "std" : "std()", - "var" : "var()", - "cumsum" : "cumsum().values", - "cumprod": "cumprod().values", - "cummax" : "cummax().values", - "cummin" : "cummin().values" - }; - const is_array_operation = Array.isArray(operation); - const count_group = {}; - - //the local variable to store variables to be used in eval - // this seems not to be needed in Node version, since local - //variable are easily accessed in the eval function - let local = null; - function dfs(sub_count_group, sub_group_col) { - for (const [ key, value ] of Object.entries(sub_group_col)){ - if (Array.isArray(value)) { - sub_count_group[key] = []; - let data; - if (is_array_operation) { - for (let i = 0; i < value.length; i++){ - const op = operation[i]; - if (!ops_name.includes(op)){ - throw new Error("operation does not exist"); - } - local = value[i]; - data = eval(`local.${ops_map[op]}`); - sub_count_group[key].push(data); - } - } else { - value.forEach((v) => { - local = v; - data = eval(`local.${operation}`); - sub_count_group[key].push(data); - }); - } - } else { - sub_count_group[key] = {}; - dfs(sub_count_group[key], value); - } - } - } - - dfs(count_group, this.group_col); - return count_group; - } - - operations(ops, name) { - if (!this.group_col) { - let column = this.column_name.filter((val) => !this.key_col.includes(val)); - let col_gp = this.col(column); - let value = col_gp.arithemetic(ops); - let df = col_gp.to_DataFrame(col_gp.key_col, col_gp.group_col_name, value, name); - return df; - } else { - let value = this.arithemetic(ops); - let df = this.to_DataFrame(this.key_col, this.group_col_name, value, name); - return df; - } - } - count(){ - return this.operations("count()", "count"); - } - - sum(){ - return this.operations("sum()", "sum"); - } - - std(){ - return this.operations("std()", "std"); - } - - var(){ - return this.operations("var()", "var"); - } - - mean(){ - return this.operations("mean()", "mean"); - } - - cumsum(){ - return this.operations("cumsum().values", "cumsum"); - } - cummax(){ - return this.operations("cummax().values", "cummax"); - } - - cumprod(){ - return this.operations("cumprod().values", "cumprod"); - } - - cummin(){ - return this.operations("cummin().values", "cummin"); - } - - max(){ - return this.operations("max()", "max"); - } - - min(){ - return this.operations("min()", "min"); - } - - /** - * returns dataframe of a group - * @param {*} key [Array] - */ - get_groups(key){ - if (this.key_col.length < 2) - return this.data_tensors[key]; - - if (key.length !== this.key_col.length) - throw new Error("specify the group by column"); - - utils.isObject(this.data_tensors, key[0], `Key Error: ${key[0]} not in object`); - const last_key = key[key.length - 1]; - let sub_data_tensors = this.data_tensors; - for (const k of key) { - if (k === last_key) - return sub_data_tensors[k]; - else - sub_data_tensors = sub_data_tensors[k]; - } - } - - /** - * Map every column to an operation - * @param {kwargs} kwargs {column name: math operation} - * @example .agg({"A": "mean","B": "sum","C":"count"}) - */ - agg(kwargs = {}){ - - let columns = Object.keys(kwargs); - let operations = columns.map((x) => { return kwargs[x].toLocaleLowerCase(); }); - - let col_gp = this.col(columns); - - let data = col_gp.arithemetic(operations); - let df = this.to_DataFrame(col_gp.key_col, col_gp.group_col_name, data, operations); - - return df; - } - - to_DataFrame(key_col, col, data, ops){ - const df_data = []; - - function concatPathAndNode(path, node, col_dtype) { - if (Array.isArray(node)) { - if (Array.isArray(node[0])) { - if (ops != "apply" ) { - const transposed_node = node[0].map((_, colIndex) => node.map((row) => row[colIndex])); - for (const n_array of transposed_node) - df_data.push(path.concat(n_array)); - } else { - for (const n_array of node) - df_data.push(path.concat(n_array)); - } - - } else - df_data.push(path.concat(node)); - } else { - for (const [ k, child ] of Object.entries(node)) { - const sanitized_k = col_dtype[0] === "string" ? k : parseInt(k); - concatPathAndNode(path.concat([ sanitized_k ]), child, col_dtype.slice(1)); - } - } - } - - concatPathAndNode([], data, this.col_dtype); - - const column = [ ...key_col ]; - const group_col = col.slice().map((x, i) => { - if (Array.isArray(ops)){ - return `${x}_${ops[i]}`; - } - return `${x}_${ops}`; - }); - column.push(...group_col); - - return new DataFrame(df_data, { columns: column }); - } - - apply(callable){ - let df_data; - let column; - if (!this.group_col) { - column = this.column_name.filter((val) => !this.key_col.includes(val)); - const col_gp = this.col(column); - df_data = col_gp.group_col; - } else { - column = this.group_col_name; - df_data = this.group_col; - } - const count_group = {}; - - function recursiveCount(sub_df_data, sub_count_group) { - for (const [ key, value ] of Object.entries(sub_df_data)) { - if (Array.isArray(value)) { - let callable_value; - if (value.length > 1) { - callable_value = concat({ df_list: value, axis: 1 }); - } else { - callable_value = value[0]; - } - const callable_rslt = callable(callable_value); - if (callable_rslt instanceof DataFrame) { - column = callable_rslt.columns; - sub_count_group[key] = callable_rslt.values; - } else if (callable_rslt instanceof Series) { - sub_count_group[key] = callable_rslt.values; - } else - sub_count_group = callable_rslt; - } else { - sub_count_group[key] = {}; - recursiveCount(value, sub_count_group[key]); - } - } - } - - recursiveCount(df_data, count_group); - - return this.to_DataFrame(this.key_col, column, count_group, "apply"); - } - -} diff --git a/danfojs-browser/src/core/indexing.js b/danfojs-browser/src/core/indexing.js deleted file mode 100644 index e2b5e04d..00000000 --- a/danfojs-browser/src/core/indexing.js +++ /dev/null @@ -1,411 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { utils } from "../shared/utils"; -import Series from "./series"; -import DataFrame from "./frame"; - -// const utils = new Utils(); - -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export function _iloc({ ndFrame, rows, columns }) { - - let _rowIndexes; - let _columnIndexes; - - const _data = ndFrame.values; - const _index = ndFrame.index; - - if (rows instanceof Series) { - rows = rows.values; - } - - if (rows !== undefined && !Array.isArray(rows)) { - throw new Error(`rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); - } - - if (columns !== undefined && !Array.isArray(columns)) { - throw new Error(`columns parameter must be an Array. For example: columns: [1,2] or columns: ["0:10"]`); - } - - if (!rows) { - _rowIndexes = utils.range(0, ndFrame.shape[0] - 1); - - } else if (rows.length == 1 && typeof rows[0] == "string") { - const rowSplit = rows[0].split(":"); - - if (rowSplit.length != 2) { - throw new Error(`Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); - } - if (isNaN(parseInt(rowSplit[0])) && rowSplit[0] != "") { - throw new Error(`Invalid row split parameter. Split parameter must be a number`); - } - - if (isNaN(parseInt(rowSplit[1])) && rowSplit[1] != "") { - throw new Error(`Invalid row split parameter. Split parameter must be a number`); - } - - const start = rowSplit[0] == "" ? 0 : parseInt(rowSplit[0]); - const end = rowSplit[1] == "" ? ndFrame.shape[0] : parseInt(rowSplit[1]); - - if (start < 0) { - throw new Error(`row slice [start] index cannot be less than 0`); - } - - if (end > ndFrame.shape[0]) { - throw new Error(`row slice [end] index cannot be bigger than ${ndFrame.shape[0]}`); - } - _rowIndexes = utils.range(start, end - 1); - } else { - const _formatedRows = []; - for (let i = 0; i < rows.length; i++) { - let _indexToUse = rows[i]; - if (_indexToUse > ndFrame.shape[0]) { - throw new Error(`Invalid row parameter: Specified index ${_indexToUse} cannot be bigger than index length ${ndFrame.shape[0]}`); - } - - if (typeof _indexToUse !== "number" && typeof _indexToUse !== "boolean") { - throw new Error(`Invalid row parameter: row index ${_indexToUse} must be a number or boolean`); - } - - if (typeof _indexToUse === "boolean" && _indexToUse === true) { - _formatedRows.push(_index[i]); - } - - if (typeof _indexToUse === "number") { - _formatedRows.push(_indexToUse); - } - } - - _rowIndexes = _formatedRows; - } - - if (!columns) { - _columnIndexes = utils.range(0, ndFrame.shape[1] - 1); - - } else if (columns.length == 1 && typeof columns[0] == "string") { - const columnSplit = columns[0].split(":"); - - if (columnSplit.length != 2) { - throw new Error(`Invalid column split parameter: If using column split string, it must be of the form; columns: ["start:end"]`); - } - if (isNaN(parseInt(columnSplit[0])) && columnSplit[0] != "") { - throw new Error(`Invalid column split parameter. Split parameter must be a number`); - } - - if (isNaN(parseInt(columnSplit[1])) && columnSplit[1] != "") { - throw new Error(`Invalid column split parameter. Split parameter must be a number`); - } - - const start = columnSplit[0] == "" ? 0 : parseInt(columnSplit[0]); - const end = columnSplit[1] == "" ? ndFrame.shape[1] : parseInt(columnSplit[1]); - - if (start < 0) { - throw new Error(`column slice [start] index cannot be less than 0`); - } - - if (end > ndFrame.shape[1]) { - throw new Error(`column slice [end] index cannot be bigger than ${ndFrame.shape[1]}`); - } - _columnIndexes = utils.range(start, end - 1); - } else { - - for (let i = 0; i < columns.length; i++) { - const _indexToUse = columns[i]; - if (_indexToUse > ndFrame.shape[1]) { - throw new Error(`Invalid column parameter: Specified index ${_indexToUse} cannot be bigger than index length ${ndFrame.shape[1]}`); - } - - if (typeof _indexToUse != "number") { - throw new Error(`Invalid column parameter: column index ${_indexToUse} must be a number`); - } - - } - - _columnIndexes = columns; - } - - if (ndFrame instanceof Series) { - const newData = []; - const newIndex = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - newData.push(_data[rowIndx]); - newIndex.push(_index[rowIndx]); - } - const sf = new Series( - newData, - { - index: newIndex, - columns: ndFrame.columns, - dtypes: ndFrame.dtypes, - config: ndFrame.config - }); - - return sf; - } else { - const newData = []; - const newIndex = []; - const newColumnNames = []; - const newDtypes = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - const rowData = _data[rowIndx]; - const newRowDataWithRequiredCols = []; - - for (let j = 0; j < _columnIndexes.length; j++) { - const colIndx = _columnIndexes[j]; - newRowDataWithRequiredCols.push(rowData[colIndx]); - } - newData.push(newRowDataWithRequiredCols); - newIndex.push(_index[rowIndx]); - } - - for (let i = 0; i < _columnIndexes.length; i++) { - const colIndx = _columnIndexes[i]; - newColumnNames.push(ndFrame.columns[colIndx]); - newDtypes.push(ndFrame.dtypes[colIndx]); - - } - - const df = new DataFrame( - newData, - { - index: newIndex, - columns: newColumnNames, - dtypes: newDtypes, - config: ndFrame.config - }); - - return df; - - } - -} - -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export function _loc({ ndFrame, rows, columns }) { - - let _rowIndexes; - let _columnIndexes; - - const _data = ndFrame.values; - const _index = ndFrame.index; - - if (rows instanceof Series) { - rows = rows.values; - } - - if (rows !== undefined && !Array.isArray(rows)) { - throw new Error(`rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); - } - - if (columns !== undefined && !Array.isArray(columns)) { - throw new Error(`columns parameter must be an Array. For example: columns: ["a","b"] or columns: ["a:c"]`); - } - - if (!rows) { - _rowIndexes = _index.map((indexValue) => _index.indexOf(indexValue)); // Return all row index - - } else if (rows.length === 1 && typeof rows[0] === "string") { - - if (rows[0].indexOf(":") === -1) { // Input type ==> ["1"] or [`"1"`] - let temp; - if (rows[0].startsWith(`"`) || rows[0].startsWith(`'`) || rows[0].startsWith("`")) { - temp = _index.indexOf(rows[0].replace(/['"`]/g, '')); - } else if (typeof rows[0] === "string") { - temp = _index.indexOf(rows[0]); - } else { - temp = _index.indexOf(Number(rows[0])); - } - - if (temp === -1) { - throw new Error(`IndexError: Specified index (${rows[0]}) not found`); - } - - _rowIndexes = [temp]; - - } else { - // Input type ==> ["1:2"] or [`"1":"4"`] - const rowSplit = rows[0].split(":"); - - if (rowSplit.length != 2) { - throw new Error(`Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); - } - - let start; - let end; - - if (rowSplit[0] === "") { - start = _index.indexOf(_index[0]); - } else { - if (rowSplit[0].startsWith(`"`) || rowSplit[0].startsWith(`'`) || rowSplit[0].startsWith("`")) { - start = _index.indexOf(rowSplit[0].replace(/['"`]/g, '')); - } else { - start = _index.indexOf(Number(rowSplit[0])); - } - } - - if (rowSplit[1] === "") { - end = _index.indexOf(_index[_index.length - 1]) + 1; - } else { - if (rowSplit[1].startsWith(`"`) || rowSplit[1].startsWith(`'`) || rowSplit[1].startsWith("`")) { - end = _index.indexOf(rowSplit[1].replace(/['"`]/g, '')); - } else { - end = _index.indexOf(Number(rowSplit[1])); - } - - } - - if (start === -1) { - throw new Error(`IndexError: Specified start index not found`); - } - - if (end === -1) { - throw new Error(`IndexError: Specified end index not found`); - } - - _rowIndexes = _index.slice(start, end).map((indexValue) => _index.indexOf(indexValue)); - } - - } else { - // Input type ==> ["1", "2"] or [1, 5] or [true, false] - const rowsIndexToUse = []; - for (let i = 0; i < rows.length; i++) { - const isBoolean = typeof rows[i] === "boolean"; - if (isBoolean && rows[i]) { - rowsIndexToUse.push(_index.indexOf(_index[i])); - } - - if (!isBoolean) { - const rowIndex = _index.indexOf(rows[i]); - if (rowIndex === -1) { - throw new Error(`IndexError: Specified index (${rows[i]}) not found`); - } - rowsIndexToUse.push(rowIndex); - } - } - - _rowIndexes = rowsIndexToUse; - } - - const _columnNames = ndFrame.columns; - - if (!columns) { - _columnIndexes = _columnNames.map((columnName) => _columnNames.indexOf(columnName));// Return all column index - - } else if (columns.length == 1) { - if (typeof columns[0] !== "string") { - throw new Error(`ColumnIndexError: columns parameter must be an array of a string name. For example: columns: ["b"]`); - } - - if (columns[0].indexOf(":") == -1) { // Input type ==> ["A"] - _columnIndexes = [_columnNames.indexOf(columns[0])]; - - } else { // Input type ==> ["a:b"] or [`"col1":"col5"`] - const columnSplit = columns[0].split(":"); - - if (columnSplit.length != 2) { - throw new Error(`ColumnIndexError: Invalid row split parameter. If using row split string, it must be of the form; rows: ["start:end"]`); - } - - const start = columnSplit[0] == "" ? _columnNames.indexOf(_columnNames[0]) : _columnNames.indexOf(columnSplit[0]); - const end = columnSplit[1] == "" ? _columnNames.indexOf(_columnNames[_columnNames.length - 1]) : _columnNames.indexOf(columnSplit[1]); - - if (start === -1) { - throw new Error(`ColumnIndexError: Specified start index not found`); - } - - if (end === -1) { - throw new Error(`ColumnIndexError: Specified end index not found`); - } - _columnIndexes = _columnNames.slice(start, end + 1).map((columnName) => _columnNames.indexOf(columnName)); - _columnIndexes.pop(); //Remove the last element - - } - } else { // Input type ==> ["A", "B"] or ["col1", "col2"] - for (let i = 0; i < columns.length; i++) { - if (_columnNames.indexOf(columns[i]) === -1) { - throw new Error(`ColumnIndexError: Specified column (${columns[i]}) not found`); - } - } - _columnIndexes = columns.map((columnName) => _columnNames.indexOf(columnName)); - } - - if (ndFrame instanceof Series) { - const newData = []; - const newIndex = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - newData.push(_data[rowIndx]); - newIndex.push(_index[rowIndx]); - } - const sf = new Series( - newData, - { - index: newIndex, - columns: ndFrame.columns, - dtypes: ndFrame.dtypes, - config: ndFrame.config - }); - - return sf; - } else { - const newData = []; - const newIndex = []; - const newColumnNames = []; - const newDtypes = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - const rowData = _data[rowIndx]; - const newRowDataWithRequiredCols = []; - - for (let j = 0; j < _columnIndexes.length; j++) { - const colIndx = _columnIndexes[j]; - newRowDataWithRequiredCols.push(rowData[colIndx]); - } - newData.push(newRowDataWithRequiredCols); - newIndex.push(_index[rowIndx]); - } - - for (let i = 0; i < _columnIndexes.length; i++) { - const colIndx = _columnIndexes[i]; - newColumnNames.push(ndFrame.columns[colIndx]); - newDtypes.push(ndFrame.dtypes[colIndx]); - - } - - const df = new DataFrame( - newData, - { - index: newIndex, - columns: newColumnNames, - dtypes: newDtypes, - config: ndFrame.config - }); - return df; - - } - -} diff --git a/danfojs-browser/src/core/math.ops.js b/danfojs-browser/src/core/math.ops.js deleted file mode 100644 index b6b3f26f..00000000 --- a/danfojs-browser/src/core/math.ops.js +++ /dev/null @@ -1,163 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -import { utils } from "../shared/utils"; - -// const utils = new Utils(); - -/** - * Generic function for performing add, sub, pow, mul and mod operation on a series - * @param object - * - * ndframe ==> The current Series - * - * other ==> The Series or number to perform math operation with - * - * operation ==> The type of operation to perform -*/ -export function _genericMathOp({ ndFrame, other, operation }) { - if (typeof other === 'number') { - //broadcast operation - let newData; - switch (operation) { - case 'add': - newData = (ndFrame.values).map(((ele) => ele + other)); - return newData; - - case 'sub': - newData = (ndFrame.values).map(((ele) => ele - other)); - return newData; - - case 'mul': - newData = (ndFrame.values).map(((ele) => ele * other)); - return newData; - - case 'div': - newData = (ndFrame.values).map(((ele) => ele / other)); - return newData; - - case 'mod': - newData = (ndFrame.values).map(((ele) => ele % other)); - return newData; - - case 'pow': - newData = (ndFrame.values).map(((ele) => ele ** other)); - return newData; - - case 'minimum': - newData = (ndFrame.values).map(((ele) => Math.min(ele, other))); - return newData; - - case 'maximum': - newData = (ndFrame.values).map(((ele) => Math.max(ele, other))); - return newData; - - default: - throw new Error(`${operation} is not implemented`); - - } - } else if (other instanceof Series) { - utils.checkSeriesOpCompactibility({ firstSeries: ndFrame, secondSeries: other, operation }); - - let newData; - switch (operation) { - case 'add': - - newData = (ndFrame.values).map((ele, index) => { return ele + (other.values)[index]; }); - return newData; - - case 'sub': - - newData = (ndFrame.values).map((ele, index) => { return ele - (other.values)[index]; }); - return newData; - - case 'mul': - - newData = (ndFrame.values).map((ele, index) => { return ele * (other.values)[index]; }); - return newData; - - case 'div': - - newData = (ndFrame.values).map((ele, index) => { return ele / (other.values)[index]; }); - return newData; - - case 'mod': - - newData = (ndFrame.values).map((ele, index) => { return ele % (other.values)[index]; }); - return newData; - - case 'pow': - newData = (ndFrame.values).map((ele, index) => { return ele ** (other.values)[index]; }); - return newData; - - case 'minimum': - newData = (ndFrame.values).map((ele, index) => { return Math.min(ele, (other.values)[index]); }); - return newData; - - case 'maximum': - newData = (ndFrame.values).map((ele, index) => { return Math.max(ele, (other.values)[index]); }); - return newData; - - default: - throw new Error(`${operation} is not implemented`); - } - } else if (Array.isArray(other)) { - if (other.length !== ndFrame.values.length){ - throw new Error(`ParamError: Length of array must be equal to length of Series`); - } - let newData; - switch (operation) { - case 'add': - - newData = (ndFrame.values).map((ele, index) => { return ele + (other)[index]; }); - return newData; - - case 'sub': - - newData = (ndFrame.values).map((ele, index) => { return ele - (other)[index]; }); - return newData; - - case 'mul': - - newData = (ndFrame.values).map((ele, index) => { return ele * (other)[index]; }); - return newData; - - case 'div': - - newData = (ndFrame.values).map((ele, index) => { return ele / (other)[index]; }); - return newData; - - case 'mod': - - newData = (ndFrame.values).map((ele, index) => { return ele % (other)[index]; }); - return newData; - - case 'pow': - newData = (ndFrame.values).map((ele, index) => { return ele ** (other)[index]; }); - return newData; - - case 'minimum': - newData = (ndFrame.values).map((ele, index) => { return Math.min(ele, (other)[index]); }); - return newData; - - case 'maximum': - newData = (ndFrame.values).map((ele, index) => { return Math.max(ele, (other)[index]); }); - return newData; - - } - } else { - throw new Error("ParamError: value for other not supported. It must be either a scalar, Array or Series"); - } -} diff --git a/danfojs-browser/src/core/merge.js b/danfojs-browser/src/core/merge.js deleted file mode 100644 index 61e8c503..00000000 --- a/danfojs-browser/src/core/merge.js +++ /dev/null @@ -1,328 +0,0 @@ -import DataFrame from './frame'; -import { utils } from "../shared/utils"; - -export class Merge { - - constructor(kwargs) { - - //check if keys exist in kwargs - utils.keyInObject(kwargs, "left"); - utils.keyInObject(kwargs, "right"); - utils.keyInObject(kwargs, "on"); - // utils.keyInObject(kwargs, "how") - if (!utils.keyInObject(kwargs, "how")){ - this.how = 'inner'; - kwargs['how'] = 'inner'; - } else { - this.how = kwargs['how']; - } - - this.left = null; - this.right = null; - this.on = null; - // this.how = null; - - let how_keys = [ "outer", "inner", "left", "right" ]; - - if ((kwargs["left"] instanceof DataFrame) && (kwargs["right"] instanceof DataFrame)) { - this.left = kwargs["left"]; - this.right = kwargs["right"]; - } else { - throw new Error("The left and right key value must be a dataFrame"); - } - - if (Array.isArray(kwargs["on"])) { - this.on = kwargs["on"]; - } else { - throw new Error("key 'on' must be a list"); - } - - if (how_keys.includes(kwargs["how"])) { - - this.how = kwargs["how"]; - } else { - throw new Error(`${kwargs["how"]} specify in keyword how is not recognise`); - } - - this.left_col_index = []; - this.right_col_index = []; - - //find the index of the columns - for (let i = 0; i < this.on.length; i++) { - - if (this.left.columns.includes(this.on[i]) && this.right.columns.includes(this.on[i])) { - - let left_index = this.left.columns.indexOf(this.on[i]); - let right_index = this.right.columns.indexOf(this.on[i]); - - this.left_col_index.push(left_index); - this.right_col_index.push(right_index); - } - } - - this.left_key_dict = {}; - this.right_key_dict = {}; - - let left_values = this.left.values; - let right_values = this.right.values; - - - /** - * Create a dictionary for both left and right dataframe - containing the key combination of columns used as keys, and - the value of such keys combination are the rows having this - keys combination. - */ - for (let i = 0; i < left_values.length; i++) { - let left_value = left_values[i]; - let left_key_comb_values = []; - - //get the value in the column index - for (let j = 0; j < this.left_col_index.length; j++) { - let index = this.left_col_index[j]; - - left_key_comb_values.push(left_value[index]); - } - //combine into single hashable string - let left_key_comb = left_key_comb_values.join('_'); - - let self = this; // assign the this scope to self - //filter out the value that are not the column key - let left_value_filter = left_value.filter(function (val, index) { - return !self.left_col_index.includes(index); - }); - - //check if the key combination already exist or not - //before storing the key combination and the value - //associated with it - if (utils.keyInObject(this.left_key_dict, left_key_comb)) { - this.left_key_dict[left_key_comb].filters.push(left_value_filter); - } else { - this.left_key_dict[left_key_comb] = { - filters: [left_value_filter], - comb_values: left_key_comb_values - }; - } - - } - for (let i = 0; i < right_values.length; i++) { - let right_value = right_values[i]; - let right_key_comb_values = []; - - for (let j = 0; j < this.right_col_index.length; j++) { - let index = this.right_col_index[j]; - - right_key_comb_values.push(right_value[index]); - } - let right_key_comb = right_key_comb_values.join('_'); - - let self = this; - let right_value_filter = right_value.filter(function (val, index) { - return !self.right_col_index.includes(index); - }); - - if (utils.keyInObject(this.right_key_dict, right_key_comb)) { - this.right_key_dict[right_key_comb].filters.push(right_value_filter); - } else { - this.right_key_dict[right_key_comb] = { - filters: [right_value_filter], - comb_values: right_key_comb_values - }; - } - } - - - //create column - this.__create_columns(); - - let data = null; - switch (this.how) { - - case "outer": - data = this.outer(); - break; - case "inner": - data = this.inner(); - break; - case "left": - data = this.left_merge(); - break; - case "right": - data = this.right_merge(); - break; - } - - // eslint-disable-next-line no-self-assign - let df = new DataFrame(data = data, { columns: this.columns }); - - return df; - } - - __create_columns() { - - let self = this; - self.left_col = self.left.columns.filter((val, index) => { - return !self.left_col_index.includes(index); - }); - - self.right_col = self.right.columns.filter((val, index) => { - return !self.right_col_index.includes(index); - }); - - self.columns = [ ...self.on ]; - let column_duplicate = {}; - - let temp_column = [ ...self.left_col ]; - temp_column.push(...self.right_col); - - for (let i = 0; i < temp_column.length; i++) { - - let col = temp_column[i]; - if (utils.keyInObject(column_duplicate, col)) { - - let col_name = `${col}_${column_duplicate[col]}`; - self.columns.push(col_name); - - column_duplicate[col] += 1; - } else { - self.columns.push(col); - column_duplicate[col] = 1; - } - } - } - - outer() { - - let keys = Object.keys(this.left_key_dict); // obtain the keys of the left dataframe - - keys.push(...Object.keys(this.right_key_dict)); - - keys = Array.from(new Set(keys)); // obtain the unique keys - - let data = this.basic(keys); - - return data; - - } - - inner() { - - let left_keys = Object.keys(this.left_key_dict); - let right_keys = Object.keys(this.right_key_dict); - - let keys = left_keys.filter((val) => { - return right_keys.includes(val); - }); - - let data = this.basic(keys); - - return data; - } - - left_merge() { - - let keys = Object.keys(this.left_key_dict); - let data = this.basic(keys); - - return data; - - } - - right_merge() { - let keys = Object.keys(this.right_key_dict); - let data = this.basic(keys); - - return data; - } - - basic(keys) { - - let data = []; - - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - - let key_array = key.split("_").filter((val) => { - return val != ""; - }); - - if (utils.keyInObject(this.left_key_dict, key)) { - let left_row = this.left_key_dict[key].filters; - let key_array = this.left_key_dict[key].comb_values; - - - for (let left_i = 0; left_i < left_row.length; left_i++) { - - let left_row_row = left_row[left_i]; - - if (utils.keyInObject(this.right_key_dict, key)) { - - let right_row = this.right_key_dict[key].filters; - - for (let r_i = 0; r_i < right_row.length; r_i++) { - - let right_row_row = right_row[r_i]; - - - let inner_data = key_array.slice(0); - inner_data.push(...left_row_row); - inner_data.push(...right_row_row); - - - data.push(inner_data); - } - } else { - let nan_array = Array(this.right_col.length); - - for (let i = 0; i < this.right_col.length; i++) { - nan_array[i] = NaN; - } - - let inner_data = key_array.slice(0); - inner_data.push(...left_row_row); - inner_data.push(...nan_array); - data.push(inner_data); - } - } - } else { - - let right_row = this.right_key_dict[key].filters; - let key_array = this.right_key_dict[key].comb_values; - - for (let i = 0; i < right_row.length; i++) { - - let right_row_row = right_row[i]; - - let nan_array = Array(this.left_col.length); - - for (let j = 0; j < nan_array.length; j++) { - nan_array[j] = NaN; - } - - let inner_data = key_array.slice(0); - inner_data.push(...nan_array); - inner_data.push(...right_row_row); - data.push(inner_data); - } - } - } - return data; - - } -} - - -/** -* Merge DataFrame or named Series objects with a database-style join. -* The join is done on columns or indexes. If joining columns on columns, the DataFrame indexes will be ignored. Otherwise -* if joining indexes on indexes or indexes on a column or columns, the index will be passed on. -* @param {kwargs}{left: DataFrame; -* right: DataFrame | Named Series, Object to merge with; -* on: label, Column or index level names to join on. These must be found in both DataFrames; -* how: {‘left’, ‘right’, ‘outer’, ‘inner’}. Type of merge to be performed. -* @returns {DataFrame} -*/ -export const merge = (kwargs) => { - let merge = new Merge(kwargs); - return merge; -}; diff --git a/danfojs-browser/src/core/series.js b/danfojs-browser/src/core/series.js deleted file mode 100644 index 94e40313..00000000 --- a/danfojs-browser/src/core/series.js +++ /dev/null @@ -1,1362 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { variance, std, median, mode } from 'mathjs'; -import { _genericMathOp } from "./math.ops"; -import { DATA_TYPES } from '../shared/defaults'; -import ErrorThrower from "../shared/errors"; -import { _iloc, _loc } from "./indexing"; -import { utils } from "../shared/utils"; -import NDframe from "./generic"; -import { table } from "table"; -import Str from './strings'; -import Dt from './datetime'; -import dummyEncode from "./get_dummies"; -import { Plot } from "../plotting/plot"; -import { data as tfData } from "@tensorflow/tfjs"; - -// const utils = new Utils(); - -/** - * One-dimensional ndarray with axis labels. - * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. - * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. - * @param data 2D Array, JSON, Tensor, Block of data. - * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * @param options.columns Array of column names. If not specified, column names are auto generated. - * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. - * @param options.config General configuration object for extending or setting NDframe behavior. - */ -export default class Series extends NDframe { - - constructor(data = [], options) { - const { index, columns, dtypes, config } = { index: undefined, columns: undefined, dtypes: undefined, config: undefined, ...options }; - if (Array.isArray(data[0]) || utils.isObject(data[0])) { - data = utils.convert2DArrayToSeriesArray(data); - super({ - data, - index, - columns, - dtypes, - config, - isSeries: true - }); - } else { - super({ - data, - index, - columns, - dtypes, - config, - isSeries: true - }); - } - } - - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc(rows) { - return _iloc({ ndFrame: this, rows }); - } - - /** - * Access a group of rows by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc(rows) { - return _loc({ ndFrame: this, rows }); - } - - /** - * Returns the first n values in a Series - * @param rows The number of rows to return - */ - head(rows = 5) { - return this.iloc([`0:${rows}`]); - } - - /** - * Returns the last n values in a Series - * @param rows The number of rows to return - */ - tail(rows = 5) { - const startIdx = this.shape[0] - rows; - return this.iloc([`${startIdx}:`]); - } - - /** - * Returns specified number of random rows in a Series - * @param num The number of rows to return - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - async sample(num = 5, options) { - const { seed } = { seed: 1, ...options }; - - if (num > this.shape[0]) { - throw new Error("Sample size n cannot be bigger than size of dataset"); - } - if (num < -1 || num == 0) { - throw new Error("Sample size cannot be less than -1 or be equal to 0"); - } - num = num === -1 ? this.shape[0] : num; - - const shuffledIndex = await tfData.array(this.index).shuffle(num, `${seed}`).take(num).toArray(); - const sf = this.iloc(shuffledIndex); - return sf; - } - - /** - * Return Addition of series and other, element-wise (binary operator add). - * Equivalent to series + other - * @param other Series, Array of same length or scalar number to add - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("add"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "add" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Returns the subtraction between a series and other, element-wise (binary operator subtraction). - * Equivalent to series - other - * @param other Number to subtract - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("sub"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "sub" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - - } - - /** - * Return Multiplication of series and other, element-wise (binary operator mul). - * Equivalent to series * other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("mul"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "mul" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Return division of series and other, element-wise (binary operator div). - * Equivalent to series / other - * @param other Series or number to divide with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("div"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "div" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Return Exponential power of series and other, element-wise (binary operator pow). - * Equivalent to series ** other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("pow"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "pow" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Return Modulo of series and other, element-wise (binary operator mod). - * Equivalent to series % other - * @param other Number to modulo with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("mod"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "mod" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Checks if the array value passed has a compatible dtype, removes NaN values, and if - * boolean values are present, converts them to integer values. - * */ - $checkAndCleanValues(values, operation) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError(operation); - values = utils.removeMissingValuesFromArray(values); - - if (this.dtypes[0] == "boolean") { - values = (utils.mapBooleansToIntegers(values, 1)); - } - return values; - } - - /** - * Returns the mean of elements in Series - */ - mean() { - const values = this.$checkAndCleanValues(this.values, "mean"); - return (values.reduce((a, b) => a + b) / values.length); - } - - - /** - * Returns the median of elements in Series - */ - median() { - const values = this.$checkAndCleanValues(this.values, "median"); - return median(values); - } - - /** - * Returns the modal value of elements in Series - */ - mode() { - const values = this.$checkAndCleanValues(this.values, "mode"); - return mode(values); - } - - /** - * Returns the minimum value in a Series - */ - min() { - const values = this.$checkAndCleanValues(this.values, "min"); - let smallestValue = values[0]; - for (let i = 0; i < values.length; i++) { - smallestValue = smallestValue < values[i] ? smallestValue : values[i]; - } - return smallestValue; - } - - /** - * Returns the maximum value in a Series - * @returns {Number} - */ - max() { - const values = this.$checkAndCleanValues(this.values, "max"); - let biggestValue = values[0]; - for (let i = 0; i < values.length; i++) { - biggestValue = biggestValue > values[i] ? biggestValue : values[i]; - } - return biggestValue; - } - - /** - * Return the sum of the values in a series. - */ - sum() { - const values = this.$checkAndCleanValues(this.values, "sum"); - return values.reduce((sum, value) => sum + value, 0); - } - - /** - * Return number of non-null elements in a Series - */ - count() { - const values = utils.removeMissingValuesFromArray(this.values); - return values.length; - } - - /** - * Return maximum of series and other. - * @param other Series or number to check against - */ - maximum(other) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("maximum"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "maximum" }); - return new Series(newData, { - columns: this.columns, - index: this.index - }); - } - - /** - * Return minimum of series and other. - * @param other Series, Numbers to check against - */ - minimum(other) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("maximum"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "minimum" }); - return new Series(newData, { - columns: this.columns, - index: this.index - }); - } - - /** - * Round each value in a Series to the specified number of decimals. - * @param dp Number of Decimal places to round to - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp = 1, options) { - const { inplace } = { inplace: false, ...options }; - - const newValues = utils.round(this.values, dp, true); - - if (inplace) { - this.$setValues(newValues); - } else { - return utils.createNdframeFromNewDataWithOldProps({ - ndFrame: this, - newData: newValues, - isSeries: true - }); - } - - } - - /** - * Return sample standard deviation of elements in Series - */ - std() { - const values = this.$checkAndCleanValues(this.values, "max"); - return std(values); - } - - /** - * Return unbiased variance of elements in a Series. - */ - var() { - const values = this.$checkAndCleanValues(this.values, "max"); - return variance(values); - } - - /** - * Return a boolean same-sized object indicating where elements are NaN. - * NaN and undefined values gets mapped to true, and everything else gets mapped to false. - */ - isna() { - const newData = this.values.map((value) => { - if (isNaN(value) && typeof value != "string") { - return true; - } else { - return false; - } - }); - const sf = new Series(newData, - { - index: this.index, - dtypes: ["boolean"], - config: this.config - }); - return sf; - } - - /** - * Replace all NaN with a specified value - * @param value The value to replace NaN with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(options) { - const { value, inplace } = { value: undefined, inplace: false, ...options }; - - if (!value && typeof value !== 'boolean') { - throw Error('Value Error: Must specify value to replace with'); - } - - const newValues = []; - (this.values).forEach((val) => { - if (isNaN(val) && typeof val != "string") { - newValues.push(value); - } else { - newValues.push(val); - } - }); - - if (inplace) { - this.$setValues(newValues); - } else { - return utils.createNdframeFromNewDataWithOldProps({ - ndFrame: this, - newData: newValues, - isSeries: true - }); - } - } - - - /** - * Sort a Series in ascending or descending order by some criterion. - * @param options Method options - * @param ascending Whether to return sorted values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options) { - const { ascending, inplace } = { inplace: false, ascending: true, ...options }; - - let sortedValues = []; - const rangeIdx = utils.range(0, this.index.length - 1); - let sortedIdx = utils.sortArrayByIndex(rangeIdx, this.values, this.dtypes[0]); - - for (let indx of sortedIdx) { - sortedValues.push(this.values[indx]); - } - - if (ascending) { - sortedValues = sortedValues.reverse(); - sortedIdx = sortedIdx.reverse(); - } - - if (inplace) { - this.$setValues(sortedValues); - this.$setIndex(sortedIdx); - } else { - const sf = new Series(sortedValues, { - index: sortedIdx, - dtypes: this.dtypes, - config: this.config - }); - return sf; - - } - } - - - /** - * Makes a deep copy of a Series - */ - copy() { - const sf = new Series([...this.values], { - columns: [...this.columns], - index: [...this.index], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return sf; - } - - - /** - * Generate descriptive statistics. - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - */ - describe() { - if (this.dtypes[0] == "string") { - throw new Error("DType Error: Cannot generate descriptive statistics for Series with string dtype"); - } else { - - const index = ['count', 'mean', 'std', 'min', 'median', 'max', 'variance']; - const count = this.count(); - const mean = this.mean(); - const std = this.std(); - const min = this.min(); - const median = this.median(); - const max = this.max(); - const variance = this.var(); - - const data = [count, mean, std, min, median, max, variance]; - const sf = new Series(data, { index: index }); - return sf; - - } - } - - - /** - * Returns Series with the index reset. - * This is useful when index is meaningless and needs to be reset to the default before another operation. - */ - reset_index(options) { - const { inplace } = { inplace: false, ...options }; - - if (inplace) { - this.$resetIndex(); - } else { - const sf = this.copy(); - sf.$resetIndex(); - return sf; - } - } - - /** - * Set the Series index (row labels) using an array of the same length. - * @param index Array of new index values, - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options) { - const { index, inplace } = { index: undefined, inplace: false, ...options }; - - if (!index) { - throw Error('Param Error: Must specify index array'); - } - - if (inplace) { - this.$setIndex(index); - } else { - const sf = this.copy(); - sf.$setIndex(index); - return sf; - } - } - - - /** - * map all the element in a column to a variable or function - * @param callable callable can either be a funtion or an object - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - map(callable, options) { - const { inplace } = { inplace: false, ...options }; - - const isCallable = utils.isFunction(callable); - - const data = this.values.map((val) => { - if (isCallable) { - return callable(val); - } else if (utils.isObject(callable)) { - if (val in callable) { - return callable[val]; - } else { - return NaN; - } - } else { - throw new Error("Param Error: callable must either be a function or an object"); - } - }); - - if (inplace) { - this.$setValues(data); - } else { - const sf = this.copy(); - sf.$setValues(data); - return sf; - } - } - - /** - * Applies a function to each element of a Series - * @param callable Function to apply to each element of the series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply(callable, options) { - const { inplace } = { inplace: false, ...options }; - - const isCallable = utils.isFunction(callable); - if (!isCallable) { - throw new Error("Param Error: callable must be a function"); - } - - const data = this.values.map((val) => { - return callable(val); - }); - - if (inplace) { - this.$setValues(data); - } else { - const sf = this.copy(); - sf.$setValues(data); - return sf; - } - } - - /** - * Returns a Series with only the unique value(s) in the original Series - */ - unique() { - const newValues = new Set(this.values); - let series = new Series(Array.from(newValues)); - return series; - } - - /** - * Return the number of unique elements in a Series - */ - nunique() { - return (new Set(this.values)).size; - } - - /** - * Returns unique values and their counts in a Series - */ - value_counts() { - const sData = this.values; - const dataDict = {}; - for (let i = 0; i < sData.length; i++) { - const val = sData[i]; - if (`${val}` in dataDict) { - dataDict[`${val}`] = dataDict[`${val}`] + 1; - } else { - dataDict[`${val}`] = 1; - } - } - - const index = Object.keys(dataDict).map((x) => { - return parseInt(x) ? parseInt(x) : x; - }); - const data = Object.values(dataDict); - - const series = new Series(data, { index: index }); - return series; - - } - - /** - * Returns the absolute values in Series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("abs"); - let newValues; - - - newValues = this.values.map((val) => Math.abs(val)); - - if (inplace) { - this.$setValues(newValues); - } else { - const sf = this.copy(); - sf.$setValues(newValues); - return sf; - } - } - - /** - * Returns the cumulative sum over a Series - */ - cumsum(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("sum", ops); - } - - /** - * Returns cumulative minimum over a Series - */ - cummin(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("min", ops); - } - - - /** - * Returns cumulative maximum over a Series - */ - cummax(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("max", ops); - } - - /** - * Returns cumulative product over a Series - */ - cumprod(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("prod", ops); - } - - /** - * perform cumulative operation on series data - */ - cumOps(ops, options) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError(ops); - const { inplace } = options; - - const sData = this.values; - let tempval = sData[0]; - const data = [tempval]; - - for (let i = 1; i < sData.length; i++) { - let currVal = sData[i]; - switch (ops) { - case "max": - if (currVal > tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "min": - if (currVal < tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "sum": - tempval = (tempval) + (currVal); - data.push(tempval); - break; - case "prod": - tempval = (tempval) * (currVal); - data.push(tempval); - break; - - } - } - - if (inplace) { - this.$setValues(data); - } else { - return new Series(data, { - index: this.index, - config: { ...this.config } - }); - } - } - - - /** - * Returns less than of series and other. Supports element wise operations - * @param other Series or number to compare against - */ - lt(other) { - return this.boolOps(other, "lt"); - } - - /** - * Returns Greater than of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - gt(other) { - return this.boolOps(other, "gt"); - } - - /** - * Returns Less than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - le(other) { - return this.boolOps(other, "le"); - } - - /** - * Returns Greater than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ge(other) { - return this.boolOps(other, "ge"); - } - - /** - * Returns Not Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ne(other) { - return this.boolOps(other, "ne"); - } - - /** - * Returns Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - eq(other) { - return this.boolOps(other, "eq"); - } - - /** - * Perform boolean operations on bool values - * @param other Other Series or number to compare with - * @param bOps Name of operation to perform [ne, ge, le, gt, lt, eq] - */ - boolOps(other, bOps) { - const data = []; - const lSeries = this.values; - let rSeries; - - if (typeof other == "number") { - rSeries = Array(this.values.length).fill(other); //create array of repeated value for broadcasting - } else if (typeof other == "string" && ["eq", "ne"].includes(bOps)) { - rSeries = Array(this.values.length).fill(other); - } else if (other instanceof Series) { - rSeries = other.values; - } else if (Array.isArray(other)) { - rSeries = other; - } else { - throw new Error("ParamError: value for other not supported. It must be either a scalar, Array or Series"); - } - - if (!(lSeries.length === rSeries.length)) { - throw new Error("LengthError: Lenght of other must be equal to length of Series"); - } - - - for (let i = 0; i < lSeries.length; i++) { - let lVal = lSeries[i]; - let rVal = rSeries[i]; - let bool = null; - switch (bOps) { - case "lt": - bool = lVal < rVal ? true : false; - data.push(bool); - break; - case "gt": - bool = lVal > rVal ? true : false; - data.push(bool); - break; - case "le": - bool = lVal <= rVal ? true : false; - data.push(bool); - break; - case "ge": - bool = lVal >= rVal ? true : false; - data.push(bool); - break; - case "ne": - bool = lVal !== rVal ? true : false; - data.push(bool); - break; - case "eq": - bool = lVal === rVal ? true : false; - data.push(bool); - break; - } - } - - return new Series(data, { - index: this.index, - config: { ...this.config } - }); - - } - - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace(options) { - const { oldValue, newValue, inplace } = { oldValue: undefined, newValue: undefined, inplace: false, ...options }; - - if (!oldValue && typeof oldValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'oldValue' to replace`); - } - - if (!newValue && typeof newValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'newValue' to replace with`); - } - - const newArr = [...this.values].map((val) => { - if (val === oldValue) { - return newValue; - } else { - return val; - } - }); - - if (inplace) { - this.$setValues(newArr); - } else { - const sf = this.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - /** - * Drops all missing values (NaN) from a Series. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(options) { - const { inplace } = { inplace: false, ...options }; - - const oldValues = this.values; - const oldIndex = this.index; - const newValues = []; - const newIndex = []; - const isNaVals = this.isna().values; - - isNaVals.forEach((val, i) => { - if (!val) { - newValues.push((oldValues)[i]); - newIndex.push(oldIndex[i]); - } - }); - - if (inplace) { - this.$setValues(newValues, false); - this.$setIndex(newIndex); - } else { - const sf = this.copy(); - sf.$setValues(newValues, false); - sf.$setIndex(newIndex); - return sf; - } - - } - - /** - * Return the integer indices that would sort the Series. - * @param ascending boolean true: will sort the Series in ascending order, false: will sort in descending order - */ - argsort(ascending = true) { - const sortedIndex = this.sort_values(ascending); - const sf = new Series(sortedIndex.index); - return sf; - } - - /** - * Return int position of the largest value in the Series. - */ - argmax() { - return this.tensor.argMax().arraySync(); - } - - - /** - * Return int position of the smallest value in the Series. - */ - argmin() { - return this.tensor.argMin().arraySync(); - } - - /** - * Remove duplicate values from a Series - * @param keep "first" | "last", which dupliate value to keep. Defaults to "first". - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop_duplicates(options) { - const { keep, inplace } = { keep: "first", inplace: false, ...options }; - - if (!(["first", "last"].includes(keep))) { - throw Error(`Params Error: Keep must be one of 'first' or 'last'`); - } - - let dataArr; - let newArr = []; - let oldIndex; - let newIndex = []; - - if (keep === "last") { - dataArr = (this.values).reverse(); - oldIndex = this.index.reverse(); - } else { - dataArr = (this.values); - oldIndex = this.index; - } - - dataArr.forEach((val, i) => { - if (!newArr.includes(val)) { - newIndex.push(oldIndex[i]); - newArr.push(val); - } - }); - - if (keep === "last") { - //re-reversed the array and index to its true order - newArr = newArr.reverse(); - newIndex = newIndex.reverse(); - } - - if (inplace) { - this.$setValues(newArr, false); - this.$setIndex(newIndex); - } else { - const sf = this.copy(); - sf.$setValues(newArr, false); - sf.$setIndex(newIndex); - return sf; - } - - } - - /** - * Cast Series to specified data type - * @param dtype Data type to cast to. One of [float32, int32, string, boolean, undefined] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(dtype, options) { - const { inplace } = { inplace: false, ...options }; - - if (!dtype) { - throw Error("Param Error: Please specify dtype to cast to"); - } - - if (!(DATA_TYPES.includes(dtype))) { - throw Error(`dtype ${dtype} not supported. dtype must be one of ${DATA_TYPES}`); - } - - const oldValues = [...this.values]; - const newValues = []; - - switch (dtype) { - case "float32": - oldValues.forEach((val) => { - newValues.push(Number(val)); - }); - break; - case "int32": - oldValues.forEach((val) => { - newValues.push(parseInt(val)); - }); - break; - case "string": - oldValues.forEach((val) => { - newValues.push(String(val)); - }); - break; - case "boolean": - oldValues.forEach((val) => { - newValues.push(Boolean(val)); - }); - break; - case "undefined": - oldValues.forEach((_) => { - newValues.push(NaN); - }); - break; - default: - break; - } - - if (inplace) { - this.$setValues(newValues, false); - this.$setDtypes([dtype]); - } else { - const sf = this.copy(); - sf.$setValues(newValues, false); - sf.$setDtypes([dtype]); - return sf; - } - - } - - /** - * Add a new value or values to the end of a Series - * @param newValues Single value | Array | Series to append to the Series - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append( - newValue, - index, - options - ) { - const { inplace } = { inplace: false, ...options }; - - if (!newValue && typeof newValue !== "boolean") { - throw Error("Param Error: newValues cannot be null or undefined"); - } - - if (!index) { - throw Error("Param Error: index cannot be null or undefined"); - } - - const newData = [...this.values]; - const newIndx = [...this.index]; - - if (Array.isArray(newValue) && Array.isArray(index)) { - - if (newValue.length !== index.length) { - throw Error("Param Error: Length of new values and index must be the same"); - } - - newValue.forEach((el, i) => { - newData.push(el); - newIndx.push(index[i]); - }); - - } else if (newValue instanceof Series) { - const _value = newValue.values; - - if (!Array.isArray(index)) { - throw Error("Param Error: index must be an array"); - } - - if (index.length !== _value.length) { - throw Error("Param Error: Length of new values and index must be the same"); - } - - _value.forEach((el, i) => { - newData.push(el); - newIndx.push(index[i]); - }); - } else { - newData.push(newValue); - newIndx.push(index); - } - - if (inplace) { - this.$setValues(newData, false); - this.$setIndex(newIndx); - } else { - const sf = new Series( - newData, - { - index: newIndx, - columns: this.columns, - dtypes: this.dtypes, - config: this.config - }); - - return sf; - } - } - - /** - * Returns dtype of Series - */ - get dtype() { - return this.dtypes[0]; - } - - /** - * Exposes numerous string methods to manipulate Series of type string - */ - get str() { - if (this.dtypes[0] == "string") { - return new Str(this); - } else { - throw new Error("Cannot call accessor str on non-string type"); - } - } - - /** - * Returns time class that exposes different date time method - */ - get dt() { - if (this.dtypes[0] == "string") { - return new Dt(this); - } else { - throw new Error("Cannot call accessor dt on non-string type"); - } - } - - /** - * Prints Series to console as a grid of row and columns. - */ - toString() { - const maxRow = this.$config.getMaxRow; - let indx; - let values = []; - - if (this.shape[0] > maxRow) { - //slice rows to show [max_rows] rows - const sfSlice = this.iloc([`0:${maxRow}`]); - - indx = sfSlice.index; - values = sfSlice.values; - - } else { - indx = this.index; - values = this.values; - } - - const tabledata = values.map((x, i) => [indx[i], x]); - return table(tabledata); - } - - /** - * Returns the logical AND between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - and(other) { - - if (other === undefined) { - throw new Error("Param Error: other cannot be undefined"); - } - const newValues = []; - - if (other instanceof Series) { - if (this.dtypes[0] !== other.dtypes[0]) { - throw new Error("Param Error must be of same dtype"); - } - - if (this.shape[0] !== other.shape[0]) { - throw new Error("Param Error must be of same shape"); - } - this.values.forEach((val, i) => { - newValues.push(Boolean(val) && Boolean(other.values[i])); - }); - - } else if (Array.isArray(other)) { - - this.values.forEach((val, i) => { - newValues.push(Boolean(val) && Boolean(other[i])); - }); - - } else { - - this.values.forEach((val) => { - newValues.push(Boolean(val) && Boolean(other)); - }); - - } - - return new Series(newValues, { - index: this.index, - config: { ...this.config } - }); - } - - /** - * Returns the logical OR between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - or(other) { - - if (other === undefined) { - throw new Error("Param Error: other cannot be undefined"); - } - const newValues = []; - - if (other instanceof Series) { - if (this.dtypes[0] !== other.dtypes[0]) { - throw new Error("Param Error must be of same dtype"); - } - - if (this.shape[0] !== other.shape[0]) { - throw new Error("Param Error must be of same shape"); - } - - this.values.forEach((val, i) => { - newValues.push(Boolean(val) || (other.values[i])); - }); - - } else if (typeof other === "boolean") { - - this.values.forEach((val) => { - newValues.push(Boolean(val) || (other)); - }); - - } else if (Array.isArray(other)) { - - this.values.forEach((val, i) => { - newValues.push(Boolean(val) || (other[i])); - }); - - } else { - throw new Error("Param Error: other must be a Series, Scalar, or Array of Scalars"); - } - - return new Series(newValues, { - index: this.index, - config: { ...this.config } - }); - } - - /** - * One-hot encode values in the Series. - * @param options Options for the operation. The following options are available: - * - `prefix`: Prefix to add to the new column. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * @returns A DataFrame with the one-hot encoded columns. - * @example - * sf.get_dummies() - * sf.get_dummies({prefix: 'cat' }) - * sf.get_dummies({ prefix: 'cat', prefixSeparator: '-' }) - */ - get_dummies(options) { - return dummyEncode(this, options); - } - - /** - * Make plots of Series or DataFrame. - * Uses the Plotly as backend, so supports Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @returns {Class} Plot class that expoese different plot type - */ - plot(div) { - const plt = new Plot(this, div); - return plt; - } -} diff --git a/danfojs-browser/src/core/strings.js b/danfojs-browser/src/core/strings.js deleted file mode 100644 index 5ecb28ff..00000000 --- a/danfojs-browser/src/core/strings.js +++ /dev/null @@ -1,739 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -/** - * Exposes numerous String methods. All methods are applied Element-wise - */ -export default class Str { - constructor(series) { - this.series = series; - this.values = (series.values); - } - - /** - * Converts all characters to lowercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toLowerCase() - * console.log(newSf.values) - * // ["good", "bad", "crazy"] - * ``` - */ - toLowerCase(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.toLowerCase()); - } - - }); - - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - /** - * Converts all characters to uppercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toUpperCase() - * console.log(newSf.values) - * // ["GOOD", "BAD", "CRAZY"] - * ``` - */ - toUpperCase(options){ - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.toUpperCase()); - } - - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - - } - } - - /** - * Capitalize first string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.capitalize() - * console.log(newSf.values) - * // ["Good", "Bad", "Crazy"] - * ``` - */ - capitalize(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - let firstChar = `${val}`.slice(0, 1); - let leftChar = `${val}`.slice(1); - let newStr = `${firstChar.toUpperCase()}${leftChar.toLowerCase()}`; - newArr.push(newStr); - } - - }); - - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - /** - * Returns the character at the specified index (position) - * @param index position of character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.charAt(1) - * console.log(newSf.values) - * // ["o", "a", "r"] - * ``` - */ - charAt(index = 0, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.charAt(index)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Joins specified `other` with values in the Series. - * @param other string|values to concatenate with. - * @param position where to concat the string from. O concats from the start, 1 concats from the end. Defaults to 1. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.concat("_new") - * console.log(newSf.values) - * // ["Good_new", "bad_new", "crazy_new" - * ``` - */ - concat(other, position = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - - if (Array.isArray(other)) { - for (let i = 0; i < other.length; i++) { - let leftStr = `${this.values[i]}`; - let rightStr = `${other[i]}`; - if (position == 1) { - newArr.push(leftStr.concat(rightStr)); - } else { - newArr.push(rightStr.concat(leftStr)); - } - - } - } else { - this.values.map((val) => { - if (position == 1) { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.concat(`${other}`)); - } - - } else { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(other.concat(`${val}`)); - } - } - }); - } - - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - - /** - * Checks whether a string begins with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.startsWith("G") - * console.log(newSf.values) - * // [true, false, false] - * ``` - */ - startsWith(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.forEach((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.startsWith(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Checks whether a string ends with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.endsWith("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - endsWith(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.endsWith(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Checks whether a string contains the specified string/characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.includes("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - includes(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.includes(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Returns the position of the first occurrence of a specified value in a string. - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.indexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - indexOf(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.indexOf(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Returns the position of the last found occurrence of a specified value in a string - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.lastIndexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - lastIndexOf(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.lastIndexOf(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - - /** - * Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced - * @param searchValue String | Character value to replace - * @param replaceValue String | Character string to replace with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace("d", 7) - * console.log(newSf.values) - * // ["Goo7", "o77", "crazy"] - * ``` - */ - replace(searchValue = "", replaceValue = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.replace(searchValue, replaceValue)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Returns a new string with a specified number of copies of an existing string - * @param num Number of times to repeat - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace(2) - * console.log(newSf.values) - * // ["GoodGood", "oddodd", "crazycrazy"] - * ``` - */ - repeat(num = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.repeat(num)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - - /** - * Searches a string for a specified value, or regular expression, and returns the position of the match - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.search("d") - * console.log(newSf.values) - * ``` - */ - search(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.search(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Extracts a part of a string and returns a new string - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.slice(0,1) - * console.log(newSf.values) - * // ["G", "o", "c"] - * ``` - */ - slice(startIndex = 0, endIndex = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.slice(startIndex, endIndex)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Splits a string into an values of substrings - * @param splitVal string or character to split at - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.split(d) - * console.log(newSf.values) - * ``` - */ - split(splitVal = " ", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${String(val).split(splitVal)}`); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Extracts the characters from a string, beginning at a specified start position, and through the specified number of character - * @param startIndex index position of start character - * @param num number of characters to return - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substr(d) - * ``` - */ - substr(startIndex = 0, num = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${String(val).substr(startIndex, num)}`); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Extracts the characters from a string, between two specified indices - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substring(d) - * ``` - */ - substring(startIndex = 0, endIndex = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${String(val).substring(startIndex, endIndex)}`); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Removes whitespace from both ends of a string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series([" Good", "odd ", " grade "]) - * const newSf = sf.str.trim(d) - * ["Good", "odd", "grade"] - * ``` - */ - trim(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.trim()); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Joins strings to specified value - * @param valToJoin string value to join to the values - * @param joinChar Character to Join with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.join("new", "_") - * // ["Good_new", "odd_new", "grade_new"] - * ``` - */ - join(valToJoin = "", joinChar = " ", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - let leftChar = val; - let rightChar = valToJoin; - let new_char = `${leftChar}${joinChar}${rightChar}`; - newArr.push(new_char); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Counts the number of characters in string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.len(d) - * // [4,3,5] - * ``` - */ - len(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.length); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - -} diff --git a/danfojs-browser/src/index.js b/danfojs-browser/src/index.js deleted file mode 100644 index a5826c87..00000000 --- a/danfojs-browser/src/index.js +++ /dev/null @@ -1,49 +0,0 @@ -import * as tf from "@tensorflow/tfjs"; -import NDframe from "./core/generic"; -import { utils } from './shared/utils'; -import Series from "./core/series"; -import DataFrame from "./core/frame"; -import { concat } from "./core/concat"; -import { merge } from "./core/merge"; -import { LabelEncoder, OneHotEncoder } from "./preprocessing/encodings"; -import { MinMaxScaler, StandardScaler } from "./preprocessing/scalers"; -import { date_range } from "./core/date_range"; -import get_dummies from "./core/get_dummies"; -import Str from "./core/strings"; -import Dt from "./core/datetime"; -import { toDateTime } from "./core/datetime"; -import { - readCSV as read_csv, - toCSV as to_csv, - readJSON as read_json, - toJSON as to_json, - readExcel as read_excel, - toExcel as to_excel } from "./io"; - - -export { - tf, - date_range, - toDateTime, - concat, - merge, - NDframe, - utils, - Str, - Dt, - Series, - DataFrame, - read_csv, - to_csv, - read_json, - to_json, - read_excel, - to_excel, - MinMaxScaler, - StandardScaler, - LabelEncoder, - OneHotEncoder, - get_dummies -}; - -export const _version = "0.3.4"; diff --git a/danfojs-browser/src/io/io.csv.js b/danfojs-browser/src/io/io.csv.js deleted file mode 100644 index 0fb5306d..00000000 --- a/danfojs-browser/src/io/io.csv.js +++ /dev/null @@ -1,137 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Papa from 'papaparse'; -import { DataFrame } from '../index'; - - -/** - * Reads a CSV file from local or remote location into a DataFrame. - * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, - * hence all PapaParse options are supported. - * @param options Configuration object. Supports all Papaparse parse config options. See https://papaparse.com/docs#config. - * @returns DataFrame containing the parsed CSV file. - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv") - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv", { - * delimiter: ",", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("./data/sample.csv") - * ``` - */ -const $readCSV = async (filePath, options) => { - options = { header: true, dynamicTyping: true, ...options }; - return new Promise((resolve) => { - Papa.parse(filePath, { - ...options, - download: true, - complete: (results) => { - const df = new DataFrame(results.data); - resolve(df); - } - }); - }); -}; - - -/** - * Converts a DataFrame or Series to CSV. - * @param df DataFrame or Series to be converted to CSV. - * @param options Configuration object. Supports the following options: - * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const csv = toCSV(df) - * ``` - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toCSV(df, { - * filePath: "./data/sample.csv", - * header: true, - * sep: "+" - * }) - * ``` - */ -const $toCSV = (df, options) => { - let { fileName, download, sep, header } = { fileName: "output.csv", sep: ",", header: true, download: true, ...options }; - - if (df.$isSeries) { - const csv = df.values.join(sep); - - if (download) { - if (!(fileName.endsWith(".csv"))) { - fileName = fileName + ".csv"; - } - $downloadFileInBrowser(csv, fileName); - } else { - return csv; - } - } else { - const rows = df.values; - let csvStr = header === true ? `${df.columns.join(sep)}\n` : ""; - - for (let i = 0; i < rows.length; i++) { - const row = `${rows[i].join(sep)}\n`; - csvStr += row; - } - - if (download) { - if (!(fileName.endsWith(".csv"))) { - fileName = fileName + ".csv"; - } - $downloadFileInBrowser(csvStr, fileName); - } else { - return csvStr; - } - } -}; - -/** - * Function to download a CSV file in the browser. - * @param content A string of CSV file contents - * @param fileName The name of the file to be downloaded - */ -const $downloadFileInBrowser = (content, fileName) => { - var hiddenElement = document.createElement('a'); - hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(content); - hiddenElement.target = '_blank'; - hiddenElement.download = fileName; - hiddenElement.click(); -}; - - -export { - $readCSV, - $toCSV -}; diff --git a/danfojs-browser/src/io/io.excel.js b/danfojs-browser/src/io/io.excel.js deleted file mode 100644 index 2063b80c..00000000 --- a/danfojs-browser/src/io/io.excel.js +++ /dev/null @@ -1,120 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { DataFrame, NDframe, Series } from '../index'; -import XLSX from 'xlsx'; - -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param file URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx") - * ``` - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx", { - * method: "GET", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - */ -const $readExcel = async (file, options) => { - const { sheet, method, headers } = { sheet: 0, method: "GET", headers: {}, ...options }; - - if (typeof file === "string" && file.startsWith("http")) { - - return new Promise((resolve) => { - fetch(file, { method, headers }).then((response) => { - if (response.status !== 200) { - throw new Error(`Failed to load ${file}`); - } - response.arrayBuffer().then((arrBuf) => { - const arrBufInt8 = new Uint8Array(arrBuf); - const workbook = XLSX.read(arrBufInt8, { type: "array" }); - const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; - const data = XLSX.utils.sheet_to_json(worksheet); - const df = new DataFrame(data); - resolve(df); - }); - }).catch((err) => { - throw new Error(err); - }); - }); - - } else if (file instanceof File) { - const arrBuf = await file.arrayBuffer(); - const arrBufInt8 = new Uint8Array(arrBuf); - const workbook = XLSX.read(arrBufInt8, { type: "array" }); - const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; - const data = XLSX.utils.sheet_to_json(worksheet); - const df = new DataFrame(data); - return df; - } else { - throw new Error("ParamError: File not supported. file must be a url or an input File object"); - } -}; - -/** - * Converts a DataFrame or Series to Excel Sheet. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `file`: The file to be written to. Defaults to `'./output.xlsx'`. - * @example - * ``` - * import { toExcel } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toExcel(df, { - * file: "./data/sample.xlsx", - * sheetName: "MySheet", - * }) - * ``` - */ -const $toExcel = (df, options) => { - let { fileName, sheetName } = { fileName: "./output.xlsx", sheetName: "Sheet1", ...options }; - - if (!(fileName.endsWith(".xlsx"))) { - fileName = fileName + ".xlsx"; - } - let data; - - if (df.$isSeries) { - const row = df.values; - const col = df.columns; - data = [ col, ...(row.map((x) => [ x ])) ]; - } else { - const row = df.values; - const cols = df.columns; - data = [ cols, ...row ]; - } - - const worksheet = XLSX.utils.aoa_to_sheet(data); - const wb = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(wb, worksheet, sheetName); - XLSX.writeFile(wb, `${fileName}`); -}; - -export { - $readExcel, - $toExcel -}; diff --git a/danfojs-browser/src/io/io.json.js b/danfojs-browser/src/io/io.json.js deleted file mode 100644 index f8b3d929..00000000 --- a/danfojs-browser/src/io/io.json.js +++ /dev/null @@ -1,167 +0,0 @@ -import { DataFrame, NDframe, Series } from '../index'; - -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param fileName URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json") - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json", { - * headers: { - * Accept: "text/json", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("./data/sample.json") - * ``` - */ -const $readJSON = async (file, options) => { - const { method, headers } = { method: "GET", headers: {}, ...options }; - - if (typeof file === "string" && file.startsWith("http")) { - - return new Promise((resolve) => { - fetch(file, { method, headers }).then((response) => { - if (response.status !== 200) { - throw new Error(`Failed to load ${file}`); - } - response.json().then((json) => { - resolve(new DataFrame(json)); - }); - }).catch((err) => { - throw new Error(err); - }); - }); - - } else if (file instanceof File) { - return new Promise((resolve) => { - const reader = new FileReader(); - reader.readAsText(file); - reader.onload = (event) => { - const jsonObj = JSON.parse(event.target.result); - resolve(new DataFrame(jsonObj)); - }; - }); - } else { - throw new Error("ParamError: File not supported. file must be a url or an input File object"); - } -}; - - -/** - * Converts a DataFrame or Series to JSON. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `fileName`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const json = toJSON(df) - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toJSON(df, { - * fileName: "./data/sample.json", - * format: "row" - * }) - * ``` - */ -const $toJSON = (df, options) => { - let { fileName, format, download } = { fileName: "output.json", download: true, format: "column", ...options }; - - if (df.$isSeries) { - const obj = {}; - obj[df.columns[0]] = df.values; - - if (download) { - if (!fileName.endsWith(".json")) { - fileName = fileName + ".json"; - } - $downloadFileInBrowser(obj, fileName); - } else { - return obj; - } - - } else { - if (format === "row") { - const obj = {}; - for (let i = 0; i < df.columns.length; i++) { - obj[df.columns[i]] = (df).column(df.columns[i]).values; - } - if (download) { - if (!(fileName.endsWith(".json"))) { - fileName = fileName + ".json"; - } - - $downloadFileInBrowser(obj, fileName); - } else { - return obj; - } - } else { - const values = df.values; - const header = df.columns; - const jsonArr = []; - - values.forEach((val) => { - const obj = {}; - header.forEach((h, i) => { - obj[h] = val[i]; - }); - jsonArr.push(obj); - }); - if (download) { - if (!fileName.endsWith(".json")) { - fileName = fileName + ".json"; - } - $downloadFileInBrowser(jsonArr, fileName); - } else { - return jsonArr; - } - } - } -}; - -/** - * Function to download a CSV file in the browser. - * @param content A string of CSV file contents - * @param fileName The name of the file to be downloaded - */ -const $downloadFileInBrowser = (content, fileName) => { - var hiddenElement = document.createElement('a'); - hiddenElement.href = 'data:text/json;charset=utf-8,' + encodeURI(JSON.stringify(content)); - hiddenElement.target = '_blank'; - hiddenElement.download = fileName; - hiddenElement.click(); -}; - - -export { - $readJSON, - $toJSON -}; diff --git a/danfojs-browser/src/plotting/plot.js b/danfojs-browser/src/plotting/plot.js deleted file mode 100644 index 643908a1..00000000 --- a/danfojs-browser/src/plotting/plot.js +++ /dev/null @@ -1,867 +0,0 @@ -/* eslint-disable no-undef */ -import { utils } from "../shared/utils"; -import Series from "../core/series"; - -/** - * Change: Rising Odegua 6th Feb 2021 - * We no longer bundle Plotjs with DanfoJs. I noticed that removing this single - * inport reduces the bundle size from 5.7mb to 2.1mb. I know it's still a huge - * bundle, but it's progress! - * If you need to use Plotly, then you can add the Plotly CDN - * to your script before DanfoJs CDN - */ -try { - const version = Plotly.version; - console.info(`Using Plotly version ${version}`); -} catch (error) { - console.info(`Plotly CDN not found. If you need to make Plots, then add the Plotly CDN to your script`); -} - -/** - * Plotting methods and Functions performed on Series and DataFrames - */ -export class Plot { - constructor(ndframe, div) { - this.div = div; - this.ndframe = ndframe; - } - - - /** - * Plot Series or DataFrame as lines. This function is useful to plot lines using DataFrame’s values as coordinates. - * Make plots of Series or DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - line(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!(param == "layout")) { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "line"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - if (utils.keyInObject(this_config, 'x')) { - trace["x"] = this.ndframe[this_config['x']].values; - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - } else { - trace["y"] = this.ndframe[this_config['y']].values; - trace["x"] = this.ndframe[c_name].values; - trace['name'] = c_name; - } - - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - trace["x"] = this.ndframe.index; - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot Series or DataFrame as Bars. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - bar(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "bar"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = "bar"; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['y'] = this.ndframe[this_config['x']].values; - } else { - trace['y'] = this.ndframe[this_config['y']].values; - } - trace['type'] = "bar"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - // params.forEach(param => { //TODO accept individual configuration for traces - // trace[param] = config[param] - // }) - trace['x'] = this.ndframe.index; - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = "bar"; - - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot two or more columns in a DataFrame as scatter points. If Series, plot against its index - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - scatter(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["x"] = this.ndframe.values; - trace['y'] = this.ndframe.index; - trace['type'] = "scatter"; - trace['mode'] = "markers"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = "scatter"; - trace['mode'] = "markers"; - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['y'] = this.ndframe.index; - trace['x'] = this.ndframe[this_config['x']].values; - - } else { - trace['x'] = this.ndframe.index; - trace['y'] = this.ndframe[this_config['y']].values; - - } - trace['type'] = "scatter"; - trace['mode'] = "markers"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - // params.forEach(param => { //TODO accept individual configuration for traces - // trace[param] = config[param] - // }) - trace['y'] = this.ndframe.index; - trace["x"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = "scatter"; - trace['mode'] = "markers"; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot columns in a Series/DataFrame as Histograms. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - hist(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["x"] = this.ndframe.values; - trace['type'] = "histogram"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x')) { - //plot as vertical histogram - let trace = {}; - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace['x'] = this.ndframe[this_config['x']].values; - trace['type'] = "histogram"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'y')) { - //plot as vertical histogram - let trace = {}; - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace['y'] = this.ndframe[this_config['y']].values; - trace['type'] = "histogram"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - trace["x"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = "histogram"; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - /** - * Makes Pie Plots from two Columns in a DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - pie(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - - - if (this.ndframe instanceof Series) { - let data = [{ - values: this.ndframe.values, - labels: this.ndframe.index, - type: 'pie', - name: this_config['labels'], - hoverinfo: 'label+percent+name', - automargin: true - }]; - - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'values') && utils.keyInObject(this_config, 'labels')) { - if (!this.ndframe.columns.includes(this_config['labels'])) { - throw Error(`Column Error: ${this_config['labels']} not found in columns. labels name must be one of [ ${this.ndframe.columns}]`); - } - if (!this.ndframe.columns.includes(this_config['values'])) { - throw Error(`Column Error: ${this_config['values']} not found in columns. value name must be one of [ ${this.ndframe.columns}]`); - } - let data = [{ - values: this.ndframe[this_config['values']].values, - labels: this.ndframe[this_config['labels']].values, - type: 'pie', - name: this_config['labels'], - hoverinfo: 'label+percent+name', - automargin: true - }]; - - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } else { - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - if (utils.keyInObject(this_config, 'row_pos')) { - if (this_config['row_pos'].length != cols_to_plot.length - 1) { - throw Error(`Lenght of row_pos array must be equal to number of columns. Got ${this_config['row_pos'].length}, expected ${cols_to_plot.length - 1}`); - } - } else { - let temp_arr = []; - for (let i = 0; i < cols_to_plot.length - 1; i++) { - temp_arr.push(0); - } - this_config['row_pos'] = temp_arr; - - } - - if (utils.keyInObject(this_config, 'col_pos')) { - if (this_config['col_pos'].length != cols_to_plot.length - 1) { - throw Error(`Lenght of col_pos array must be equal to number of columns. Got ${this_config['col_pos'].length}, expected ${cols_to_plot.length - 1}`); - } - } else { - let temp_arr = []; - for (let i = 0; i < cols_to_plot.length - 1; i++) { - temp_arr.push(i); - } - this_config['col_pos'] = temp_arr; - - } - let data = []; - - cols_to_plot.forEach((c_name, i) => { - let trace = {}; - trace["values"] = this.ndframe[c_name].values; - trace['labels'] = this.ndframe[this_config['labels']].values; - trace['name'] = c_name; - trace['type'] = "pie"; - trace['domain'] = { row: this_config['row_pos'][i], column: this_config['col_pos'][i] }; - trace["hoverinfo"] = 'label+percent+name'; - trace['textposition'] = "outside"; - trace['automargin'] = true; - data.push(trace); - - }); - - if (!utils.keyInObject(this_config, "grid")) { - //set default grid - let size = Number((this.ndframe.shape[1] / 2).toFixed()) + 1; - this_config['grid'] = { rows: size, columns: size }; - } - this_config['layout']['grid'] = this_config['grid']; - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - - } - - } - - - /** - * Plot Box plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - box(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "box"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = 'box'; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['x'] = this.ndframe[this_config['x']].values; - trace['y'] = this.ndframe.index; - trace['type'] = 'box'; - } else { - trace['x'] = this.ndframe.index; - trace['y'] = this_config['y']; - trace['type'] = 'box'; - } - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - trace["x"] = this.ndframe[c_name].values; - trace["y"] = this.ndframe.index; - trace['name'] = c_name; - trace['type'] = 'box'; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot Violin plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - violin(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "violin"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = 'violin'; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['x'] = this.ndframe[this_config['x']].values; - trace['y'] = this.ndframe.index; - trace['type'] = 'violin'; - } else { - trace['x'] = this.ndframe.index; - trace['y'] = this_config['y']; - trace['type'] = 'violin'; - } - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = 'violin'; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - /** - * Display DataFrame in a div using D3.js format - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - table(config = {}) { - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let header = {}; - let cells = {}; - let cols_data = []; - let cols_2_show; - - - if (utils.keyInObject(this_config, 'columns')) { - - this_config['columns'].forEach((cname) => { - if (!this.ndframe.columns.includes(cname)) { - throw Error(`Column Error: ${cname} not found in columns. Columns should be one of [ ${this.ndframe.columns} ]`); - } - - let idx = this.ndframe.columns.indexOf(cname); - cols_data.push(this.ndframe.getColumnData[idx]); - }); - cols_2_show = this_config['columns']; - } else { - - cols_2_show = this.ndframe.columns; - cols_data = this.ndframe.getColumnData; - - } - - header['values'] = cols_2_show.map((col) => [col]); - cells['values'] = cols_data; - - if (this_config['header_style']) { - Object.keys(this_config['header_style']).forEach((param) => { - header[param] = this_config['header_style'][param]; - }); - } - - if (this_config['cell_style']) { - Object.keys(this_config['cell_style']).forEach((param) => { - cells[param] = this_config['cell_style'][param]; - }); - } - var data = [{ - type: 'table', - header: header, - cells: cells - }]; - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - - __get_plot_params(config) { - let params = Object.keys(config); - let this_config = {}; - - params.forEach((param) => { - this_config[param] = config[param]; - }); - - if (!utils.keyInObject(config, "layout")) { - this_config['layout'] = {}; - } - - - return [this_config, params]; - - } - - ____check_if_cols_exist(cols) { - cols.forEach((col) => { - if (!this.ndframe.columns.includes(col)) { - throw Error(`Column Error: ${col} not found in columns. Columns should be one of [ ${this.ndframe.columns} ]`); - } - }); - return cols; - } - - -} diff --git a/danfojs-browser/src/preprocessing/encodings.js b/danfojs-browser/src/preprocessing/encodings.js deleted file mode 100644 index 49b507ef..00000000 --- a/danfojs-browser/src/preprocessing/encodings.js +++ /dev/null @@ -1,106 +0,0 @@ -import Series from "../core/series"; -import DataFrame from "../core/frame"; -import { utils } from "../shared/utils"; - -export class LabelEncoder { - - /** - * - * @param {data} data [Array|Series] - * @returns Array. - */ - fit(data) { - let in_data = null; - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array or a Series"); - } - - let data_set = new Set(in_data); - this.label = Array.from(data_set); - - let self = this; - let output_data = in_data.map((x) => { - return self.label.indexOf(x); - }); - - return new Series(output_data); - } - - /** - * Transform data using the label generated from fitting - * @param {data} data [Array|Series] - * @returns Array - */ - transform(data) { - let in_data = null; - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array or a Series"); - } - - let self = this; - let output_data = in_data.map((x) => { - return self.label.indexOf(x); - }); - return new Series(output_data); - } -} - -export class OneHotEncoder { - - fit(data) { - let in_data = null; - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array"); - } - - let data_set = new Set(in_data); - this.label = Array.from(data_set); - - let onehot_data = utils.zeros(in_data.length, this.label.length); - - for (let i = 0; i < in_data.length; i++) { - - let elem = in_data[i]; - let elem_index = this.label.indexOf(elem); - onehot_data[i][elem_index] = 1; - } - - return new DataFrame(onehot_data, { columns: this.label }); - - } - - transform(data) { - let in_data = null; - - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array"); - } - - let onehot_data = utils.zeros(in_data.length, this.label.length); - - for (let i = 0; i < in_data.length; i++) { - let elem = in_data[i]; - let elem_index = this.label.indexOf(elem); - onehot_data[i][elem_index] = 1; - } - - return new DataFrame(onehot_data, { columns: this.label }); - - } -} diff --git a/danfojs-browser/src/preprocessing/scalers.js b/danfojs-browser/src/preprocessing/scalers.js deleted file mode 100644 index 3b27e227..00000000 --- a/danfojs-browser/src/preprocessing/scalers.js +++ /dev/null @@ -1,342 +0,0 @@ -import { tensor, moments } from "@tensorflow/tfjs"; -import Series from "../core/series"; -import DataFrame from "../core/frame"; -import { utils } from "../shared/utils"; - -export class MinMaxScaler { - /** - * Fit minmax scaler on data, to obtain their min and max value - * @param {data} data [DataFrame | Series | Array] - * @returns Array - */ - fit(data) { - let tensor_data = null; - if (Array.isArray(data)) { - tensor_data = tensor(data); - } else if (data instanceof DataFrame || data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - tensor_data = tensor(data.values); - } else { - throw new Error("data must either be an Array, DataFrame or Series"); - } - - this.max = tensor_data.max(0); - this.min = tensor_data.min(0); - - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - - if (data instanceof Series || Array.isArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } - - /** - * Transform an array using the min and max generated from the fitting on data - * @param {data} data [Array] - * @returns array - */ - transform(data) { - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } - - /** - * Restore a transformed array to their original values, - * using the min and max generated from the fitting on data - * @param {Series|Array|DataFrame} data - * @returns Series|DataFrame - */ - inverse_transform(data) { - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .mul(this.max.sub(this.min)) - .add(this.min) - .arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data - .mul(this.max.sub(this.min)) - .add(this.min) - .arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .mul(this.max.sub(this.min)) - .add(this.min) - .arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } -} - -export class StandardScaler { - /** - * - * @param {data} data [DataFame | Series | Array] - * @returns Array - */ - fit(data) { - let tensor_data = null; - if (Array.isArray(data)) { - tensor_data = tensor(data); - } else if (data instanceof DataFrame || data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - tensor_data = tensor(data.values); - } else { - throw new Error("data must either be an Array, DataFrame or Series"); - } - - this.std = moments(tensor_data, 0).variance.sqrt(); - this.mean = tensor_data.mean(0); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - - if (data instanceof Series || Array.isArray(data)) { - return new Series((data = output_data)); - } else { - return new DataFrame((data = output_data)); - } - } - - transform(data) { - // if(!Array.isArray(data)){ - // throw new Error(data) - // } - - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } - - /** - * Restore a transformed array to their original values, - * using the mean and std generated from the fitting on data - * @param {Series|Array|DataFrame} data - * @returns Series|DataFrame - */ - inverse_transform(data) { - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.mul(this.std).add(this.mean).arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data.mul(this.std).add(this.mean).arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.mul(this.std).add(this.mean).arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } -} - -// export class RobustScaler{ - -// __median(arr, isTensor,return_index) { -// if (!isTensor) { -// const sorted = arr.slice().sort((a, b) => a - b); -// const middle = Math.floor(sorted.length / 2); - -// if (sorted.length % 2 === 0) { - -// return return_index ? [(middle - 1) , middle] : (sorted[middle - 1] + sorted[middle]) / 2; -// } - -// return return_index ? middle : sorted[middle] ; -// } else { -// let result_arr = [] -// arr.map(ele => { -// const sorted = ele.slice().sort((a, b) => a - b); -// const middle = Math.floor(sorted.length / 2); - -// if (sorted.length % 2 === 0) { -// result_arr.push(return_index ? [(middle - 1) , middle] :(sorted[middle - 1] + sorted[middle]) / 2 ) -// } else { -// result_arr.push(return_index ? middle : sorted[middle]) -// } - -// }) -// return result_arr -// } - -// } - -// quantile(data,isTensor){ - -// if(isTensor){ -// data = utils.__get_col_values(data); -// } - -// let median = this.__median(data,isTensor,true) -// let med = this.__median(data,isTensor,false) - -// let q1 = [] -// let q2 = [] - -// if(!isTensor){ -// let sorted = data.slice().sort((a, b) => a - b); - -// if(Array.isArray(median)){ -// let lower = median[0] -// let lower_data = sorted.slice(0,lower+1) -// let upper_data = sorted.slice(lower+1,) - -// q1.push(this.__median(lower_data,isTensor,false)); -// q2.push(this.__median(upper_data,isTensor,false)); - -// }else{ -// let lower_data = sorted.slice(0,median) -// let upper_data = sorted.slice(median+1,) - -// q1.push(this.__median(lower_data,isTensor,false)); -// q2.push(this.__median(upper_data,isTensor,false)); -// } - -// }else{ - -// data.map((x,i)=>{ -// let sorted = x.slice().sort((a, b) => a - b); - -// if(Array.isArray(median[i])){ -// let lower = median[i][0] -// let lower_data = sorted.slice(0,lower+1) -// let upper_data = sorted.slice(lower+1,) - -// q1.push(this.__median(lower_data,!isTensor,false)); -// q2.push(this.__median(upper_data,!isTensor,false)); - -// }else{ -// let lower_data = sorted.slice(0,median[i]) -// let upper_data = sorted.slice(median[i]+1,) - -// q1.push(this.__median(lower_data,!isTensor,false)); -// q2.push(this.__median(upper_data,!isTensor,false)); -// } - -// }) -// } - -// return [q1,q2, med] - -// } - -// /** -// * Fit robust scalar on data to obtain the first quantile and third quantile -// * @param {data} data [DataFrame | Series | Array] -// * @returns Array -// */ -// fit(data){ - -// let tensor_data = null -// let isTensor = false; -// if(Array.isArray(data)){ -// tensor_data = tensor(data) -// } -// else if((data instanceof DataFrame)){ -// tensor_data = tensor(data.values) -// isTensor = true; -// } -// else if((data instanceof Series)){ -// tensor_data = tensor(data.values) -// } -// else{ -// throw new Error("data must either be an Array, DataFrame or Series") -// } - -// let [q1, q3, median] = this.quantile(data,isTensor) -// let q3_tensor = tensor(q3) -// let output_data = tensor_data.sub(median).div(q3_tensor.sub(q1)).arraySync() - -// return output_data; -// } -// } diff --git a/danfojs-browser/src/shared/config.js b/danfojs-browser/src/shared/config.js deleted file mode 100644 index 40f011c5..00000000 --- a/danfojs-browser/src/shared/config.js +++ /dev/null @@ -1,83 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -/** - * Package wide configuration class - */ -export default class Configs { - - constructor(options) { - const { - tableDisplayConfig, - tableMaxRow, - tableMaxColInConsole, - dtypeTestLim, - lowMemoryMode - } = { - tableDisplayConfig: {}, - tableMaxRow: 10, - tableMaxColInConsole: 21, - dtypeTestLim: 10, - lowMemoryMode: false, - ...options - }; - this.tableDisplayConfig = tableDisplayConfig; - this.tableMaxRow = tableMaxRow; // The maximum number of rows to display in console - this.tableMaxColInConsole = tableMaxColInConsole; // The maximum number of columns to display in console - this.dtypeTestLim = dtypeTestLim; // The number of rows to use when inferring data type - this.lowMemoryMode = lowMemoryMode; // Whether to use minimal memory or not. - } - - setTableDisplayConfig(config) { - this.tableDisplayConfig = config; - } - - get getTableDisplayConfig() { - return this.tableDisplayConfig; - } - - setTableMaxColInConsole(val) { - this.tableMaxColInConsole = val; - } - - get getTableMaxColInConsole() { - return this.tableMaxColInConsole; - } - - setMaxRow(val) { - this.tableMaxRow = val; - } - - get getMaxRow() { - return this.tableMaxRow; - } - - get getDtypeTestLim() { - return this.dtypeTestLim; - } - - setDtypeTestLim(val) { - this.dtypeTestLim = val; - } - - get isLowMemoryMode() { - return this.lowMemoryMode; - } - - setIsLowMemoryMode(val) { - this.lowMemoryMode = val; - } -} - diff --git a/danfojs-browser/src/shared/errors.js b/danfojs-browser/src/shared/errors.js deleted file mode 100644 index ebd91219..00000000 --- a/danfojs-browser/src/shared/errors.js +++ /dev/null @@ -1,93 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -/** - * Package wide error throwing class - */ -class ErrorThrower { - - throwColumnNamesLengthError(ndframe, columns){ - const msg = `ParamError: Column names length mismatch. You provided a column of length ${columns.length} but Ndframe columns has lenght of ${ndframe.shape[1]}`; - throw new Error(msg); - } - - throwIndexLengthError(ndframe, index){ - const msg = `IndexError: You provided an index of length ${index.length} but Ndframe rows has lenght of ${ndframe.shape[0]}`; - throw new Error(msg); - } - - throwIndexDuplicateError(){ - const msg = `IndexError: Row index must contain unique values`; - throw new Error(msg); - } - - throwColumnDuplicateError(){ - const msg = `ColumnIndexError: Column index must contain unique values`; - throw new Error(msg); - } - - throwDtypesLengthError(ndframe, dtypes){ - const msg = `DtypeError: You provided a dtype array of length ${dtypes.length} but Ndframe columns has lenght of ${ndframe.shape[1]}`; - throw new Error(msg); - } - - throwDtypeNotSupportedError (dtype){ - const msg = `DtypeError: Dtype "${dtype}" not supported. dtype must be one of "${DATA_TYPES}"`; - throw new Error(msg); - } - - throwColumnLengthError(ndframe, arrLen){ - const msg = `ParamError: Column data length mismatch. You provided data with length ${arrLen} but Ndframe has column of lenght ${ndframe.shape[1]}`; - throw new Error(msg); - } - - throwRowLengthError(ndframe, arrLen){ - const msg = `ParamError: Row data length mismatch. You provided data with length ${arrLen} but Ndframe has row of lenght ${ndframe.shape[0]}`; - throw new Error(msg); - } - - throwColumnNotFoundError(ndframe){ - const msg = `ParamError: Column not found!. Column name must be one of ${ndframe.columns}`; - throw new Error(msg); - } - - throwNotImplementedError(){ - const msg = `Method not implemented`; - throw new Error(msg); - } - - throwIlocRowIndexError(){ - const msg = `ParamError: rows parameter must be a Array. For example: rows: [1,2] or rows: ["0:10"]`; - throw new Error(msg); - } - - throwIlocColumnsIndexError(){ - const msg = `ParamError: columns parameter must be a Array. For example: columns: [1,2] or columns: ["0:10"]`; - throw new Error(msg); - } - - throwStringDtypeOperationError(operation){ - const msg = `DtypeError: String data type does not support ${operation} operation`; - throw new Error(msg); - } - - throwSeriesMathOpLengthError(ndframe, other){ - const msg = `ParamError: Row length mismatch. Length of other (${other.shape[0]}), must be the same as Ndframe (${ndframe.shape[0]})`; - throw new Error(msg); - } - -} - -export default new ErrorThrower(); diff --git a/danfojs-browser/src/shared/utils.js b/danfojs-browser/src/shared/utils.js deleted file mode 100644 index 2279f7bd..00000000 --- a/danfojs-browser/src/shared/utils.js +++ /dev/null @@ -1,801 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -import { BASE_CONFIG } from './defaults'; -import Config from './config'; -import { Series } from '..'; -import { DataFrame } from '..'; -import ErrorThrower from './errors'; - -const config = new Config(BASE_CONFIG); - -/** - * Utility class for working with Frames and Series - */ -class Utils { - /** - * Removes an element from a 1D array - * - * ```js - * - * ``` - * @param arr The array to filter. - * @param index The index to filter by. - */ - removeElementFromArray(arr, index) { - const newArr = arr.filter((_, i) => i != index); - return newArr; - } - - /** - * Check if value is a string. - * @param value The value to check. - * @returns - */ - isString(value) { - return typeof value === "string"; - } - - /** - * Checks if value is a number. - * @param value The value to check. - * @returns - */ - isNumber(value) { - return typeof value === "number" && isFinite(value); - } - - /** - * Checks if value is an object. - * @param value The value to check. - * @returns - */ - isObject(value) { - return typeof value === "object" && value.constructor && value.constructor.name === "Object"; - } - - /** - * Checks if a value is null - * @param value The value to check. - * @returns - */ - isNull(value) { - return value === null; - } - - /** - * Checks if a value is undefined - * @param value The value to check. - * @returns - */ - isUndefined(value) { - return typeof value === "undefined"; - } - - /** - * Checks if a value is empty. Empty means it's either null, undefined or NaN - * @param value The value to check. - * @returns - */ - isEmpty(value) { - return value === undefined || value === null || (isNaN(value) && typeof value !== "string"); - } - - /** - * Generates an array of integers between specified range - * @param start The starting number. - * @param end The ending number. - */ - range(start, end){ - if (end < start) { - throw new Error("ParamError: end must be greater than start"); - } - - if (start === end) { - return [start]; - } - - const arr = []; - for (let i = start; i <= end; i++) { - arr.push(i); - } - return arr; - } - - /** - * Checks if object has the specified key - * @param obj The object to check. - * @param key The key to find. - */ - keyInObject(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - } - - /** - * Transposes an array of array - * @param obj The object to check. - * @param key The key to find. - */ - transposeArray(arr ) { //old name: __get_col_values - if (arr.length === 0) return arr; - - const rowLen = arr.length; - if (Array.isArray(arr[0])) { - const colLen = arr[0].length; - const newArr = []; - - for (let i = 0; i <= colLen - 1; i++) { - const temp = []; - for (let j = 0; j < rowLen; j++) { - const _elem = (arr)[j][i]; - temp.push(_elem); - } - newArr.push(temp); - } - return newArr; - } else { - return arr; - } - } - - /** - * Retrieve row array and column names from an object of the form {a: [1,2,3,4], b: [30,20, 30, 20]} - * @param obj The object to retrieve rows and column names from. - */ - getRowAndColValues(obj) { - const colNames = Object.keys(obj); - const colData = Object.values(obj); - const firstColLen = colData[0].length; - - colData.forEach((cdata) => { - if (cdata.length != firstColLen) { - throw Error("Length Error: Length of columns must be the same!"); - } - }); - - const rowsArr = this.transposeArray(colData); - return [rowsArr, colNames]; - } - - /** - * Converts a 2D array of array to 1D array for Series Class - * @param arr The array to convert. - */ - convert2DArrayToSeriesArray(arr){ - const newArr = arr.map((val) => { - if (this.isObject(val)) { - return JSON.stringify(val); - } else { - return `${val}`; - } - }); - return newArr; - } - - /** - * Replaces all missing values with NaN. Missing values are undefined, Null and Infinity - * @param arr The array - * @param isSeries Whether the arr is a series or not - */ - replaceUndefinedWithNaN(arr, isSeries) { - if (arr.length === 0) return arr; - - if (isSeries && Array.isArray(arr)) { - const newArr = arr.map((ele) => { - if (typeof ele === "undefined") { - return NaN; - } - if (typeof ele === "number" && (isNaN(ele) || ele == Infinity)) { - return NaN; - } - if (ele == null) { - return NaN; - } - return ele; - }); - return newArr; - } else { - const newArr = []; - if (Array.isArray(arr)) { - for (let i = 0; i < arr.length; i++) { - const innerArr = arr[i]; - const temp = (innerArr).map((ele) => { - if (typeof ele === "undefined") { - return NaN; - } - if (typeof ele === "number" && (isNaN(ele) || ele == Infinity)) { - return NaN; - } - if (ele == null) { - return NaN; - } - return ele; - }); - newArr.push(temp); - } - } - return newArr; - } - } - - /** - * Infer data type from an array or array of arrays - * @param arr An array or array of arrays - */ - inferDtype(arr ) { - const self = this; - if (this.is1DArray(arr)) { - return [this.$typeChecker(arr)]; - } else { - const arrSlice = this.transposeArray(arr.slice(0, config.getDtypeTestLim)); - const dtypes = arrSlice.map((innerArr) => { - return self.$typeChecker(innerArr); - }); - return dtypes; - } - } - - /** - * Private type checker used by inferDtype function - * @param arr The array - */ - $typeChecker(arr ) { - let dtypes; - let lim; - let intTracker = []; - let floatTracker = []; - let stringTracker = []; - let boolTracker = []; - - if (arr.length < config.getDtypeTestLim) { - lim = arr.length; - } else { - lim = config.getDtypeTestLim; - } - - const arrSlice = arr.slice(0, lim); - - for (let i = 0; i < lim; i++) { - const ele = arrSlice[i]; - if (typeof ele == "boolean") { - floatTracker.push(false); - intTracker.push(false); - stringTracker.push(false); - boolTracker.push(true); - } else if (this.isEmpty(ele)) { - floatTracker.push(true); - intTracker.push(false); - stringTracker.push(false); - boolTracker.push(false); - } else if (!isNaN(Number(ele))) { - if ((ele).toString().includes(".")) { - floatTracker.push(true); - intTracker.push(false); - stringTracker.push(false); - boolTracker.push(false); - } else { - floatTracker.push(false); - intTracker.push(true); - stringTracker.push(false); - boolTracker.push(false); - } - } else { - floatTracker.push(false); - intTracker.push(false); - stringTracker.push(true); - boolTracker.push(false); - } - } - - const even = (ele) => ele == true; - - if (stringTracker.some(even)) { - dtypes = "string"; - } else if (floatTracker.some(even)) { - dtypes = "float32"; - } else if (intTracker.some(even)) { - dtypes = "int32"; - } else if (boolTracker.some(even)) { - dtypes = "boolean"; - } else { - dtypes = "undefined"; - } - - return dtypes; - } - - /** - * Returns the unique values in an 1D array - * @param arr The array - */ - unique(arr) { - const uniqueArr = new Set(arr); - return Array.from(uniqueArr); - } - - /** - * Checks if array is 1D - * @param arr The array - */ - is1DArray(arr ) { - if ( - typeof arr[0] == "number" || - typeof arr[0] == "string" || - typeof arr[0] == "boolean" - ) { - return true; - } else { - return false; - } - } - - /** - * Converts an array to an object using array index as object keys - * @param arr The array - */ - convertArrayToObject(arr ) { - const arrObj = {}; - for (let i = 0; i < arr.length; i++) { - arrObj[i] = arr[i]; - - } - return arrObj; - } - - /** - * Count the NaN and non-NaN values present in an array - * @param arr Array object - * @param val whether to return the value count instead of the null count - * @param isSeries Whether the array is of type series or not - */ - countNaNs(arr, returnVal = true, isSeries) { - if (isSeries) { - let nullCount = 0; - let valCount = 0; - for (let i = 0; i < arr.length; i++) { - const ele = arr[i]; - if (Number.isNaN(ele)) { - nullCount = nullCount + 1; - } else { - valCount = valCount + 1; - } - - } - if (returnVal) { - return valCount; - } else { - return nullCount; - } - } else { - const resultArr = []; - for (let i = 0; i < arr.length; i++) { - const innerArr = arr[i]; - let nullCount = 0; - let valCount = 0; - for (let i = 0; i < (innerArr).length; i++) { - const ele = (innerArr)[i]; - if (Number.isNaN(ele)) { - nullCount = nullCount + 1; - } else { - valCount = valCount + 1; - } - } - - if (returnVal) { - resultArr.push(valCount); - } else { - resultArr.push(nullCount); - } - } - return resultArr; - } - } - - /** - * Round elements of an array or array of arrays to specified dp - * @param arr The Array to round - * @param dp The number of dp to round to - * @param isSeries Whether the array is of type Series or not - */ - round(arr, dp = 1, isSeries) { - if (dp < 0) { - dp = 1; - } - - if (isSeries) { - const newArr = []; - for (let i = 0; i < arr.length; i++) { - const ele = arr[i]; - if (typeof ele == "number" && !isNaN(ele) && ele !== undefined && ele !== null) { - newArr.push(Number((ele).toFixed(dp))); - } else { - newArr.push(ele); - } - } - return newArr; - } else { - const resultArr = []; - for (let i = 0; i < arr.length; i++) { - const innerVal = arr[i]; - const newArr = []; - if (Array.isArray(innerVal)) { - for (let i = 0; i < innerVal.length; i++) { - const ele = innerVal[i]; - if (typeof ele == "number" && !isNaN(ele) && ele !== undefined && ele !== null) { - newArr.push(Number((ele).toFixed(dp))); - } else { - newArr.push(ele); - } - } - resultArr.push(newArr); - } else { - if (typeof innerVal == "number" && !isNaN(innerVal) && innerVal !== undefined && innerVal !== null) { - newArr.push(Number((innerVal).toFixed(dp))); - } else { - newArr.push(innerVal); - } - } - - } - return resultArr; - } - } - - /** - * Checks if a func is a function - * @param func - */ - isFunction(func) { - return typeof func == "function"; - } - - /** - * Generates n random numbers between start and end. - * @param start - * @param end - * @param size - */ - randNumberGenerator(start, end, size) { - let genNum = []; - - function randi(a, b) { - return Math.floor(Math.random() * (b - a) + a); - } - - function recursive(val, arr) { - if (!arr.includes(val)) { - return val; - } - val = randi(start, end); - recursive(val, arr); - } - - for (let i = 0; i < size; i++) { - let genVal = randi(start, end); - let recursiveVal = recursive(genVal, genNum); - genNum.push(recursiveVal); - } - return genNum; - } - - /** - * Throws error when a required parameter is missing. - * @param paramsObject The parameters passed to the function - * @param paramsNeeded The required parameters in the function - */ - throwErrorOnWrongParams(paramsObject, paramsNeeded) { - const keys = Object.keys(paramsObject); - const bool = []; - for (let i = 0; i < keys.length; i++) { - if (paramsNeeded.includes(keys[i])) { - bool.push(true); - } else { - bool.push(false); - } - } - const truthy = (element) => element == false; - if (bool.some(truthy)) { - throw Error( - `Params Error: Required parameter not found. Your params must include the following [${paramsNeeded}]` - ); - } - } - - /** - * Maps integer values (0, 1) to boolean (false, true) - * @param arr The array of integers - * @param dim The dimension of the array - */ - mapIntegersToBooleans(arr, dim){ - if (dim == 2) { - const newArr = []; - arr.map((innerArr) => { - const temp = []; - (innerArr).map((val) => temp.push(val == 1)); - newArr.push(temp); - }); - return newArr; - } else { - const newArr = []; - arr.map((val) => newArr.push(val == 1)); - return newArr; - } - } - - /** - * Maps boolean values (false, true) to integer equivalent (0, 1) - * @param arr The array of booleans - * @param dim The dimension of the array - */ - mapBooleansToIntegers(arr, dim){ - if (dim == 2) { - const newArr = []; - arr.map((innerArr) => { - const temp = []; - (innerArr).map((val) => temp.push(val ? 1 : 0)); - newArr.push(temp); - }); - return newArr; - } else { - const newArr = []; - arr.map((val) => newArr.push(val ? 1 : 0)); - return newArr; - } - } - - /** - * Generates an array of dim (row x column) with inner values set to zero - * @param row - * @param column - */ - zeros(row, column) { - const zeroData = []; - for (let i = 0; i < row; i++) { - const colData = Array(column); - for (let j = 0; j < column; j++) { - colData[j] = 0; - } - zeroData.push(colData); - } - return zeroData; - } - - /** - * Shuffles and returns a random slice of an array - * @param num - * @param array - */ - shuffle(array, num) { - let i = array.length; - let j = 0; - let temp; - - while (i--) { - j = Math.floor(Math.random() * (i + 1)); - temp = array[i]; - array[i] = array[j]; - array[j] = temp; - } - - return array.slice(0, num); - } - - /** - * Sorts an array in specified order - * @param arr - * @param ascending - * @returns - */ - sort(arr, ascending = true) { - const sorted = [...arr]; - return sorted.sort((a, b) => { - if (ascending) { - if (typeof a === "string" && typeof b === "string") { - return a.charCodeAt(0) - b.charCodeAt(0); - } else { - return (a) - (b); - } - } else { - if (typeof a === "string" && typeof b === "string") { - return b.charCodeAt(0) - a.charCodeAt(0); - } else { - return (b) - (a); - } - } - }); - } - - /** - * Checks if current environment is Browser - */ - isBrowserEnv() { - const isBrowser = new Function( - "try {return this===window;}catch(e){ return false;}" - ); - return isBrowser(); - } - - /** - * Checks if current environment is Node - */ - isNodeEnv() { - const isNode = new Function( - "try {return this===global;}catch(e){return false;}" - ); - return isNode(); - } - - /** - * Remove NaN values from 1D array - * @param arr - */ - removeMissingValuesFromArray(arr) { - const values = arr.filter((val) => { - return !(this.isEmpty(val)); - }); - return values; - } - - - /** - * Replace NaN with null before tensor operations - * @param arr - */ - replaceNanWithNull(arr ) { - const values = arr.map((val) => { - if (isNaN(val)) { - return null; - } else { - return val; - } - }); - return values; - } - - /** - * Get duplicate values in a array - * @param arr - */ - getDuplicate(arr) { - const tempObj = {}; - const resultObj = {}; - - for (let i = 0; i < arr.length; i++) { - const val = arr[i]; - if (this.keyInObject(tempObj, val)) { - tempObj[val]["count"] += 1; - tempObj[val]["index"].push(i); - } else { - tempObj[val] = {}; - tempObj[val]["count"] = 1; - tempObj[val]["index"] = [i]; - } - } - - for (let key in tempObj) { - if (tempObj[key]["count"] >= 2) { - resultObj[key] = {}; - resultObj[key]["count"] = tempObj[key]["count"]; - resultObj[key]["index"] = tempObj[key]["index"]; - } - } - - return resultObj; - } - - /** - * Returns the index of a sorted array - * @param arr1 The first array - * @param arr2 The second array - * @param dtype The data type of the arrays - * - * @returns sorted index - */ - sortArrayByIndex(arr1, arr2, dtype) { - const sortedIdx = arr1.map((item, index) => { - return [arr2[index], item]; - }); - if (dtype == "string") { - sortedIdx.sort(); - } else { - sortedIdx.sort(([arg1], [arg2]) => (arg2) - (arg1)); - } - - return sortedIdx.map(([, item]) => item); - } - - /** - * Returns a new series with properties of the old series - * - * @param series The series to copy - */ - createNdframeFromNewDataWithOldProps({ ndFrame, newData, isSeries }) { - if (isSeries) { - return new Series( - newData, - { - index: [...ndFrame.index], - columns: [...ndFrame.columns], - dtypes: [...ndFrame.dtypes], - config: { ...ndFrame.config } - }); - } else { - return new DataFrame(newData, - { - index: [...ndFrame.index], - columns: [...ndFrame.columns], - dtypes: [...ndFrame.dtypes], - config: { ...ndFrame.config } - }); - } - } - - /** - * Checks if two series are compatible for a mathematical operation - * @param object - * - * firstSeries ==> First Series object - * - * secondSeries ==> Second Series object to comapre with - * - * operation ==> The mathematical operation - */ - checkSeriesOpCompactibility({ firstSeries, secondSeries, operation }) { - - if (firstSeries.shape[0] != secondSeries.shape[0]) { - ErrorThrower.throwSeriesMathOpLengthError(firstSeries, secondSeries); - } - if (firstSeries.dtypes[0] == 'string' || secondSeries.dtypes[0] == 'string') { - ErrorThrower.throwStringDtypeOperationError(operation); - } - } - - /** - * Custom sort for an array of index and values - * @param arr The array of objects to sort - * @param ascending Whether to sort in ascending order or not - */ - sortObj( - arr, - ascending - ) { - return arr.sort((obj1, obj2) => { - const a = obj2.value; - const b = obj1.value; - - if (!ascending) { - if (typeof a === "string" && typeof b === "string") { - return a.charCodeAt(0) - b.charCodeAt(0); - } else if ((typeof a === "number" && typeof b === "number") || (typeof a === "boolean" && typeof b === "boolean")) { - return Number(a) - Number(b); - } else { - throw Error('ParamError: column values must be either numbers or strings'); - } - } else { - if (typeof a === "string" && typeof b === "string") { - return b.charCodeAt(0) - a.charCodeAt(0); - } else if ((typeof a === "number" && typeof b === "number") || (typeof a === "boolean" && typeof b === "boolean")) { - return Number(b) - Number(a); - } else { - throw Error('ParamError: column values must be either numbers or strings'); - } - } - }); - } -} - -const utils = new Utils(); -export { utils }; - diff --git a/danfojs-browser/tests/core/frame.js b/danfojs-browser/tests/core/frame.js deleted file mode 100644 index 8851345e..00000000 --- a/danfojs-browser/tests/core/frame.js +++ /dev/null @@ -1,2168 +0,0 @@ -/* eslint-disable no-undef */ - -describe("DataFrame", function () { - - describe("to_csv", function () { - - it("return dataframe csv string", async function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - const csvContent = df.to_csv({ download: false }); - assert.deepEqual(csvContent, "A,B,C\n1,2,3\n4,5,6\n"); - }); - - }); - - describe("drop", function () { - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.throws(function () { df.drop({ columns: [3], axis: 0, inplace: false }); }, Error, 'ParamError: specified column "3" not found in columns'); - }); - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.throws(function () { df.drop({ columns: ["D"], axis: 1, inplace: false }); }, Error, 'ParamError: specified column "D" not found in columns'); - }); - - it("drop a column inplace", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.drop({ columns: ["C", "B"], axis: 1, inplace: true }); - let column = ["A"]; - assert.deepEqual(df.columns, column); - }); - it("check if data is updated after column is dropped", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.drop({ columns: ["C"], axis: 1, inplace: true }); - let new_data = [[1, 2], [4, 5]]; - assert.deepEqual(df.values, new_data); - assert.deepEqual(df.dtypes.length, 2); - - }); - - it("check if data is updated after row is dropped", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.drop({ index: [0], axis: 0, inplace: true }); - let new_data = [[4, 5, 6]]; - assert.deepEqual(df.values, new_data); - }); - it("check if new dataframe is properly created after column is dropped (not-in-inplace)", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let df_drop = df.drop({ columns: ["C"], axis: 1, inplace: false }); - - let expected_data = [[1, 2], [4, 5]]; - let expected_cols = ["A", "B"]; - let expected_df = new dfd.DataFrame(expected_data, { columns: expected_cols }); - assert.deepEqual(df_drop.values, expected_df.values); - }); - it("check that the dtype is updated after column drop", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.drop({ columns: ["A"], axis: 1, inplace: true }); - let dtype = ['int32', 'int32']; - assert.deepEqual(df.ctypes.values, dtype); - }); - it("drop row by single string labels", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 34, 5]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols, index: ["a", "b", "c"] }); - df.drop({ index: ["a"], axis: 0, inplace: true }); - let new_data = [[4, 5, 6], [20, 34, 5]]; - assert.deepEqual(df.values, new_data); - }); - it("drop row by two or more string labels", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 34, 5], [2, 3.4, 5], [2.0, 340, 5]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols, index: ["a", "b", "c", "d", "e"] }); - df.drop({ index: ["a", "b"], axis: 0, inplace: true }); - let new_data = [[20, 34, 5], [2, 3.4, 5], [2.0, 340, 5]]; - assert.deepEqual(df.values, new_data); - - }); - }); - - describe("head", function () { - it("Gets the first n rows in a DataFrame", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.deepEqual(df.head(2).values, [[1, 2, 3], [4, 5, 6]]); - }); - - }); - - describe("tail", function () { - it("Prints the last n rows of a DataFrame", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.deepEqual(df.tail(2).values, [[20, 30, 40], [39, 89, 78]]); - }); - it("Return last 3 row index in a DataFrame", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.deepEqual(df.tail(2).index, [2, 3]); - }); - it("Check print format on head call", function () { - let data = [[1, 2, 34, 5, 0, 6, 4, 5, 6, 7], [20, 30, 40, 39, 89, 78, 45, 56, 56, 45]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.tail(2).values, [[1, 2, 34, 5, 0, 6, 4, 5, 6, 7], [20, 30, 40, 39, 89, 78, 45, 56, 56, 45]]); - }); - }); - - describe("sample", function () { - it("Samples n number of random elements from a DataFrame", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let expected = [[1, 2, 3], [20, 30, 40]]; - let values = (await df.sample(2)).values; - assert.deepEqual(values, expected); - }); - it("Throw error if n is greater than lenght of Dataframe", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - try { - await df.sample(100); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('ParamError: Sample size cannot be bigger than number of rows'); - } - }); - it("Throw error if n is less than -1", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - try { - await df.sample(-2); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); - } - }); - it("Throw error if n is 0", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - try { - await df.sample(0); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); - } - }); - }); - - describe("loc", function () { - - it("throw error for wrong column name", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.throws(function () { df.loc({ "rows": [0, 1], "columns": ["A", "D"] }); }, Error, "ColumnIndexError: Specified column (D) not found"); - }); - it("check data after selecting column", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": [0, 1], "columns": ["B", "C"] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after selecting row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": [1], "columns": ["B", "C"] }); - let col_data = [[5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row and column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": ["0:2"], "columns": ["B:C"] }); - let col_data = [[2], [5]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": ["0:2"], "columns": ["B", "C"] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": [0, 1], "columns": ["A:C"] }); - let col_data = [[1, 2], [4, 5]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("loc by single string index", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new dfd.DataFrame(data, { index: ["a", "b", "c", "d"] }); - let sub_df = df.loc({ rows: ["a"], columns: ["Name", "Count"] }); - let expected = [["Apples", 21]]; - assert.deepEqual(sub_df.values, expected); - - }); - it("loc by multiple string index", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new dfd.DataFrame(data, { index: ["a", "b", "c", "d"] }); - let sub_df = df.loc({ rows: ["a", "b"], columns: ["Name", "Count"] }); - let expected = [["Apples", 21], ["Mango", 5]]; - assert.deepEqual(sub_df.values, expected); - - }); - it("loc by slice string index", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new dfd.DataFrame(data, { index: ["a", "b", "c", "d"] }); - let sub_df = df.loc({ rows: [`"a":"c"`], columns: ["Name", "Count"] }); - let expected = [["Apples", 21], ["Mango", 5]]; - assert.deepEqual(sub_df.values, expected); - - }); - - - }); - - describe("iloc", function () { - - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.throws(function () { df.iloc({ "rows": 0, "columns": [0, 3] }); }, Error, `rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); - }); - - it("throw error for wrong column indexing", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.throws(function () { df.iloc({ "rows": [0, 1], "columns": 3 }); }, Error, `columns parameter must be an Array. For example: columns: [1,2] or columns: ["0:10"]`); - }); - - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - assert.throws(function () { df.iloc({ "rows": [0, 8], "columns": [1, 2] }); }, Error, "Invalid row parameter: Specified index 8 cannot be bigger than index length 2"); - }); - - it("check data after selecting column", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [0, 1], "columns": [1, 2] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after selecting row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [1], "columns": [1, 2] }); - let col_data = [[5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row and column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": ["0:2"], "columns": ["1:2"] }); - let col_data = [[2], [5]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": ["0:2"], "columns": [1, 2] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [0, 1, 2], "columns": ["1:2"] }); - let col_data = [[2], [5], [30]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("Return all columns if columns parameter is not specified", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [0, 1, 2] }); - let col_data = [[1, 2, 3], [4, 5, 6], [20, 30, 40]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("Return all rows if rows parameter is not specified", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "columns": ["1:2"] }); - let col_data = [[2], [5], [30], [89]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("column slice starting with 0 and returning a single result works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new dfd.DataFrame(data); - let sub_df = df.iloc({ rows: ["2:3"], columns: ["0:1"] }); - const result = [["Banana"]]; - assert.deepEqual(sub_df.values, result); - - }); - it("column slice with format '0:' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new dfd.DataFrame(data); - let sub_df = df.iloc({ rows: ["2:3"], columns: ["0:"] }); - const result = [["Banana", 30, 40]]; - assert.deepEqual(sub_df.values, result); - - }); - it("column slice with format ':2' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new dfd.DataFrame(data); - let sub_df = df.iloc({ rows: ["2:3"], columns: [":2"] }); - const result = [["Banana", 30]]; - assert.deepEqual(sub_df.values, result); - - }); - it("row slice with format ':2' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new dfd.DataFrame(data); - let sub_df = df.iloc({ rows: [":2"], columns: [":1"] }); - const result = [['Apples'], ['Mango']]; - assert.deepEqual(sub_df.values, result); - - }); - it("row slice with format '1:' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new dfd.DataFrame(data); - let sub_df = df.iloc({ rows: [":2"], columns: [":2"] }); - const result = [['Apples', 21], ['Mango', 5]]; - assert.deepEqual(sub_df.values, result); - - }); - - }); - - - describe("add", function () { - it("Return Addition of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.add(2).values, [[2, 4, 6], [362, 182, 362]]); - }); - it("Return addition of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2, 1]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.add(sf).values, [[1, 4, 5], [361, 182, 361]]); - }); - it("Return addition of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.add(sf, { axis: 0 }).values, [[1, 3, 5], [362, 182, 362]]); - }); - it("Return addition of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.add(df2).values, [[1, 4, 8], [370, 185, 360]]); - }); - it("Return addition of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.add(df2, { axis: 0 }).values, [[1, 4, 8], [370, 185, 360]]); - }); - - }); - - describe("sub", function () { - it("Return subtraction of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.sub(2).values, [[-2, 0, 2], [358, 178, 358]]); - }); - it("Return subtraction of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2, 1]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.sub(sf).values, [[-1, 0, 3], [359, 178, 359]]); - }); - it("Return subtraction of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.sub(sf, { axis: 0 }).values, [[-1, 1, 3], [358, 178, 358]]); - }); - it("Return subtraction of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.sub(df2).values, [[-1, 0, 0], [350, 175, 360]]); - }); - it("Return subtraction of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.sub(df2).values, [[-1, 0, 0], [350, 175, 360]]); - }); - - }); - - describe("mul", function () { - it("Return multiplication of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mul(2).values, [[0, 4, 8], [720, 360, 720]]); - }); - it("Return multiplication of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2, 1]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mul(sf).values, [[0, 4, 4], [360, 360, 360]]); - }); - it("Return multiplication of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mul(sf, { axis: 0 }).values, [[0, 2, 4], [720, 360, 720]]); - }); - it("Return multiplication of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mul(df2).values, [[0, 4, 16], [3600, 900, 0]]); - }); - it("Return multiplication of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mul(df2, { axis: 0 }).values, [[0, 4, 16], [3600, 900, 0]]); - }); - - }); - - describe("div", function () { - it("Return division of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.div(2).values, [[0, 1, 2], [180, 90, 180]]); - }); - it("Return division of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2, 1]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.div(sf).values, [[0, 1, 4], [360, 90, 360]]); - }); - it("Return division of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.div(sf, { axis: 0 }).values, [[0, 2, 4], [180, 90, 180]]); - }); - it("Return division of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.div(df2).values, [[0, 1, 1], [36, 36, Infinity]]); - }); - it("Return division of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - assert.deepEqual(df1.div(df1).values, [[NaN, 1, 1], [1, 1, 1]]); - }); - it("Return division of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.div(df2).values, [[0, 1, 1], [36, 36, Infinity]]); - }); - - }); - - describe("pow", function () { - it("Return exponential of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.pow(2).values, [[0, 4, 16], [129600, 32400, 129600]]); - }); - it("Return exponential of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2, 1]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.pow(sf).values, [[0, 4, 4], [360, 32400, 360]]); - }); - it("Return exponential of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new dfd.Series([1, 2]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.pow(sf, { axis: 0 }).values, [[0, 2, 4], [129600, 32400, 129600]]); - }); - it("Return exponential of a DataFrame with another DataFrame along default axis 1", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [3, 10, 4]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.pow(df2).values, [[0, 4, 256], [59049, 100000, 1]]); - }); - it("Return exponential of a DataFrame with another DataFrame along axis 0", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [3, 10, 4]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.pow(df2, { axis: 0 }).values, [[0, 4, 256], [59049, 100000, 1]]); - }); - - }); - - describe("mod", function () { - it("Return modulus of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mod(2).values, [[0, 0, 0], [0, 0, 0]]); - }); - it("Return modulus of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [31, 15, 360]]; - let sf = new dfd.Series([1, 2, 1]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mod(sf).values, [[0, 0, 0], [0, 1, 0]]); - }); - it("Return modulus of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [31, 15, 360]]; - let sf = new dfd.Series([1, 2]); - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mod(sf, { axis: 0 }).values, [[0, 0, 0], [1, 1, 0]]); - }); - it("Return modulus of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [31, 15, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mod(df2).values, [[0, 0, 0], [1, 0, NaN]]); - }); - it("Return modulus of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new dfd.DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new dfd.DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mod(df2).values, [[0, 0, 0], [0, 0, NaN]]); - }); - - }); - - describe("mean", function () { - it("Returns the mean of a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data, { columns: ["col1", "col2", "col3"] }); - assert.deepEqual(df.mean().values, [180, 91, 182]); - assert.deepEqual(df.mean().index, ["col1", "col2", "col3"]); - - }); - it("Return mean of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mean({ axis: 0 }).values, [2, 300]); - }); - it("Removes NaN before calculating mean of a DataFrame", function () { - let data = [[11, 20, 3], [NaN, 15, 6], [2, 30, 40], [2, 89, 78]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mean().values, [5, 38.5, 31.75]); - }); - }); - - describe("median", function () { - it("Returns the median of a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.median().values, [180, 91, 182]); - }); - it("Return median of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.median({ "axis": 0 }).values, [2, 360]); - }); - - }); - - describe("mode", function () { - it("Returns the mode of a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360], [0, 2, 4]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mode().values, [0, 2, 4]); - }); - it("Returns mode of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 0], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.mode({ "axis": 0 }).values, [0, 360]); - }); - }); - - describe("min", function () { - it("Returns the minimum values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.min().values, [0, 2, 4]); - }); - it("Returns the minimum values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.min({ "axis": 0 }).values, [0, 180]); - }); - - }); - - describe("max", function () { - it("Returns the maximum values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.max().values, [360, 180, 360]); - }); - it("Returns the maximum values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.max({ "axis": 0 }).values, [4, 360]); - }); - - }); - - describe("std", function () { - it("Returns the standard deviations of values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.std().values, [254.55844122715712, 125.86500705120545, 251.7300141024109]); - }); - it("Return the standard deviations of values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.std({ "axis": 0 }).values, [2, 103.92304845413264]); - }); - - - }); - - describe("var", function () { - it("Returns the variance of values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.var().values, [64800, 15842, 63368]); - }); - it("Return the variance of values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.var({ "axis": 0 }).values, [4, 10800]); - }); - - - }); - - describe("describe", function () { - it("Returns descriptive statistics of columns in a DataFrame created from an array", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 360, "b"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data); - let res = [[3, 3, 3], [120.66666666666667, 62, 123.33333333333333], - [207.27115895206774, 102.19589032832974, 204.961785055979], - [0, 2, 4], [2, 4, 6], - [360, 180, 360], - [42961.33333333333, 10444, 42009.333333333336]]; - - assert.deepEqual(df.describe().values, res); - }); - it("Returns descriptive statistics of columns in a DataFrame created from an Object", function () { - let data = { - "col1": [0, 2, 4], - "col2": [360, 180, 360], - "col3": [2, 4, 6], - "col4": ["boy", "girl", "man"], - "col5": ["apple", "car", "bee"] - }; - let df = new dfd.DataFrame(data); - - let res = [[3, 3, 3], [2, 300, 4], - [2, 103.92304845413264, 2], - [0, 180, 2], [2, 360, 4], - [4, 360, 6], - [4, 10800, 4]]; - - assert.deepEqual(df.describe().values, res); - }); - - }); - - describe("count", function () { - it("Returns the count of non-nan values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180.1, 360.11], [NaN, 2, 4], [360, undefined, 360]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.count().values, [3, 3, 4]); - }); - it("Return the count of non NaN values of a DataFrame along axis 0", function () { - let data = [[0, 2, 4, NaN], [360, undefined, 360, 70]]; - let df = new dfd.DataFrame(data); - assert.deepEqual(df.count({ axis: 0 }).values, [3, 3]); - }); - - }); - - describe("round", function () { - it("Rounds values in a DataFrame to 3dp", function () { - let data = [[10.1, 2.092, 4.23], [360.232244, 180.0190290, 36.902612]]; - let df = new dfd.DataFrame(data); - let expected = [[10.1, 2.092, 4.23], [360.232, 180.0190, 36.903]]; - assert.deepEqual(df.round(3).values, expected); - }); - it("Rounds values in a DataFrame to 1dp", function () { - let data = [[10.1, 2.092, 4.23], [360.232244, 180.0190290, 36.902612]]; - let df = new dfd.DataFrame(data); - let expected = [[10.1, 2.1, 4.2], [360.2, 180.0, 36.9]]; - assert.deepEqual(df.round(1).values, expected); - }); - - }); - - describe("sort_values", function () { - it("Sort values in DataFrame by specified column in ascending order (Default)", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 360, "b"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - df.sort_values({ "by": "col1", inplace: true, ascending: true }); - let expected = [[0, 2, 4, "a"], [2, 4, 6, "c"], [360, 180, 360, "b"]]; - assert.deepEqual(df.values, expected); - assert.deepEqual(df.index, [0, 2, 1]); - - }); - - it("Sort values in DataFrame by specified column in ascending order (Default)", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 1, "b"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let df_sort = df.sort_values({ "by": "col3" }); - let expected = [[360, 180, 1, "b"], [0, 2, 4, "a"], [2, 4, 6, "c"]]; - assert.deepEqual(df_sort.values, expected); - assert.deepEqual(df_sort.index, [1, 0, 2]); - - }); - it("Sort values in DataFrame by specified column in descending order", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 360, "b"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let expected = [[360, 180, 360, "b"], [2, 4, 6, "c"], [0, 2, 4, "a"]]; - assert.deepEqual(df.sort_values({ "by": "col1", "ascending": false }).values, expected); - }); - - it("Sort values in DataFrame by specified column in descending order (second col)", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 1, "b"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let expected = [[2, 4, 6, "c"], [0, 2, 4, "a"], [360, 180, 1, "b"]]; - assert.deepEqual(df.sort_values({ "by": "col3", "ascending": false }).values, expected); - }); - it("Sort values in DataFrame by specified column containing alpha(numeric) values", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 1, "b"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let expected = [[2, 4, 6, 'c'], [360, 180, 1, 'b'], [0, 2, 4, 'a']]; - assert.deepEqual(df.sort_values({ "by": "col4", "ascending": false }).values, expected); - }); - it("Sort duplicate DataGrame with duplicate columns", function () { - - let data = { - "A": [1, 2, 3, 4, 5, 3, 5, 6, 4, 5, 3, 4], - "B": [2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] - }; - - let df = new dfd.DataFrame(data); - let expected = [[1, 2], - [2, 3], - [3, 4], - [3, 7], - [3, 3], - [4, 5], - [4, 1], - [4, 4], - [5, 6], - [5, 8], - [5, 2], - [6, 9]]; - assert.deepEqual(df.sort_values({ "by": "A", "ascending": true }).values, expected); - }); - - - }); - - describe("copy", function () { - it("Makes a deep copy of DataFrame", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new dfd.DataFrame(data); - let df_copy = df.copy(); - assert.deepEqual(df_copy.values, [[0, 2, 4], [360, 180, 360]]); - }); - }); - - - describe("set_index", function () { - it("Sets the index of a DataFrame created from an Object", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new dfd.DataFrame(data); - let df_new = df.set_index({ "index": ["one", "two", "three"] }); - assert.deepEqual(df_new.index, ["one", "two", "three"]); - }); - it("Sets the index of a DataFrame from column name", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new dfd.DataFrame(data); - let df_new = df.set_index({ "column": "alpha" }); - assert.deepEqual(df_new.index, ["A", "B", "C"]); - }); - it("Sets the index of a DataFrame from column name", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new dfd.DataFrame(data); - let df_new = df.set_index({ column: "alpha", drop: true }); - assert.deepEqual(df_new.index, ["A", "B", "C"]); - }); - it("Sets the index of a DataFrame created from an Array", function () { - let data = [[0, 2, 4], [360, 180, 360], [0, 2, 4], [360, 180, 360], [0, 2, 4]]; - let df = new dfd.DataFrame(data); - df.set_index({ "index": ["one", "two", "three", "four", "five"], "inplace": true }); - assert.deepEqual(df.index, ["one", "two", "three", "four", "five"]); - }); - - }); - - describe("reset_index", function () { - it("Resets the index of a DataFrame created from an Object", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new dfd.DataFrame(data); - let df_new = df.set_index({ "index": ["one", "two", "three"] }); - let df_reset = df_new.reset_index(); - assert.deepEqual(df_reset.index, [0, 1, 2]); - }); - it("Resets the index of a DataFrame created from an Array", function () { - let data = [[0, 2, 4], [360, 180, 360], [0, 2, 4], [360, 180, 360], [0, 2, 4]]; - let df = new dfd.DataFrame(data); - df.set_index({ "index": ["one", "two", "three", "four", "five"], "inplace": true }); - df.reset_index({ inplace: true }); - assert.deepEqual(df.index, [0, 1, 2, 3, 4]); - }); - - }); - - - describe("apply_map", function () { - it("Apply a function to all values of a DataFrame", function () { - let data = [[0, 2, 4], - [360, 180, 360], - [0, 2, 4]]; - let df = new dfd.DataFrame(data); - - let apply_func = (x) => { - return x + 1000; - }; - let expected = [[1000, 1002, 1004], [1360, 1180, 1360], [1000, 1002, 1004]]; - assert.deepEqual(df.apply_map(apply_func).values, expected); - }); - }); - - - describe("query", function () { - - it("Get the DataFrame containing rows with the filtered column", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let query_df = df.query({ condition: df["B"].ge(5) }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(query_df.values, query_data); - }); - it("Get the Dataframe containing rows with the filtered column in String values", function () { - let data = { "Abs": [20, 30, 47], "Count": [34, 4, 5], "country code": ["NG", "FR", "GH"] }; - let cols = ["Abs", "Count", "country code"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let query_df = df.query({ condition: df["country code"].eq("NG") }); - let query_data = [[20, 34, "NG"]]; - assert.deepEqual(query_df.values, query_data); - }); - - it("Confirms that query index are updated", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let df_query = df.query({ condition: df["B"].ge(5) }); - assert.deepEqual(df_query.index, [1, 2, 3]); - }); - - it("Confirms that query happens inplace", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.query({ condition: df["B"].ge(5), inplace: true }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(df.values, query_data); - }); - - - it("Get the DataFrame containing rows with the filtered column (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let query_df = df.query({ "column": "B", "is": ">=", "to": 5 }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(query_df.values, query_data); - }); - it("Get the Dataframe containing rows with the filtered column in String values (Without Condition)", function () { - let data = { "Abs": [20, 30, 47], "Count": [34, 4, 5], "country code": ["NG", "FR", "GH"] }; - let cols = ["Abs", "Count", "country code"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let query_df = df.query({ column: "country code", is: "==", to: "NG" }); - let query_data = [[20, 34, "NG"]]; - assert.deepEqual(query_df.values, query_data); - }); - it("Print Error for value key not specified (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "column": "B", "is": ">=" }); }, Error, "ParamError: specify a value to query by"); - }); - it("Print Error for operator key not specified (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "column": "B", "to": 5 }); }, Error, "ParamError: specify an operator to apply. operator must be one of >,<,<=,>=,==,!="); - }); - - it("Print Error for column key not specified (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "is": ">=", "to": 5 }); }, Error, "ParamError: specify a column name to query"); - }); - it("Print Error for column name not in dataframe (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "column": "D", "is": ">=", "to": 5 }); }, Error, "ParamError: column D not found in column names"); - }); - it("Confirms that query index are updated (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let df_query = df.query({ "column": "B", "is": ">=", "to": 5 }); - assert.deepEqual(df_query.index, [1, 2, 3]); - }); - it("Confirms that columns data are updated inplace (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.query({ "column": "B", "is": ">=", "to": 5, inplace: true }); - assert.deepEqual(df.getColumnData, [[4, 20, 39], [5, 30, 89], [6, 40, 78]]); - }); - it("Confirms that query happens inplace (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.query({ "column": "B", "is": ">=", "to": 5, inplace: true }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(df.values, query_data); - }); - it("Confirms that query happens inplace and index are updated (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - df.query({ "column": "B", "is": ">=", "to": 5, inplace: true }); - assert.deepEqual(df.index, [1, 2, 3]); - }); - }); - - describe("addColumn", function () { - it("Print the data, after changing a column data", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let new_col = [1, 2, 3, 4]; - - df.addColumn({ "column": "C", "values": new_col }); - - let new_data = [[1, 2, 1], [4, 5, 2], [20, 30, 3], [39, 89, 4]]; - - assert.deepEqual(df.values, new_data); - }); - it("Print the Dataframe column names, after a new column is added ", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let new_col = [1, 2, 3, 4]; - - df.addColumn({ "column": "D", "values": new_col, inplace: true }); - - let new_column = ["A", "B", "C", "D"]; - - assert.deepEqual(df.columns, new_column); - }); - it("Print Error for column name not in keyword passed", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let new_col = [1, 2, 3, 4]; - - assert.throws(function () { df.addColumn({ "values": new_col, inplace: true }); }, Error, "ParamError: column must be specified"); - }); - it("Check if new column value length is the same with Dataframe length", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let new_col = [1, 2, 3]; - assert.throws(function () { df.addColumn({ "column": "D", "values": new_col, inplace: true }); }, Error, "ParamError: Column data length mismatch. You provided data with length 3 but Ndframe has column of lenght 3"); - }); - - it("Check that dtype is updated after a new column is added ", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let new_col = ["n", "b", "c", "f"]; - - df.addColumn({ "column": "D", "values": new_col, inplace: true }); - let dtype = ["int32", "int32", "int32", "string"]; - - assert.deepEqual(df.dtypes, dtype); - }); - - it("add series as value to a new column ", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let sf = new dfd.Series(["n", "b", "c", "f"]); - - let newdf = df.addColumn({ "column": "D", "values": sf }); - let dtype = ["int32", "int32", "int32", "string"]; - - assert.deepEqual(newdf.dtypes, dtype); - }); - it("Confirms that column names are not changed", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let df_query = df.query({ "column": "B", "is": ">=", "to": 5 }); - assert.deepEqual(df_query.index, [1, 2, 3]); - assert.deepEqual(df_query.columns, ["A", "B", "C"]); - }); - - }); - - // describe("groupby", function () { - // it("Check group by One column data", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A"]); - - // let group_dict = { - // '1': [[1, 2, 3]], - // '4': [[4, 5, 6]], - // '20': [[20, 30, 40]], - // '39': [[39, 89, 78]] - // }; - - // assert.deepEqual(group_df.col_dict, group_dict); - // }); - // it("Obtain the DataFrame of one of the group", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A"]); - // let new_data = [[1, 2, 3]]; - - // assert.deepEqual(group_df.get_groups([1]).values, new_data); - // }); - // it("Check group by Two column data", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [[1, 2, 3]] }, - // '4': { '5': [[4, 5, 6]] }, - // '20': { '30': [[20, 30, 40]] }, - // '39': { '89': [[39, 89, 78]] } - // }; - - // assert.deepEqual(group_df.col_dict, new_data); - // }); - - // it("Obtain the DataFrame of one of the group, grouped by two column", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = [[1, 2, 3]]; - - // assert.deepEqual(group_df.get_groups([1, 2]).values, new_data); - // }); - - // it("Count column in group", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [1] }, - // '4': { '5': [1] }, - // '20': { '30': [1] }, - // '39': { '89': [1] } - // }; - - // assert.deepEqual(group_df.col(["C"]).count(), new_data); - // }); - // it("sum column element in group", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [3] }, - // '4': { '5': [6] }, - // '20': { '30': [40] }, - // '39': { '89': [78] } - // }; - - // assert.deepEqual(group_df.col(["C"]).sum(), new_data); - // }); - - // it("sum column element group by one column", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A"]); - - // let new_data = { '1': [2, 3], '4': [5, 6], '20': [30, 40], '39': [89, 78] }; - - // assert.deepEqual(group_df.col(["B", "C"]).sum(), new_data); - // }); - - // it("Perform aggregate on column for groupby", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [2, 1] }, - // '4': { '5': [5, 1] }, - // '20': { '30': [30, 1] }, - // '39': { '89': [89, 1] } - // }; - - // assert.deepEqual(group_df.agg({ "B": "mean", "C": "count" }), new_data); - // }); - - - // }); - - // describe("column", function () { - // it("Obtain a column from a dataframe created from object", function () { - // let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - // let options = { columns: ["Gender", "count"] }; - // let df = new dfd.DataFrame(data, options); - // let col_data = df.column("count"); - // let rslt_data = [1, 2, 3]; - // assert.deepEqual(col_data.values, rslt_data); - // }); - // it("Obtain a column from a dataframe", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // let col_data = df.column("C"); - // let rslt_data = [3, 6, 40, 78]; - // assert.deepEqual(col_data.values, rslt_data); - // }); - // it("Throw Error for wrong column", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new dfd.DataFrame(data, { columns: cols }); - // assert.throws(() => { df.column("D"); }, Error, "ParamError: Column not found!. Column name must be one of A,B,C"); - - // }); - // }); - - // describe("Concatenate", function () { - - // it("Check the axis 0 concatenation", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols = ["A", "B", "C"] - // let df = new dfd.DataFrame(data, { columns: cols }) - - // let data1 = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols1 = ["A", "B", "C"] - // let df1 = new dfd.DataFrame(data1, { columns: cols1 }) - - // let data2 = [[1, 2, 3, 5], [4, 5, 6, 8], [20, 30, 40, 10]] - // let cols2 = ["A", "B", "C", "D"] - // let df2 = new dfd.DataFrame(data2, { columns: cols2 }) - - // let new_df = DataFrame.concat({ "df_list": [df, df1, df2], "axis": 0 }) - - // let data_values = [[1, 2, 3, NaN], [4, 5, 6, NaN], [20, 30, 40, NaN], [39, 89, 78, NaN], - // [1, 2, 3, NaN], [4, 5, 6, NaN], [20, 30, 40, NaN], [39, 89, 78, NaN], - // [1, 2, 3, 5], [4, 5, 6, 8], [20, 30, 40, 10]] - - // assert.deepEqual(new_df.values, data_values); - // }); - - // it("Check the axis 1 concatenation", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols = ["A", "B", "C"] - // let df = new dfd.DataFrame(data, { columns: cols }) - - // let data1 = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols1 = ["A", "B", "C"] - // let df1 = new dfd.DataFrame(data1, { columns: cols1 }) - - // let data2 = [[1, 2, 3, 5], [4, 5, 6, 8], [20, 30, 40, 10]] - // let cols2 = ["A", "B", "C", "D"] - // let df2 = new dfd.DataFrame(data2, { columns: cols2 }) - - // let new_df = DataFrame.concat({ "df_list": [df, df1, df2], "axis": 1 }) - - // let data_values = [[1, 2, 3, 1, 2, 3, 1, 2, 3, 5], [4, 5, 6, 4, 5, 6, 4, 5, 6, 8], - // [20, 30, 40, 20, 30, 40, 20, 30, 40, 10], [39, 89, 78, 39, 89, 78, NaN, - // NaN, NaN, NaN]] - // assert.deepEqual(new_df.values, data_values); - // }); - // }); - - - describe("Apply", function () { - - it("Apply add operation element wise dataframe on axis 0", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let result = [6, 15, 90, 206]; - - let apply_rslt = df.apply((x) => { - return x.reduce((a, b) => a + b, 0); - }, { - axis: 0 - }); - - assert.deepEqual(apply_rslt.values, result); - }); - - it("Apply add operation element wise dataframe on axis 0", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - - let result = [64, 126, 127]; - - let apply_rslt = df.apply((x) => { - return x.reduce((a, b) => a + b, 0); - }, { - axis: 1 - }); - - assert.deepEqual(apply_rslt.values, result); - }); - }); - - describe("dropna", function () { - it("drop inplace at axis 0", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - - let df_val = [[5, 6, 7, 8]]; - - assert.deepEqual(df.dropna(0).values, df_val); - - }); - it("drop inplace at axis 1, inplace false ", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - - let df_val = [[1, 3], [4, 9], [6, 8]]; - - assert.deepEqual(df.dropna(1).values, df_val); - - }); - it("drop inplace at axis 1, inplace true ", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - - let df_val = [[1, 3], [4, 9], [6, 8]]; - df.dropna(1, { inplace: true }); - - - assert.deepEqual(df.values, df_val); - - }); - it("drop inplace at axis 0 at inplace true", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - - let df_val = [[5, 6, 7, 8]]; - - df.dropna(0, { inplace: true }); - assert.deepEqual(df.values, df_val); - - }); - }); - - describe("isna", function () { - - it("check if each value are nan", function () { - let data = [[NaN, 1, 2, 3], [3, 4, undefined, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - - let df_val = [ - [true, false, false, false], - [false, false, true, false], - [false, false, false, false] - ]; - - assert.deepEqual(df.isna().values, df_val); - }); - }); - - describe("fillna", function () { - - it("replace all NaN value", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - - let df_val = [[-999, 1, 2, 3], [3, 4, -999, 9], [5, 6, 7, 8]]; - df.fillna(-999, { inplace: true }); - assert.deepEqual(df.values, df_val); - }); - it("replace all NaN value", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - - let df_val = [[-999, 1, 2, 3], [3, 4, -999, 9], [5, 6, 7, 8]]; - - let df_filled = df.fillna(-999); - assert.deepEqual(df_filled.values, df_val); - }); - - it("Fills only a specified column", function () { - let data = [[1, 2, 3], - [4, 5, 6], - [20, NaN, 40], - [39, NaN, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let new_vals = [[1, 2, 3], [4, 5, 6], [20, 2, 40], [39, 2, 78]]; - let df_filled = df.fillna([2], { columns: ["B"] }); - - assert.deepEqual(df_filled.values, new_vals); - }); - it("Fills column with specified values not in place", function () { - let data = [[1, 2, 3], [4, 5, 6], [NaN, 20, 40], [NaN, -1, 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let new_vals = [[1, 2, 3], [4, 5, 6], [-2, 20, 40], [-2, -1, 78]]; - let df_filled = df.fillna([-2], { columns: ["A"] }); - - assert.deepEqual(df_filled.values, new_vals); - }); - - it("Fills a list of columns with specified values", function () { - let data = [[1, undefined, 3], [4, undefined, 6], [NaN, "boy", 40], [NaN, "girl", 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let new_vals = [[1, "girl", 3], [4, "girl", 6], [200, "boy", 40], [200, "girl", 78]]; - let df_filled = df.fillna([200, "girl"], { columns: ["A", "B"] }); - assert.deepEqual(df_filled.values, new_vals); - }); - it("Fills a list of columns with specified values inplace", function () { - let data = [[1, undefined, 3], [4, undefined, 6], [NaN, "boy", 40], [NaN, "girl", 78]]; - let cols = ["A", "B", "C"]; - let df = new dfd.DataFrame(data, { columns: cols }); - let new_vals = [[1, "girl", 3], [4, "girl", 6], [200, "boy", 40], [200, "girl", 78]]; - df.fillna([200, "girl"], { columns: ["A", "B"], inplace: true }); - assert.deepEqual(df.values, new_vals); - }); - }); - - - // describe("nanindex", function () { - - // it("print out the nanIndex", function () { - // let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - // let column = ["A", "B", "C", "D"]; - // let df = new dfd.DataFrame(data, { columns: column }); - - // let df_val = [0, 1]; - // assert.deepEqual(df.nanIndex(), df_val); - // }); - // }); - - describe("select_dtypes", function () { - - it("Returns float columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], [3.2, 4, 30, "girl"], [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['float32']); - assert.deepEqual(df_sub["A"].values, [30, 3.2, 5.09]); - }); - - it("Returns int columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['int32']); - assert.deepEqual(df_sub.values, [[1, 2], [4, 30], [6, 7]]); - }); - - it("Returns string columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['string']); - assert.deepEqual(df_sub["D"].values, ["boy", "girl", "cat"]); - }); - - it("Returns string and float columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let expected = [[30, "boy"], - [3.2, "girl"], - [5.09, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['string', 'float32']); - assert.deepEqual(df_sub.values, expected); - }); - - it("Returns int and float columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['int32', 'float32']); - assert.deepEqual(df_sub.values, [[30, 1, 2], [3.2, 4, 30], [5.09, 6, 7]]); - }); - }); - - describe("cum_ops", function () { - - it("check cumsum data", function () { - let data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - let rslt = [[2, 1, 2, 3], [5, 5, 13, 12], [10, 11, 20, 20]]; - - assert.deepEqual(df.cumsum({ axis: 1 }).values, rslt); - }); - it("check cumsum data along axis 1", function () { - let data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new dfd.DataFrame(data, { columns: column }); - let rslt = [[2, 3, 5, 8], [3, 7, 18, 27], [5, 11, 18, 26]]; - - assert.deepEqual(df.cumsum({ axis: 0 }).values, rslt); - }); - }); - - describe("lt", function () { - it("Returns Less than of DataFrame and other DataFrame (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new dfd.DataFrame(data1); - let df2 = new dfd.DataFrame(data2); - let expected = [[true, true, true, false], - [false, false, false, false]]; - assert.deepEqual(df.lt(df2).values, expected); - }); - - it("Return Less than of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let sf = new dfd.DataFrame(data1); - let expected = [[true, false, false, true], - [true, true, true, true]]; - assert.deepEqual(sf.lt(30).values, expected); - }); - it("Return Less than of series and DataFrame scalar along axis 1 (column)", function () { - let data1 = [[10, 45, 56, 10], - [23, 20, 10, 10]]; - let sf = new dfd.Series([10, 23, 56, 100]); - let df = new dfd.DataFrame(data1); - let expected = [[false, false, false, true], [false, true, true, true]]; - assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); - }); - - it("Return Less than of Array and DataFrame scalar along axis 1 (column)", function () { - let data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; - let sf = [10, 23, 56, 100]; - let df = new dfd.DataFrame(data1); - let expected = [[false, false, false, true], [false, true, true, true]]; - assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); - }); - - }); - - describe("gt", function () { - it("Return Greater than of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new dfd.DataFrame(data1); - let df2 = new dfd.DataFrame(data2); - let expected = [[false, false, false, true], [false, true, true, false]]; - assert.deepEqual(df.gt(df2).values, expected); - }); - - it("Return Greater than of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let sf = new dfd.DataFrame(data1); - let expected = [[false, true, true, false], [false, false, false, false]]; - assert.deepEqual(sf.gt(30).values, expected); - }); - - it("Return Less than of Array and DataFrame scalar along axis 1 (column)", function () { - let data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; - let sf = [10, 23, 56, 100]; - let df = new dfd.DataFrame(data1); - let expected = [[false, true, false, false], [true, false, false, false]]; - assert.deepEqual(df.gt(sf, { axis: 1 }).values, expected); - }); - - }); - - describe("le", function () { - it("Return Less than or Equal to of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new dfd.DataFrame(data1); - let df2 = new dfd.DataFrame(data2); - let expected = [[true, true, true, false], [true, false, false, true]]; - assert.deepEqual(df.le(df2).values, expected); - }); - - it("Return Less than or Equal to of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new dfd.DataFrame(data1); - let expected = [[true, false, false, true], [true, true, true, true]]; - assert.deepEqual(sf.le(30).values, expected); - }); - - }); - - describe("ge", function () { - it("Return Greater than or Equal to of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new dfd.DataFrame(data1); - let df2 = new dfd.DataFrame(data2); - let expected = [[false, false, false, true], [true, true, true, true]]; - assert.deepEqual(df.ge(df2).values, expected); - }); - - it("Return Greater than or Equal to of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new dfd.DataFrame(data1); - let expected = [[false, true, true, false], [false, false, true, false]]; - assert.deepEqual(sf.ge(30).values, expected); - }); - - }); - - describe("ne", function () { - it("Return Not Equal to of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new dfd.DataFrame(data1); - let df2 = new dfd.DataFrame(data2); - let expected = [[true, true, true, true], [false, true, true, false]]; - assert.deepEqual(df.ne(df2).values, expected); - }); - - it("Return Not Equal to of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new dfd.DataFrame(data1); - let expected = [[true, true, true, true], [true, true, false, true]]; - assert.deepEqual(sf.ne(30).values, expected); - }); - - }); - - describe("eq", function () { - it("Return Equal to of DataFrame and other DataFrame (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new dfd.DataFrame(data1); - let df2 = new dfd.DataFrame(data2); - let expected = [[false, false, false, false], [true, false, false, true]]; - assert.deepEqual(df.eq(df2).values, expected); - }); - - it("Return Equal to of DataFrame with scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new dfd.DataFrame(data1); - let expected = [[false, false, false, false], [false, false, true, false]]; - assert.deepEqual(sf.eq(30).values, expected); - }); - it("Return Equal to of series and DataFrame scalar along axis 1 (column)", function () { - let data1 = { "Col1": [10, 45, 56, 10], "Col2": [23, 20, 10, 10] }; - let sf = new dfd.Series([10, 23]); - let df = new dfd.DataFrame(data1); - let expected = [[true, true], [false, false], [false, false], [true, false]]; - assert.deepEqual(df.eq(sf, { axis: 1 }).values, expected); - }); - - }); - - describe("replace", function () { - it("Replace values given in replace param", function () { - let data1 = [[10, 45, 56, 25], [23, 20, 10, 24]]; - let sf = new dfd.DataFrame(data1); - let expected = [[-999, 45, 56, 25], [23, 20, -999, 24]]; - let df_rep = sf.replace(10, -999); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values given in replace param with value (String type)", function () { - let data1 = [["A", "A", "A", "B"], ["B", "C", "C", "D"]]; - let df = new dfd.DataFrame(data1); - let expected = [["boy", "boy", "boy", "B"], ["B", "C", "C", "D"]]; - let df_rep = df.replace("A", "boy"); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values in specified two column(s)", function () { - let data1 = [["A", "A", 1, "girl"], - ["B", "A", 2, "woman"], - ["A", "B", 3, "man"]]; - let df = new dfd.DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); - let expected = [["boy", "boy", 1, "girl"], - ["B", "boy", 2, "woman"], - ["boy", "B", 3, "man"]]; - let df_rep = df.replace("A", "boy", { columns: ["col1", "col2"] }); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values in specified single column(s)", function () { - let data1 = [[2, "A", 1, "girl"], - [3, "A", 2, "woman"], - [4, "B", 3, "man"]]; - let df = new dfd.DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); - let expected = [[2, "A", 1, "girl"], - [10, "A", 2, "woman"], - [4, "B", 3, "man"]]; - let df_rep = df.replace(3, 10, { columns: ["col1"] }); - assert.deepEqual(df_rep.values, expected); - }); - - }); - - - describe("sum", function () { - it("Sum values of a DataFrame by Default axis column (axis=1)", function () { - let data1 = [[30, 40, 3.1], - [5, 5, 5.1], - [5, 5, 3.2]]; - let sf = new dfd.DataFrame(data1); - let res = [40, 50, 11.399999999999999]; - assert.deepEqual(sf.sum().values, res); - }); - it("Sum values of a DataFrame along row axis (axis=0)", function () { - let data1 = [[30, 40, 3.1], - [5, 5, 5.1], - [5, 5, 3.2]]; - let df = new dfd.DataFrame(data1); - let res = [73.1, 15.1, 13.2]; - assert.deepEqual(df.sum({ axis: 0 }).values, res); - }); - it("Sum values of a mixed DataFrame along row axis (axis=0)", function () { - let data1 = [[30, 40, 3.1, true], - [5, 5, 5.1, true], - [5, 5, 3.2, true]]; - let df = new dfd.DataFrame(data1); - let res = [74.1, 16.1, 14.2]; - assert.deepEqual(df.sum({ axis: 0 }).values, res); - }); - it("Sum values of a boolean DataFrame along row axis (axis=0)", function () { - let data1 = [[true, true, false, true], - [false, false, false, false], - [false, true, true, false]]; - let df = new dfd.DataFrame(data1); - let res = [3, 0, 2]; - assert.deepEqual(df.sum({ axis: 0 }).values, res); - }); - it("Sum values of a boolean DataFrame along default column axis (axis=1)", function () { - let data1 = [[true, true, false, true], - [false, false, false, false], - [false, true, true, false]]; - let df = new dfd.DataFrame(data1); - let res = [1, 2, 1, 1]; - assert.deepEqual(df.sum().values, res); - }); - it("Sum values of a df with missing values", function () { - let data1 = [[11, 20, 3], [null, 15, 6], [2, 30, 40], [2, 89, 78]]; - let df = new dfd.DataFrame(data1); - let res = [15, 154, 127]; - assert.deepEqual(df.sum().values, res); - }); - - }); - - describe("abs", function () { - it("Returns the absolute values in DataFrame of ints", function () { - let data1 = [[-10, 45, 56, 10], [-25, 23, 20, -10]]; - let df = new dfd.DataFrame(data1); - let expected = [[10, 45, 56, 10], [25, 23, 20, 10]]; - assert.deepEqual(df.abs().values, expected); - }); - - it("Returns the absolute values in mixed DataFrame", function () { - let data1 = [[-10, -45.1, 56, 10], [-25, -23.2, 20, -10]]; - let df = new dfd.DataFrame(data1); - let expected = [[10, 45.1, 56, 10], [25, 23.2, 20, 10]]; - assert.deepEqual(df.abs().values, expected); - }); - }); - - describe("T", function () { - it("Returns the Tranpose of a DataFrame", function () { - let data1 = [[10, 45, 56, 10], - [25, 23, 20, 10]]; - - let cols = ["a", "b", "c", "d"]; - let df = new dfd.DataFrame(data1, { columns: cols }); - let df_trans = df.T; - let expected_vals = [[10, 25], [45, 23], [56, 20], [10, 10]]; - let expected_index = cols; - let expected_col_names = ['0', '1']; - assert.deepEqual(df_trans.index, expected_index); - assert.deepEqual(df_trans.values, expected_vals); - assert.deepEqual(df_trans.columns, expected_col_names); - - }); - - }); - - - describe("astype", function () { - it("set type of float column to int", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["a", "b", "c", "c"] - }; - let ndframe = new dfd.DataFrame(data); - let df = ndframe.astype({ column: "A", dtype: "int32" }); - - assert.deepEqual(df.dtypes, ['int32', 'int32', 'float32', 'string']); - assert.deepEqual(df['A'].values, [-20, 30, 47, -20]); - - }); - it("set type of int column to float", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["a", "b", "c", "c"] - }; - let ndframe = new dfd.DataFrame(data); - let df = ndframe.astype({ column: "B", dtype: "float32" }); - - assert.deepEqual(df.dtypes, ['float32', 'float32', 'float32', 'string']); - assert.deepEqual(df['B'].values, [34, -4, 5, 6]); - - }); - it("set type of string column to int", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["20.1", "21", "23.4", "50.78"] - }; - let ndframe = new dfd.DataFrame(data); - let df = ndframe.astype({ column: "D", dtype: "int32" }); - - assert.deepEqual(df.dtypes, ['float32', 'int32', 'float32', 'int32']); - assert.deepEqual(df['D'].values, [20, 21, 23, 50]); - - }); - it("set type of string column to float", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["20.1", "21", "23.4", "50.78"] - }; - let ndframe = new dfd.DataFrame(data); - let df = ndframe.astype({ column: "D", dtype: "float32" }); - - assert.deepEqual(df.dtypes, ['float32', 'int32', 'float32', 'float32']); - assert.deepEqual(df['D'].values, [20.1, 21, 23.4, 50.78]); - - }); - }); - - - describe("nunique", function () { - it("Returns the number of unique elements along axis 1", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new dfd.DataFrame(data); - let df = ndframe.nunique(1); - let res = [3, 4, 2, 3]; - assert.deepEqual(df.values, res); - - }); - it("Returns the number of unique elements along axis 0", function () { - let data = { - "A": [20, 30, 47.3, 30], - "B": [34, -4, 5, 30], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new dfd.DataFrame(data); - let df = ndframe.nunique(0); - let res = [3, 4, 4, 2]; - assert.deepEqual(df.values, res); - - }); - - }); - - describe("rename", function () { - it("Rename columns along axis 1", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new dfd.DataFrame(data); - let df = ndframe.rename({ mapper: { "A": "a1", "B": "b1" } }); - let res = ["a1", "b1", "C", "D"]; - assert.deepEqual(df.columns, res); - - }); - - it("Rename columns along axis 1 inplace", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let df = new dfd.DataFrame(data); - df.rename({ mapper: { "A": "a1", "B": "b1" }, inplace: true }); - let res = ["a1", "b1", "C", "D"]; - assert.deepEqual(df.columns, res); - - }); - it("Rename string index along axis 0", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new dfd.DataFrame(data, { index: ["a", "b", "c", "d"] }); - let df = ndframe.rename({ mapper: { "a": 0, "b": 1 }, axis: 0 }); - let res = [0, 1, "c", "d"]; - assert.deepEqual(df.index, res); - - }); - it("Rename string index along axis 0 inplace", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let df = new dfd.DataFrame(data, { index: ["a", "b", "c", "d"] }); - df.rename({ mapper: { "a": 0, "b": 1 }, axis: 0, inplace: true }); - let res = [0, 1, "c", "d"]; - assert.deepEqual(df.index, res); - - }); - - it("Get new column via subseting works after rename (inplace)", function () { - let data = { - "A": [-20, 30, 47.3], - "B": [34, -4, 5], - "C": [20, 2, 30] - }; - let df = new dfd.DataFrame(data); - df.rename({ mapper: { "A": "new_name" }, inplace: true }); - assert.deepEqual(df["new_name"].values, data["A"]); - }); - - it("Get new column via subseting works after rename (not-inplace)", function () { - let data = { - "A": [-20, 30, 47.3], - "B": [34, -4, 5], - "C": [20, 2, 30] - }; - let df = new dfd.DataFrame(data); - let new_df = df.rename({ mapper: { "A": "new_name" } }); - assert.deepEqual(new_df["new_name"].values, data["A"]); - }); - }); - - describe("sort_index", function () { - - it("sort index in ascending order", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - let df2 = df.sort_index(); - let rslt = [[360, 180, 360, 'a'], [0, 2, 4, 'b'], [2, 4, 6, 'c']]; - - assert.deepEqual(df2.values, rslt); - }); - it("sort index in descending order", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - let df2 = df.sort_index({ ascending: false }); - let rslt = [[2, 4, 6, 'c'], [0, 2, 4, 'b'], [360, 180, 360, 'a']]; - - assert.deepEqual(df2.values, rslt); - }); - it("sort index in descending order with inplace set to true", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - df.sort_index({ ascending: false, inplace: true }); - let rslt = [[2, 4, 6, 'c'], [0, 2, 4, 'b'], [360, 180, 360, 'a']]; - assert.deepEqual(df.values, rslt); - }); - it("sort index in descending order and retains index", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - let df2 = df.sort_index({ ascending: false }); - let rslt = ["c", "b", "a"]; - - assert.deepEqual(df2.index, rslt); - }); - }); - - describe("append", function () { - - it("Add a new single row (array) to the end of a DataFrame", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data); - let expected_val = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"], - [20, 40, 60, "d"]]; - - let rslt_df = df.append([[20, 40, 60, "d"]], [3]); - assert.deepEqual(rslt_df.values, expected_val); - - }); - - it("Add a new single row (object) to the end of a DataFrame", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let df2 = new dfd.DataFrame([[20, 40, 60, "d"]], { "columns": ["col1", "col2", "col3", "col4"] }); - - let expected_val = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"], - [20, 40, 60, "d"]]; - - let rslt_df = df.append(df2, [3]); - assert.deepEqual(rslt_df.values, expected_val); - - }); - it("Confirm index Change after append", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new dfd.DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let df2 = new dfd.DataFrame([[20, 40, 60, "d"]], { "columns": ["col1", "col2", "col3", "col4"] }); - - let rslt_df = df.append(df2, [3]); - assert.deepEqual(rslt_df.index, [0, 1, 2, 3]); - - }); - }); - - describe("Str", function () { - it("Str (startsWith) works for columns selected from a DF", function () { - let data = { - "Name": ["Apples", "Bake", "Application", undefined], - "Count": [2, 5, 4, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new dfd.DataFrame(data); - let name_sf = df['Name']; - assert.deepEqual(name_sf.str.startsWith("App").values, [true, false, true, NaN]); - }); - it("Str (toLowerCase) works for columns selected from a DF", function () { - let data = { - "Name": ["Apples", "Bake", "Application", undefined], - "Count": [2, 5, 4, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new dfd.DataFrame(data); - let name_sf = df['Name']; - assert.deepEqual(name_sf.str.toLowerCase().values, ["apples", "bake", "application", NaN]); - }); - }); - -}); diff --git a/danfojs-browser/tests/core/generic.js b/danfojs-browser/tests/core/generic.js deleted file mode 100644 index 0312b723..00000000 --- a/danfojs-browser/tests/core/generic.js +++ /dev/null @@ -1,259 +0,0 @@ -/* eslint-disable no-undef */ -const tf = require('@tensorflow/tfjs'); - - -describe("Generic (NDFrame)", function () { - describe("NDframe Created from Array", function () { - it("prints the shape of a 1D array", function () { - let data = [ 1, 2, 3, "Boy", "Girl" ]; - let ndframe = new dfd.NDframe({ data, isSeries:true }); - assert.deepEqual(ndframe.shape, [ 5, 1 ]); - }); - it("prints the default assigned column name in a series", function () { - let data = [ "Boy", 20, 25 ]; - let ndframe = new dfd.NDframe({ data, isSeries:true }); - assert.deepEqual(ndframe.columns, [ "0" ]); - }); - it("prints the assigned column name in a series", function () { - let data = [ "Boy", 20, 25 ]; - let options = { "columns": 'Records', isSeries : true }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.columns, "Records"); - }); - it("prints the shape of a 2D array", function () { - let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.shape, [ 2, 2 ]); - }); - it("prints the default assigned column names in 2D frame", function () { - let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.columns, [ "0", "1" ]); - }); - it("prints the assigned column names", function () { - let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; - let options = { "columns": [ "Gender", "Age" ], isSeries : false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.columns, [ "Gender", "Age" ]); - }); - it("prints the size of a frame", function () { - let data = [ [ "Boy", 20, 1 ], [ "Girl", 25, 3 ] ]; - let options = { "columns": [ "Gender", "Age", "count" ], isSeries : false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.size, 6); - }); - it("prints the dimension of a frame", function () { - let data = [ [ "Boy", 20, 1 ], [ "Girl", 25, 3 ] ]; - let options = { "columns": [ "Gender", "Age", "count" ], isSeries:false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.ndim, 2); - }); - it("prints the values of a frame", function () { - let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ] ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, data); - }); - it("prints the values of a frame", function () { - let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ] ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, data); - }); - }); - - describe("NDframe Created from JavaScript Object", function () { - - it("prints the shape of a 2D frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.shape, [ 3, 2 ]); - }); - it("prints the column names of frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.columns, [ "alpha", "count" ]); - }); - it("prints the shape of a 1D frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 } ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.shape, [ 1, 2 ]); - }); - - it("prints the size of a frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let options = { isSeries : false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.size, 6); - }); - it("prints the dimension of a frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; - let options = { isSeries : false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.ndim, 2); - }); - it("prints the values of a frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, [ [ "A", 1 ], [ "B", 2 ] ]); - }); - it("prints the values of a frame created from an Object with null values", function () { - let data = [ { alpha: "A", count: null }, { alpha: null, count: 2 } ]; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, [ [ "A", null ], [ null, 2 ] ]); - }); - }); - - describe("NDframe Created from a Tensor", function () { - - it("prints the shape of a 2D frame created from a 2D tensor", function () { - let data = tf.tensor([ 1, 2, 3, 4 ]); - let ndframe = new dfd.NDframe({ data, isSeries:true }); - assert.deepEqual(ndframe.ndim, 1); - assert.deepEqual(ndframe.values, [ 1, 2, 3, 4 ]); - - }); - it("prints the shape of a 2D frame created from a 1D tensor", function () { - let data = tf.tensor([ [ 2, 3, 4 ], [ 4, 5, 6 ] ]); - let ndframe = new dfd.NDframe({ data, columns: [ "alpha", "count", "sum" ], isSeries : false }); - assert.deepEqual(ndframe.columns, [ "alpha", "count", "sum" ]); - }); - - }); - - describe("index", function () { - it("Returns the index of an NDframe", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let df = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(df.index, [ 0, 1, 2 ]); - }); - it("Returns the index of an NDframe created from an Array", function () { - let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; - let df = new dfd.NDframe({ data, isSeries:false }); - assert.deepEqual(df.index, [ 0, 1, 2, 3 ]); - }); - }); - - describe("NDframe Created from JavaScript Object of Arrays", function () { - it("retrieves the row data created from OA ", function () { - let data = { alpha: [ "A", "B" ], count: [ 1, 2 ] }; - let ndframe = new dfd.NDframe({ data, isSeries:false }); - // assert.deepEqual(ndframe.shape, [4, 2]) - assert.deepEqual(ndframe.values, [ [ "A", 1 ], [ "B", 2 ] ]); - }); - }); - - describe("$setIndex", function () { - it("sets the index of an NDframe", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let df = new dfd.NDframe({ data, isSeries:false }); - df.$setIndex([ "A", "B", "C" ]); - assert.deepEqual(df.index, [ "A", "B", "C" ]); - }); - it("Returns the index of an NDframe created from an Array", function () { - let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; - let df = new dfd.NDframe({ data, isSeries:false }); - df.$setIndex([ 10, 20, 30, 40 ]); - assert.deepEqual(df.index, [ 10, 20, 30, 40 ]); - }); - }); - - - describe("dtype", function () { - it("Returns int dtype set during creation of 1DFrame (Series) from an Object", function () { - let data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; - let options = { dtypes: [ 'int32' ], isSeries : true }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ 'int32' ]); - }); - - it("Returns string dtype set during creation of 1DFrame (Series) from an Array", function () { - let data = [ "Alice", "Yemi", "Rising", "Mark" ]; - let options = { dtypes: [ 'string' ], isSeries : true }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string" ]); - }); - - it("Returns string dtype automatically inferred from 1DFrame (Series)", function () { - let data = [ "Alice", "Yemi", "Rising", "Mark" ]; - let options = { columns: 'Names', isSeries : true }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string" ]); - }); - - it("Returns int dtype automatically inferred from 1DFrame (Series)", function () { - let data = [ 20, 30, 20, 20 ]; - let options = { columns: 'Size', isSeries : true }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "int32" ]); - }); - it("Returns float dtype automatically inferred from 1DFrame (Series)", function () { - let data = [ 20.1, 30.4, 20.2, 4.23, 20.1 ]; - let options = { columns: 'Size', isSeries : true }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "float32" ]); - }); - - - it("Returns dtype set during creation of 2DFrame from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; - let options = { dtypes: [ 'string', 'int32' ], isSeries : false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ 'string', 'int32' ]); - }); - it("Returns dtype set during creation of 2DFrame from an Array", function () { - let data = [ [ "Alice", 2, 3.0 ], [ "Boy", 5, 6.1 ], [ "Girl", 30, 40 ], [ 39, 89, 78.2 ] ]; - let cols = [ "Name", "Count", "Score" ]; - let options = { columns: cols, dtypes: [ 'string', 'int32', 'float32' ], isSeries : false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string", "int32", "float32" ]); - }); - - it("Returns dtype automatically inferred from 2DFrame", function () { - let data = [ [ "Alice", 2, 3.1 ], [ "Boy", 5, 6.1 ], [ "Girl", 30, 40.2 ], [ 39, 89, 78.2 ] ]; - let cols = [ "Name", "Count", "Score" ]; - let options = { columns: cols, isSeries : false }; - let ndframe = new dfd.NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string", "int32", "float32" ]); - }); - - }); - - - // describe("to_csv", async function () { - // it("Converts DataFrame to csv format and return string", async function () { - // let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - // let df = new dfd.NDframe({ data, isSeries:true }); - // let result = `alpha,count\nA,1\nB,2\nC,3\n`; - // df.to_csv().then((csv) => { - // assert.deepEqual(csv, result); - // }); - // }); - // it("Converts DataFrame of Series to csv format and return string when path is not specified", async function () { - // let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; - // let df = new dfd.NDframe(data, { columns: [ "A", "B", "C" ] }); - // let result = `A,B,C\n12,2,20\n90,5,23\n45,56,70\n9,10,19\n`; - // assert.deepEqual(await df.to_csv(), result); - // }); - // }); - - // describe("to_json", async function () { - // it("Converts DataFrame to json format and return string", async function () { - // let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - // let result = JSON.stringify([ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]); - - // let df = new dfd.NDframe({ data, isSeries:true }); - // df.to_json().then((json) => { - // assert.deepEqual(json, result); - // }); - // }); - // it("Converts DataFrame to json format", async function () { - // let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ] ]; - // let df = new dfd.NDframe(data, { columns: [ "A", "B", "C" ] }); - // let result = JSON.stringify([ { A: 12, B: 2, C: 20 }, { A: 90, B: 5, C: 23 }, { A: 45, B: 56, C: 70 } ]); - // df.to_json().then((json) => { - // assert.deepEqual(json, result); - // }); - // }); - // }); - - -}); diff --git a/danfojs-browser/tests/core/get_dummies.js b/danfojs-browser/tests/core/get_dummies.js deleted file mode 100644 index 3acfea24..00000000 --- a/danfojs-browser/tests/core/get_dummies.js +++ /dev/null @@ -1,175 +0,0 @@ -/* eslint-disable no-undef */ - -describe("DummyEncoder", function () { - it("get_dummies works on Series", function () { - - const data = ["dog", "male", "female", "male", "female", "male", "dog"]; - const series = new dfd.Series(data); - const df = dfd.get_dummies(series, { prefix: "test", prefixSeparator: "/" }); - - const dfValues = [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [1, 0, 0] - ]; - const dfColumns = ['test/dog', 'test/male', 'test/female']; - assert.deepEqual(df.values, dfValues); - assert.deepEqual(df.columns, dfColumns); - }); - it("get_dummies works on Series with default prefix and prefixSeperator", function () { - - const data = ["dog", "male", "female", "male", "female", "male", "dog"]; - const series = new dfd.Series(data); - const df = dfd.get_dummies(series); - - const dfValues = [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [1, 0, 0] - ]; - const dfColumns = ['0_dog', '1_male', '2_female']; - assert.deepEqual(df.values, dfValues); - assert.deepEqual(df.columns, dfColumns); - }); - - it("get_dummies works on DataFrame", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new dfd.DataFrame(data, { columns: columns }); - - const df1 = dfd.get_dummies(df, { prefixSeparator: ["_", "#"], columns: ["A", "d"], prefix: "test" }); - const expectedColumns = ['B', 'C', 'test_1', 'test_3', 'test_4', 'test#fat', 'test#good', 'test#best']; - const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], - ['fog', 2.0, 0, 1, 0, 0, 1, 0], - ['gof', 3.0, 0, 0, 1, 0, 0, 1]]; - assert.deepEqual(df1.values, expected); - assert.deepEqual(df1.columns, expectedColumns); - - }); - it("Throw error if the prefix specified is not equal to the column specified", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new dfd.DataFrame(data, { columns: columns }); - - assert.throws(function () { dfd.get_dummies(df, { prefix: ["fg"], prefixSeparator: "_", columns: ["A", "d"] }); }, Error, - `ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "fg"}`); - - }); - it("replace column sepecified with prefix", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new dfd.DataFrame(data, { columns: columns }); - - const df1 = dfd.get_dummies(df, { prefix: ["F", "G"], prefixSeparator: "_", columns: ["A", "d"] }); - const expectedColumns = [ - 'B', 'C', - 'F_1', 'F_3', - 'F_4', 'G_fat', - 'G_good', 'G_best' - ]; - - const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], - ['fog', 2.0, 0, 1, 0, 0, 1, 0], - ['gof', 3.0, 0, 0, 1, 0, 0, 1]]; - - assert.deepEqual(df1.values, expected); - assert.deepEqual(df1.columns, expectedColumns); - - }); - - it("get_dummies auto infers and encode columns with string dtype", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new dfd.DataFrame(data, { columns: columns }); - - const df1 = dfd.get_dummies(df, { prefixSeparator: "_" }); - const expectedColumns = [ - 'A', 'C', - 'B_dog', 'B_fog', - 'B_gof', 'd_fat', - 'd_good', 'd_best' - ]; - const expected = [ - [ - 1, 1, 1, 0, - 0, 1, 0, 0 - ], - [ - 3, 2, 0, 1, - 0, 0, 1, 0 - ], - [ - 4, 3, 0, 0, - 1, 0, 0, 1 - ] - ]; - assert.deepEqual(df1.values, expected); - assert.deepEqual(df1.columns, expectedColumns); - - }); - - it("should one hot encode all other columns", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new dfd.DataFrame(data, { columns: columns }); - const rslt = [ - [1, 'dog', 1, 1, 0, 0], - [3, 'fog', 2, 0, 1, 0], - [4, 'gof', 3, 0, 0, 1] - ]; - - assert.deepEqual(dfd.get_dummies(df, { columns: ["d"] }).values, rslt); - - }); - - - it("Dummification works for object DF", function () { - - let data = { - fruits: ['pear', 'mango', "pawpaw", "mango", "bean"], - Count: [20, 30, 89, 12, 30], - Country: ["NG", "NG", "GH", "RU", "RU"] - }; - - let df = new dfd.DataFrame(data); - const expected = [ - [ - 20, 1, 0, 0, - 0, 1, 0, 0 - ], - [ - 30, 0, 1, 0, - 0, 1, 0, 0 - ], - [ - 89, 0, 0, 1, - 0, 0, 1, 0 - ], - [ - 12, 0, 1, 0, - 0, 0, 0, 1 - ], - [ - 30, 0, 0, 0, - 1, 0, 0, 1 - ] - ]; - - let dum_df = dfd.get_dummies(df, { prefixSeparator: "_" }); - assert.deepEqual(dum_df.values, expected); - - }); -}); diff --git a/danfojs-browser/tests/core/series.js b/danfojs-browser/tests/core/series.js deleted file mode 100644 index 0db59136..00000000 --- a/danfojs-browser/tests/core/series.js +++ /dev/null @@ -1,1328 +0,0 @@ -/* eslint-disable no-undef */ - -const tf = require('@tensorflow/tfjs'); - -describe("Series", function () { - describe("tensor", function () { - it("Returns the tensor object of a Series", function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.dtype, "int32"); - }); - it("Returns the float dtype of a tensor object", function () { - let data = [1.1, 2.2, 3, 4.1, 5, 620, 30.1, 40, 39, 89, 78]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.dtype, "float32"); - }); - it("Compares a tensor returned from a Series to Tensorflow's tensor", function () { - let data = [1.1, 2.2, 3, 4.1, 5, 620, 30.1, 40, 39, 89, 78]; - let sf = new dfd.Series(data); - let tf_data = tf.tensor(data); - assert.deepEqual(sf.tensor.arraySync(), tf_data.arraySync()); - }); - }); - describe("tensor", function () { - it("Returns the dtype string Series", function () { - let data = ["b", "c", "d"]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.dtype, "string"); - }); - it("Returns the dtype int Series", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.dtype, "int32"); - }); - it("Returns the dtype int Series", function () { - let data = [1.1, 2.2, 3.3, 4.5, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.dtype, "float32"); - }); - }); - - describe("head", function () { - it("Gets the first n rows in a Series", function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let cols = ["A"]; - let sf = new dfd.Series(data, { columns: cols }); - assert.deepEqual(sf.head(2).values, [1, 2]); - }); - }); - - describe("tail", function () { - it("Prints the last n rows of a Series", function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.tail(2).values, [89, 78]); - }); - }); - - describe("sample", function () { - it("Samples n number of random elements from a DataFrame", async function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new dfd.Series(data); - assert.deepEqual((await sf.sample(7)).values.length, 7); - }); - it("Throw error if n is greater than lenght of Series", async function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new dfd.Series(data); - try { - await sf.sample(100); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('Sample size n cannot be bigger than size of dataset'); - } - }); - }); - - describe("add", function () { - it("Return Addition of series with another series", function () { - let data = [1, 2, 3, 4, 5, 6]; - let data2 = [30, 40, 39, 1, 2, 1]; - let sf = new dfd.Series(data); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf.add(sf2).values, [31, 42, 42, 5, 7, 7]); - }); - it("Return Addition of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.add(1).values, [2, 3, 4, 5, 6]); - }); - it("Throws type error on addition of string type", function () { - let data = [1, 2, 3, 4]; - let data2 = ["A", "B", "C", "d"]; - let sf = new dfd.Series(data); - let sf2 = new dfd.Series(data2); - assert.throws( - () => { - sf.add(sf2); - }, - Error, - "DtypeError: String data type does not support add operation" - ); - }); - it("Throws length error if series lenght mixmatch", function () { - let data = [1, 2, 3, 4]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf = new dfd.Series(data); - let sf2 = new dfd.Series(data2); - assert.throws(() => { sf.add(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); - }); - }); - - describe("sub", function () { - it("Return Subtraction of series with another series", function () { - let data1 = [30, 40, 39, 1, 2, 1]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.sub(sf2).values, [29, 38, 36, -3, -3, -5]); - }); - it("Return Subtraction of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.sub(1).values, [0, 1, 2, 3, 4]); - }); - it("Throws type error on Subtraction of string type", function () { - let data = [1, 2, 3, 4]; - let data2 = ["A", "B", "C", "d"]; - let sf = new dfd.Series(data); - let sf2 = new dfd.Series(data2); - assert.throws( - () => { - sf.sub(sf2); - }, - Error, - "DtypeError: String data type does not support sub operation" - ); - }); - it("Throws length error if series lenght mixmatch", function () { - let data = [1, 2, 3, 4]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf = new dfd.Series(data); - let sf2 = new dfd.Series(data2); - assert.throws(() => { sf.sub(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); - }); - }); - - describe("mul", function () { - it("Return multiplication of series with another series", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [1, 2, 3, 4]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.mul(sf2).values, [30, 80, 9, 20]); - }); - it("Return multiplication of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.mul(1).values, [1, 2, 3, 4, 5]); - }); - it("Throws type error on multiplication of string type", function () { - let data = [1, 2, 3, 4]; - let data2 = ["A", "B", "C", "d"]; - let sf = new dfd.Series(data); - let sf2 = new dfd.Series(data2); - assert.throws(() => { sf.mul(sf2); }, Error, "DtypeError: String data type does not support mul operation"); - }); - it("Throws length error if series lenght mixmatch", function () { - let data = [1, 2, 3, 4]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf = new dfd.Series(data); - let sf2 = new dfd.Series(data2); - assert.throws(() => { sf.mul(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); - }); - }); - - describe("div", function () { - it("Return float division of series with another series", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [1, 2, 3, 4]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.div(sf2).values, [30, 20, 1, 1.25]); - }); - it("Return division of series with a single value (Broadcasting)", function () { - let data = [10, 2, 3, 90]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.div(2).values, [5, 1, 1.5, 45]); - }); - }); - - describe("pow", function () { - it("Return Exponetial power of series with another series", function () { - let data1 = [2, 3, 4, 5]; - let data2 = [1, 2, 3, 0]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.pow(sf2).values, [2, 9, 64, 1]); - }); - it("Return Exponetial power of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.pow(2).values, [1, 4, 9, 16, 25]); - }); - }); - - describe("mod", function () { - it("Return modulo of series with another float series", function () { - let data1 = [2, 30, 4, 5]; - let data2 = [1.1, 2.2, 3.3, 2.4]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - let expected = [ - 0.8999999999999999, - 1.3999999999999977, - 0.7000000000000002, - 0.20000000000000018 - ]; - assert.deepEqual(sf1.mod(sf2).values, expected); - }); - it("Return modulo of series with another int series", function () { - let data1 = [2, 30, 4, 5]; - let data2 = [1, 2, 3, 1]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.mod(sf2).values, [0, 0, 1, 0]); - }); - it("Return modulo power of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.mod(2).values, [1, 0, 1, 0, 1]); - }); - }); - - describe("mean", function () { - it("Computes the mean of elements in a int series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.mean(), 19.5); - }); - it("Computes the mean of elements in a float series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.mean(), 19.625); - }); - it("Computes the mean of elements in a float series with NaN", function () { - let data1 = [30.1, 40.2, 3.1, 5.1, NaN]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.mean(), 19.625); - }); - it("Throws error if dtype is string", function () { - let data1 = ["boy", "girl", "Man"]; - let sf = new dfd.Series(data1); - assert.throws( - () => { - sf.mean(); - }, - Error, - "DtypeError: String data type does not support mean operation" - ); - }); - }); - - describe("median", function () { - it("Computes the median value of elements across int Series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.median(), 17.5); - }); - it("Computes the median value of elements across float Series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1, NaN]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.median(), 17.6); - }); - }); - - describe("sum", function () { - it("Sum values of a Int Series", function () { - let data1 = [30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.sum(), 131); - }); - it("Sum values of a Float Series", function () { - let data1 = [30.1, 3.1, 40.2, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.sum(), 81.6); - }); - it("Sum values of a bool Series", function () { - let data1 = [true, true, false, false, false]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.sum(), 2); - }); - it("Sum values a Series with missing values", function () { - let data1 = [11, NaN, 2, 2]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.sum(), 15); - }); - }); - - describe("mode", function () { - it("Computes the multi-modal values of a Series", function () { - let data1 = [30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.mode(), [5, 3]); - }); - it("Computes the modal value of a Series", function () { - let data1 = [30.1, 3.1, 40.2, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.mode(), [3.1]); - }); - }); - - describe("min", function () { - it("Returns the single smallest elementin a Series", function () { - let data = [30, 40, 3, 5]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.min(), 3); - }); - it("Computes the minimum of elements across an float Series", function () { - let data1 = [30.1, 40.2, 3.12, 5.1]; - let sf = new dfd.Series(data1, { dtypes: ["float32"] }); - assert.deepEqual(Number(sf.min().toFixed(2)), 3.12); - }); - }); - - describe("max", function () { - it("Computes the maximum of elements across dimensions of a Series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.max(), 40); - }); - it("Return sum of float values in a series", function () { - let data1 = [30.1, 40.21, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(Number(sf.max().toFixed(2)), 40.21); - }); - it("Throws error on addition of string Series", function () { - let data1 = ["boy", "gitl", "woman", "man"]; - let sf = new dfd.Series(data1); - assert.throws( - () => { - sf.max(); - }, - Error, - "DtypeError: String data type does not support max operation" - ); - }); - }); - - describe("std", function () { - it("Computes the standard of elements in a int series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.std(), 18.375708603116962); - }); - it("Computes the standard deviation of elements in a float series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.std(), 18.412925713566906); - }); - it("Computes the standard deviation of elements in a float series with missing values", function () { - let data1 = [30, 40, 3, 5, undefined]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.std(), 18.375708603116962); - }); - }); - - describe("var", function () { - it("Computes the variance of elements in a int series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.var(), 337.6666666666667); - }); - it("Computes the variance of elements in a float series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.var(), 339.03583333333336); - }); - it("Computes the variance of elements in a int series with missing values", function () { - let data1 = [30, undefined, 40, 3, 5]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.var(), 337.6666666666667); - }); - }); - - describe("describe", function () { - it("Computes the descriptive statistics on an int Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.describe().round().values, [ - 7, - 27, - 17.4, - 10, - 23, - 56, - 302 - ]); - }); - it("Computes the descriptive statistics on a float Series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.describe().round().values, [4, 19.6, 18.4, 3.1, 17.6, 40.2, 339]); - }); - it("Computes the descriptive statistics on a float Series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.describe().index, [ - "count", - "mean", - "std", - "min", - "median", - "max", - "variance" - ]); - }); - }); - - describe("maximum", function () { - it("Returns the max of a and b (a > b ? a : b) element-wise. Supports broadcasting.", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [10, 41, 2, 0]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.maximum(sf2).values, [30, 41, 3, 5]); - }); - it("Throws error on checking maximum of incompatible Series", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [10, 41, 2]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.throws( - () => { - sf1.maximum(sf2); - }, - Error, - "ParamError: Row length mismatch. Length of other (3), must be the same as Ndframe (4)" - ); - }); - }); - - describe("minimum", function () { - it("Returns the min of a and b (a < b ? a : b) element-wise. Supports broadcasting.", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [10, 41, 2, 0]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.minimum(sf2).values, [10, 40, 2, 0]); - }); - it("Return sum of float values in a series", function () { - let data1 = [30.1, 40.9, 3, 5]; - let data2 = [10.2, 41, 2, 0]; - let sf1 = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - assert.deepEqual(sf1.minimum(sf2).values, [10.2, 40.9, 2, 0]); - - }); - }); - - describe("count", function () { - it("Returns the count of non NaN values in a string Series", function () { - let data = ["boy", "gitl", "woman", NaN]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.count(), 3); - }); - it("Returns the count of non NaN values in a string Series", function () { - let data = ["boy", "gitl", "woman", "Man"]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.count(), 4); - }); - it("Returns the count of non NaN values in a int Series", function () { - let data = [20, 30, NaN, 2, NaN, 30, 21]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.count(), 5); - }); - it("Returns the count of non NaN values in a float Series", function () { - let data = [20.1, 30.4, NaN, 2.1, NaN, 30.0, 21.3]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.count(), 5); - }); - }); - - describe("round", function () { - it("Rounds elements in a Series to nearest whole number", function () { - let data1 = [30.21091, 40.190901, 3.564, 5.0212]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.round(0).values, [30, 40, 4, 5]); - }); - it("Rounds elements in a Series to 1dp", function () { - let data1 = [30.21091, 40.190901, 3.564, 5.0212]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.round(1).values, [30.2, 40.2, 3.6, 5.0]); - }); - it("Rounds elements in a Series to 2dp", function () { - let data1 = [30.2191, 40.190901, 3.564, 5.0212]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.round(2).values, [30.22, 40.19, 3.56, 5.02]); - }); - }); - - describe("isna", function () { - it("Return a boolean same-sized object indicating if string Series contain NaN", function () { - let data1 = [NaN, undefined, "girl", "Man"]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.isna().values, [true, true, false, false]); - }); - it("Return a boolean same-sized object indicating if float Series values are NaN", function () { - let data1 = [30.21091, NaN, 3.564, undefined]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.isna().values, [false, true, false, true]); - }); - it("Return a boolean same-sized object indicating if int Series values are NaN", function () { - let data1 = [30, 40, 3, 5, undefined, undefined]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.isna().values, [ - false, - false, - false, - false, - true, - true - ]); - }); - }); - - describe("sort_values", function () { - it("Sort values in a Series in ascending order (not inplace)", function () { - let sf = new dfd.Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [0, 1, 2, 4, 4, 20, 30, 57, 89]; - let sorted_sf = sf.sort_values(); - assert.deepEqual(sorted_sf.values, result); - }); - it("confirms that sort_values in ascending order does not happen inplace", function () { - let sf = new dfd.Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [0, 1, 2, 4, 4, 20, 30, 57, 89]; - let expected_index = [7, 2, 3, 8, 4, 0, 1, 5, 6]; - sf.sort_values({ inplace: true }); - assert.deepEqual(sf.values, result); - assert.deepEqual(sf.index, expected_index); - }); - it("Sort values in a Series in Descending order", function () { - let sf = new dfd.Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [89, 57, 30, 20, 4, 4, 2, 1, 0]; - let sorted_sf = sf.sort_values({ ascending: false }); - assert.deepEqual(sorted_sf.values, result); - }); - it("confirms that sort_values in descending order happens inplace", function () { - let sf = new dfd.Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [89, 57, 30, 20, 4, 4, 2, 1, 0]; - sf.sort_values({ ascending: false, inplace: true }); - assert.deepEqual(sf.values, result); - }); - it("Confirms that series index is sorted in ascending order (not in inplace)", function () { - let sf = new dfd.Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [7, 2, 3, 8, 4, 0, 1, 5, 6]; - let sorted_sf = sf.sort_values(); - assert.deepEqual(sorted_sf.index, result); - }); - it("Confirms that series index is sorted in descending order (not in inplace)", function () { - let sf = new dfd.Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [6, 5, 1, 0, 4, 8, 3, 2, 7]; - let sorted_sf = sf.sort_values({ ascending: false }); - assert.deepEqual(sorted_sf.index, result); - }); - it("Sort string values in a Series", function () { - let sf = new dfd.Series(["boy", "zebra", "girl", "man"]); - let result = ["boy", "girl", "man", "zebra"]; - let sorted_sf = sf.sort_values({ ascending: false }); - assert.deepEqual(sorted_sf.values, result); - }); - }); - - describe("copy", function () { - it("Checks if copied values are the same as the first one", function () { - let sf = new dfd.Series([30.21091, 40.190901, 3.564, 5.0212]); - let sf_copy = sf.copy(); - assert.deepEqual(sf.values, sf_copy.values); - }); - it("Checks if copied index are the same", function () { - let sf = new dfd.Series([30.21091, 40.190901, 3.564, 5.0212]); - sf = sf.set_index({ index: ["a", "b", "c", "d"] }); - let sf_copy = sf.copy(); - assert.deepEqual(sf.index, sf_copy.index); - }); - it("Checks if copied dtype is the same", function () { - let sf = new dfd.Series([30.21091, 40.190901, 3.564, 5.0212]); - sf.round(); - sf.astype('int32'); - let sf_copy = sf.copy(); - assert.deepEqual(sf.dtypes[0], sf_copy.dtypes[0]); - assert.deepEqual(sf.values, sf_copy.values); - - }); - }); - - describe("reset_index", function () { - it("resets the index of a Series", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new dfd.Series(data); - let df_new = df.set_index({ index: ["one", "two", "three"] }); - let df_reset = df_new.reset_index(); - assert.deepEqual(df_reset.index, [0, 1, 2]); - }); - it("Reset the index of a Series created from an Array", function () { - let data = [1, 2, 3, 4, 5, 6]; - let df = new dfd.Series(data); - df.set_index({ - index: ["one", "two", "three", "four", "five", "six"], - inplace: true - }); - let df_new = df.reset_index(); - assert.deepEqual(df_new.index, [0, 1, 2, 3, 4, 5]); - }); - it("checks that the original series changed after reseting new index inplace", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new dfd.Series(data); - df.reset_index({ inplace: true }); - assert.deepEqual(df.index, [0, 1, 2]); - }); - }); - - describe("set_index", function () { - it("sets the index of an Series", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new dfd.Series(data); - let df_new = df.set_index({ index: ["one", "two", "three"] }); - assert.deepEqual(df_new.index, ["one", "two", "three"]); - assert.notDeepEqual(df.index, df_new.index); - }); - it("checks that the original series is not modified after setting new index not-inplace", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new dfd.Series(data); - let df_new = df.set_index({ index: ["one", "two", "three"] }); - assert.notDeepEqual(df.index, df_new.index); - }); - it("sets the index of an Series inplace", function () { - let data = [12, 2, 20, 50]; - let df = new dfd.Series(data); - df.set_index({ index: ["one", "two", "three", "four"], inplace: true }); - assert.deepEqual(df.index, ["one", "two", "three", "four"]); - }); - }); - - describe("Map", function () { - it("map series element to object keys", function () { - let sf = new dfd.Series([1, 2, 3, 4]); - let map = { 1: "ok", 2: "okie", 3: "frit", 4: "gop" }; - - let rslt = ["ok", "okie", "frit", "gop"]; - - assert.deepEqual(sf.map(map).values, rslt); - }); - - it("map series element to a function statement", function () { - let sf = new dfd.Series([1, 2, 3, 4]); - let func_map = (x) => { - return x + 1; - }; - - let rslt = [2, 3, 4, 5]; - - assert.deepEqual(sf.map(func_map).values, rslt); - }); - }); - - describe("Apply", function () { - it("apply a function to a series element", function () { - let sf = new dfd.Series([1, 2, 3, 4, 5, 6, 7, 8]); - - let apply_func = (x) => { - return x + x; - }; - - let rslt = [2, 4, 6, 8, 10, 12, 14, 16]; - assert.deepEqual(sf.apply(apply_func).values, rslt); - }); - }); - - describe("unique", function () { - it("returns the unique values in a Series of type int", function () { - let sf = new dfd.Series([1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5]); - let expected = [1, 2, 3, 4, 5, 6, 7, 8, 22]; - assert.deepEqual(sf.unique().values, expected); - }); - it("returns the unique values in a Series of type string", function () { - let sf = new dfd.Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected = ["a", "b", "c", "d", "e"]; - assert.deepEqual(sf.unique().values, expected); - }); - it("returns the unique values in a Series of type string", function () { - let sf = new dfd.Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected = ["a", "b", "c", "d", "e"]; - assert.deepEqual(sf.unique().values, expected); - }); - it("returns the nunique values in a Series of type string", function () { - let sf = new dfd.Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected = 5; - assert.deepEqual(sf.nunique(), expected); - }); - }); - - describe("value_counts", function () { - it("returns the unique values and their counts in a Series of type int", function () { - let sf = new dfd.Series([1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5]); - let expected_index = [1, 2, 3, 4, 5, 6, 7, 8, 22]; - let expected_vals = [3, 1, 1, 1, 4, 1, 1, 2, 1]; - assert.deepEqual(sf.value_counts().values, expected_vals); - assert.deepEqual(sf.value_counts().index, expected_index); - }); - it("returns the unique values and their counts in a Series of type string", function () { - let sf = new dfd.Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected_vals = [2, 1, 2, 3, 2]; - let expected_index = ["a", "b", "c", "d", "e"]; - assert.deepEqual(sf.value_counts().values, expected_vals); - assert.deepEqual(sf.value_counts().index, expected_index); - }); - }); - - describe("abs", function () { - it("Returns the absolute values in Series", function () { - let data1 = [-10, 45, 56, -25, 23, -20, 10]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.abs().values, [10, 45, 56, 25, 23, 20, 10]); - }); - it("Computes the descriptive statistics on a float Series", function () { - let data1 = [-30.1, -40.2, -3.1, -5.1]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.abs().values, [30.1, 40.2, 3.1, 5.1]); - }); - }); - - describe("fillna", function () { - it("replace all NaN value with specified value", function () { - let data = [NaN, 1, 2, 33, 4, NaN, 5, 6, 7, 8]; - let sf = new dfd.Series(data); - let sf_val = [-999, 1, 2, 33, 4, -999, 5, 6, 7, 8]; - sf.fillna({ value: -999, inplace: true }); - assert.deepEqual(sf.values, sf_val); - }); - it("replace all NaN value in string Series with specified value", function () { - let data = [NaN, "boy", NaN, "hey", "Man", undefined]; - let sf = new dfd.Series(data); - let sf_val = ["filled", "boy", "filled", "hey", "Man", "filled"]; - let sf_fill = sf.fillna({ value: "filled" }); - assert.deepEqual(sf_fill.values, sf_val); - }); - }); - - describe("cumsum", function () { - it("Return cumulative sum over a Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.cumsum().values, [10, 55, 111, 136, 159, 179, 189]); - }); - }); - - describe("cummax", function () { - it("Return cumulative maximum over a Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.cummax().values, [10, 45, 56, 56, 56, 56, 56]); - }); - }); - - describe("cummin", function () { - it("Return cumulative minimum over a Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - assert.deepEqual(sf.cummin().values, [10, 10, 10, 10, 10, 10, 10]); - }); - }); - - describe("cumprod", function () { - it("Return cumulative product over a Series", function () { - let data1 = [1, 2, 10, 3, 12, 14, 1]; - let sf = new dfd.Series(data1); - let rslt = [1, 2, 20, 60, 720, 10080, 10080]; - assert.deepEqual(sf.cumprod().values, rslt); - }); - }); - - describe("lt", function () { - it("Return Less than of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 5, 25, 2, 0]; - - let sf = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - let expected = [true, true, true, false, true, false, false]; - assert.deepEqual(sf.lt(sf2).values, expected); - }); - - it("Return Less than of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - let expected = [true, false, false, true, true, true, true]; - assert.deepEqual(sf.lt(30).values, expected); - }); - it("Correct index is returned after operation", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new dfd.Series(data1, { index: ["one", "two", "three", "four", "five"] }); - - const expected = ["one", "two", "three", "four", "five"]; - assert.deepEqual(sf.lt(data2).index, expected); - }); - }); - - describe("gt", function () { - it("Return Greater than of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 5, 25, 2, 0]; - - let sf = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - let expected = [false, false, false, true, false, true, true]; - assert.deepEqual(sf.gt(sf2).values, expected); - }); - - it("Return Greater than of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - let expected = [false, true, true, false, false, false, false]; - assert.deepEqual(sf.gt(30).values, expected); - }); - }); - - describe("le", function () { - it("Return Less than or Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 5, 25, 2, 0]; - - let sf = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - let expected = [true, true, true, false, true, false, false]; - assert.deepEqual(sf.le(sf2).values, expected); - }); - - it("Return Less than or Equal to of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - let expected = [true, false, false, true, true, true, true]; - assert.deepEqual(sf.le(30).values, expected); - }); - }); - - describe("ge", function () { - it("Return Greater than or Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 56, 5, 25, 20, 0]; - - let sf = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - let expected = [false, false, true, true, false, true, true]; - assert.deepEqual(sf.ge(sf2).values, expected); - }); - - it("Return Greater than or Equal to of series scalar (element-wise)", function () { - let data1 = [30, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - let expected = [true, true, true, false, false, false, false]; - assert.deepEqual(sf.ge(30).values, expected); - }); - }); - - describe("ne", function () { - it("Return Not Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [10, 450, 56, 5, 25, 2, 0]; - - let sf = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - let expected = [false, true, false, true, true, true, true]; - assert.deepEqual(sf.ne(sf2).values, expected); - }); - - it("Return Not Equal to of series scalar (element-wise)", function () { - let data1 = [10, 30, 56, 30, 23, 20, 10]; - let sf = new dfd.Series(data1); - let expected = [true, false, true, false, true, true, true]; - assert.deepEqual(sf.ne(30).values, expected); - }); - }); - - describe("eq", function () { - it("Return Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 25, 25, 2, 0]; - - let sf = new dfd.Series(data1); - let sf2 = new dfd.Series(data2); - let expected = [false, false, false, true, false, false, false]; - assert.deepEqual(sf.eq(sf2).values, expected); - }); - - it("Return Equal to of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 30]; - let sf = new dfd.Series(data1); - let expected = [false, false, false, false, false, false, true]; - assert.deepEqual(sf.eq(30).values, expected); - }); - }); - - describe("replace", function () { - it("Replace values given in replace param with value", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new dfd.Series(data1); - let expected = [-50, 45, 56, 25, 23, 20, -50]; - let df_rep = sf.replace({ oldValue: 10, newValue: -50 }); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values given in replace param with value (String type)", function () { - let data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; - let sf = new dfd.Series(data1); - let expected = ["boy", "boy", "boy", "B", "B", "C", "C", "D"]; - sf.replace({ oldValue: "A", newValue: "boy", inplace: true }); - assert.deepEqual(sf.values, expected); - }); - it("Throw error on wrong param passed", function () { - let data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; - let sf = new dfd.Series(data1); - let expected = `Params Error: Must specify param 'oldValue' to replace`; - assert.throws( - () => { - sf.replace({ newValue: "boy", inplace: true }); - }, - Error, - expected - ); - }); - }); - - describe("drop_duplicates", function () { - it("Return Series with duplicate values removed (Default, first values kept)", function () { - let data1 = [10, 45, 56, 10, 23, 20, 10, 10]; - let sf = new dfd.Series(data1); - let expected = [10, 45, 56, 23, 20]; - let expected_index = [0, 1, 2, 4, 5]; - let df_drop = sf.drop_duplicates(); - assert.deepEqual(df_drop.values, expected); - assert.deepEqual(df_drop.index, expected_index); - }); - - it("Return Series with duplicate values removed (last values kept)", function () { - let data1 = [10, 45, 56, 10, 23, 20, 10, 10]; - let sf = new dfd.Series(data1); - let expected = [45, 56, 23, 20, 10]; - let expected_index = [1, 2, 4, 5, 7]; - let df_drop = sf.drop_duplicates({ keep: "last" }); - assert.deepEqual(df_drop.values, expected); - assert.deepEqual(df_drop.index, expected_index); - }); - - it("Return Series with duplicate values removed (String)", function () { - let data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; - let sf = new dfd.Series(data1); - let expected = ["A", "B", "C", "D"]; - let expected_index = [0, 3, 5, 7]; - sf.drop_duplicates({ inplace: true }); - assert.deepEqual(sf.values, expected); - assert.deepEqual(sf.index, expected_index); - }); - }); - - describe("dropna", function () { - it("Return a new dfd.Series with missing values removed (Int)", function () { - let data1 = [10, 45, undefined, 10, 23, 20, undefined, 10]; - let sf = new dfd.Series(data1); - let expected = [10, 45, 10, 23, 20, 10]; - let expected_index = [0, 1, 3, 4, 5, 7]; - let sf_drop = sf.dropna(); - assert.deepEqual(sf_drop.values, expected); - assert.deepEqual(sf_drop.index, expected_index); - }); - - it("Return a new dfd.Series with missing values removed (String)", function () { - let data1 = ["A", NaN, "A", "B", "B", NaN, "C", undefined]; - let sf = new dfd.Series(data1); - let expected = ["A", "A", "B", "B", "C"]; - let expected_index = [0, 2, 3, 4, 6]; - - sf.dropna({ inplace: true }); - assert.deepEqual(sf.values, expected); - assert.deepEqual(sf.index, expected_index); - }); - }); - - describe("argsort", function () { - it("Return the integer indices that would sort the Series values", function () { - let data1 = [10, 45, 20, 10, 23, 20, 30, 11]; - let sf = new dfd.Series(data1); - let expected = [3, 0, 7, 5, 2, 4, 6, 1]; - let sf_sort = sf.argsort(); - assert.deepEqual(sf_sort.values, expected); - }); - - it("Return the integer indices that would sort the Series values (Float)", function () { - let data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; - let sf = new dfd.Series(data1); - let expected = [2, 1, 3, 0, 7, 5, 4, 6]; - let sf_sort = sf.argsort(false); - assert.deepEqual(sf_sort.values, expected); - }); - }); - - describe("argmax", function () { - it("Return int position of the largest value in the Series.", function () { - let data1 = [10, 45, 20, 10, 23, 20, 30, 11]; - let sf = new dfd.Series(data1); - let expected = 1; - let argmax = sf.argmax(); - assert.deepEqual(argmax, expected); - }); - - it("Return int position of the largest value in the Float Series.", function () { - let data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; - let sf = new dfd.Series(data1); - let expected = 6; - let argmax = sf.argmax(); - assert.deepEqual(argmax, expected); - }); - }); - - describe("argmin", function () { - it("Return int position of the smallest value in the Series", function () { - let data1 = [10, 45, 20, 122, 23, 20, 30, 11]; - let sf = new dfd.Series(data1); - let expected = 0; - let argmin = sf.argmin(); - assert.deepEqual(argmin, expected); - }); - - it("Return int position of the smallest value in a Float Series", function () { - let data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; - let sf = new dfd.Series(data1); - let expected = 2; - let argmin = sf.argmin(); - assert.deepEqual(argmin, expected); - }); - }); - - describe("Str", function () { - it("Converts all characters to lowercase.", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["lower", "capitals", "this is a sentence", "swapcase"]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.str.toLowerCase().values, res); - }); - it("Converts all characters to uppercase.", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["LOWER", "CAPITALS", "THIS IS A SENTENCE", "SWAPCASE"]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.str.toUpperCase().values, res); - }); - it("Converts all characters to capital case.", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["Lower", "Capitals", "This is a sentence", "Swapcase"]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.str.capitalize().values, res); - }); - - it("Returns the character at the specified index (position)", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["w", "P", "i", "A"]; - let sf = new dfd.Series(data); - assert.deepEqual(sf.str.charAt(2).values, res); - }); - - it("Throws error on concat of numeric series", function () { - let data = [1, 2, 3, 4, 5, 6]; - let sf = new dfd.Series(data); - assert.throws( - () => { - sf.str.concat("20", 1); - }, - Error, - "Cannot call accessor str on non-string type" - ); - - }); - }); - - describe("dt", function () { - it("check month generated", function () { - let data = ["02Sep2019", "03Dec2019", "04Jan2019"]; - let sf = new dfd.Series(data); - let new_data = [8, 11, 0]; - assert.deepEqual(sf.dt.month().values, new_data); - }); - - it("check month Name generated", function () { - let data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - let sf = new dfd.Series(data); - let new_data = ["Jun", "Jul", "Aug"]; - assert.deepEqual(sf.dt.month_name().values, new_data); - }); - - it("check days of the weeks generated", function () { - let data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - let sf = new dfd.Series(data); - let new_data = ["Sun", "Mon", "Wed"]; - assert.deepEqual(sf.dt.weekdays().values, new_data); - }); - - it("check day of the month generated", function () { - let data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - let sf = new dfd.Series(data); - let new_data = [30, 29, 28]; - assert.deepEqual(sf.dt.monthday().values, new_data); - }); - }); - - describe("astype", function () { - it("set type of float column to int", function () { - let data = [-20.1, 30, 47.3, -20]; - let ndframe = new dfd.Series(data); - let df = ndframe.astype("int32"); - - assert.deepEqual(df.dtypes, ["int32"]); - assert.deepEqual(df.values, [-20, 30, 47, -20]); - }); - it("set type of int column to float", function () { - let data = [34, -4, 5, 6]; - let ndframe = new dfd.Series(data); - let df = ndframe.astype("float32"); - assert.deepEqual(df.dtypes, ["float32"]); - assert.deepEqual(df.values, [34, -4, 5, 6]); - }); - it("set type of string column to int", function () { - let data = ["20.1", "21", "23.4", "50.78"]; - let ndframe = new dfd.Series(data); - let df = ndframe.astype("int32"); - - assert.deepEqual(df.dtypes, ["int32"]); - assert.deepEqual(df.values, [20, 21, 23, 50]); - }); - it("set type of string column to float", function () { - let data = ["20.1", "21", "23.4", "50.78"]; - let ndframe = new dfd.Series(data); - let df = ndframe.astype("float32"); - - assert.deepEqual(df.dtypes, ["float32"]); - assert.deepEqual(df.values, [20.1, 21, 23.4, 50.78]); - }); - }); - - describe("iloc", function () { - it("indexing by list of index", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new dfd.Series(data); - - let expected_val = [2, "a", 3, 4, "b"]; - - assert.deepEqual(sf.iloc([1, 4, 2, 3, 5]).values, expected_val); - }); - it("indexing by slicing", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new dfd.Series(data); - - let expected_val = [2, 3, 4]; - - assert.deepEqual(sf.iloc(["1:4"]).values, expected_val); - }); - it("indexing by slicing format ':5' works", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new dfd.Series(data); - let expected_val = [1, 2, 3, 4, 'a']; - assert.deepEqual(sf.iloc([":5"]).values, expected_val); - }); - it("indexing by slicing format '2:` works", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new dfd.Series(data); - let expected_val = [3, 4, "a", "b", "c"]; - assert.deepEqual(sf.iloc(["2:"]).values, expected_val); - }); - }); - - describe("append", function () { - it("Add a new single value to the end of a Series", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new dfd.Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c", "d"]; - sf.append("d", "r1", { inplace: true }); - assert.deepEqual(sf.values, expected_val); - }); - it("Add a new array of values to the end of a Series", function () { - let data = [1, 2, 3, 4]; - let to_add = ["a", "b", "c"]; - let sf = new dfd.Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c"]; - sf.append(to_add, ["r1", "r2", "r3"], { inplace: true }); - assert.deepEqual(sf.values, expected_val); - }); - it("Add a Series to the end of another Series", function () { - let sf1 = new dfd.Series([1, 2, 3, 4]); - let sf2 = new dfd.Series(["a", "b", "c"]); - let expected_val = [1, 2, 3, 4, "a", "b", "c"]; - sf1.append(sf2, ["r1", "r2", "r3"], { inplace: true }); - assert.deepEqual(sf1.values, expected_val); - }); - it("Add a new single value to the end of a Series", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new dfd.Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c", "d"]; - sf = sf.append("d", "r1"); - assert.deepEqual(sf.values, expected_val); - }); - it("Add a new array of values to the end of a Series", function () { - let data = [1, 2, 3, 4]; - let to_add = ["a", "b", "c"]; - let sf = new dfd.Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c"]; - sf = sf.append(to_add, ["r1", "r2", "r3"]); - assert.deepEqual(sf.values, expected_val); - }); - }); - describe("or", function () { - it("Return logical OR of series and other series (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new dfd.Series(data1); - const sf2 = new dfd.Series(data2); - - const expected = [true, true, true, true, false]; - assert.deepEqual(sf.or(sf2).values, expected); - }); - - it("Return logical OR of series and other scalar", function () { - const data1 = [true, true, true, false, false]; - const sf = new dfd.Series(data1); - - const expected = [true, true, true, true, true]; - assert.deepEqual(sf.or(true).values, expected); - }); - - it("Return logical OR of series and other array (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new dfd.Series(data1); - - const expected = [true, true, true, true, false]; - assert.deepEqual(sf.or(data2).values, expected); - }); - it("Correct index is returned after operation", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new dfd.Series(data1, { index: ["one", "two", "three", "four", "five"] }); - - const expected = ["one", "two", "three", "four", "five"]; - assert.deepEqual(sf.and(data2).index, expected); - }); - }); - - describe("and", function () { - it("Return logical AND of series and other series (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new dfd.Series(data1); - const sf2 = new dfd.Series(data2); - - const expected = [true, false, true, false, false]; - assert.deepEqual(sf.and(sf2).values, expected); - }); - - it("Return logical AND of series and other scalar", function () { - const data1 = [true, true, true, false, false]; - const sf = new dfd.Series(data1); - - const expected = [true, true, true, false, false]; - assert.deepEqual(sf.and(true).values, expected); - }); - - it("Return logical AND of series and other array (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new dfd.Series(data1); - - const expected = [true, false, true, false, false]; - assert.deepEqual(sf.and(data2).values, expected); - }); - it("Correct index is returned after operation", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new dfd.Series(data1, { index: ["one", "two", "three", "four", "five"] }); - - const expected = ["one", "two", "three", "four", "five"]; - assert.deepEqual(sf.and(data2).index, expected); - }); - - it("Chaining works for logical AND of series and other array (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const data3 = [true, false, false, true, false]; - - const sf = new dfd.Series(data1); - const expected = [true, false, false, false, false]; - assert.deepEqual(sf.and(data2).and(data3).values, expected); - }); - - it("Chaining works for logical AND and OR combined", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const data3 = [true, false, false, true, false]; - - const sf = new dfd.Series(data1); - const expected = [true, false, true, true, false]; - assert.deepEqual(sf.and(data2).or(data3).values, expected); - }); - }); - -}); diff --git a/danfojs-browser/tests/core/utils.js b/danfojs-browser/tests/core/utils.js deleted file mode 100644 index decb84d2..00000000 --- a/danfojs-browser/tests/core/utils.js +++ /dev/null @@ -1,160 +0,0 @@ -/* eslint-disable no-undef */ - -describe("Utils Functions", function () { - it("removes an element from an array", function () { - let arr = [ 1, 2, 3, 4 ]; - assert.deepEqual(dfd.utils.removeElementFromArray(arr, 2), [ 1, 2, 4 ]); - }); - it("Checks if variable is a string", function () { - let arr = [ "1", "2" ]; - assert.isTrue(dfd.utils.isString(arr[0])); - }); - it("Checks if variable is a number", function () { - let arr = [ 1, 2, 3, 4 ]; - assert.isTrue(dfd.utils.isNumber(arr[0])); - }); - it("Checks if value is null", function () { - let val = null; - let val2 = 1; - assert.isTrue(dfd.utils.isNull(val)); - assert.isFalse(dfd.utils.isNull(val2)); - }); - - it("Checks if value is undefined", function () { - let arr; - assert.isTrue(dfd.utils.isUndefined(arr)); - }); - - it("Generate number betwee two set of values", function () { - - let start = 0; - let end = 5; - let data = [ 0, 1, 2, 3, 4, 5 ]; - assert.deepEqual(dfd.utils.range(start, end), data); - }); - - describe("inferDtype", function () { - it("Returns string type present in an 1D array", function () { - let data = [ 'Alice', 'Boy', 'Girl', "39" ]; - let result = [ 'string' ]; - assert.deepEqual(dfd.utils.inferDtype(data), result); - }); - it("Returns float type present in an 1D array", function () { - let data = [ 1.1, 2.1, 3.2, 4.4 ]; - let result = [ 'float32' ]; - assert.deepEqual(dfd.utils.inferDtype(data), result); - }); - it("Returns int type present in an 1D array", function () { - let data = [ 1, 2, 3, 45 ]; - let result = [ 'int32' ]; - assert.deepEqual(dfd.utils.inferDtype(data), result); - }); - it("Returns float when there's a mixture of int and float in a 1D array", function () { - let data = [ 1, 2.1, 3, 45 ]; - let result = [ 'float32' ]; - assert.deepEqual(dfd.utils.inferDtype(data), result); - }); - it("Returns float type when NaN is present in an 1D array", function () { - let data = [ 1, 2, 3, 45, NaN ]; - let result = [ 'float32' ]; - assert.deepEqual(dfd.utils.inferDtype(data), result); - }); - }); - - describe("__map_int_to_bool", function () { - it("map ints to bools in array of arrays", function () { - let data = [ [ 1, 0, 1 ], [ 1, 1, 0 ] ]; - assert.deepEqual(dfd.utils.mapIntegersToBooleans(data, 2), [ [ true, false, true ], [ true, true, false ] ]); - }); - it("map ints to bools in array", function () { - let data = [ 1, 0, 0, 1, 1 ]; - assert.deepEqual(dfd.utils.mapIntegersToBooleans(data, 1), [ true, false, false, true, true ]); - }); - }); - - describe("__round", function () { - it("round elements in array to 1 dp", function () { - let data = [ 10.01, 2.2, 3.11, 20.505, 20.22, 40.0909 ]; - assert.deepEqual(dfd.utils.round(data, 1, true), [ 10.0, 2.2, 3.1, 20.5, 20.2, 40.1 ]); - }); - it("round elements in array to 2 dp", function () { - let data = [ 10.019, 2.2099, 3.1145, 20.506, 20.22, 40.0909 ]; - assert.deepEqual(dfd.utils.round(data, 2, true), [ 10.02, 2.21, 3.11, 20.51, 20.22, 40.09 ]); - }); - }); - - describe("__replace_undefined_with_NaN", function () { - it("replace undefined in Series with NaN", function () { - let data = [ 10.01, 2.2, undefined, 20.505, 20.22, undefined ]; - assert.deepEqual(dfd.utils.replaceUndefinedWithNaN(data, true), [ 10.01, 2.2, NaN, 20.505, 20.22, NaN ]); - }); - it("replace undefined in DataFrame with NaN", function () { - let data = [ [ 10.01, 2.2, undefined, 20.505, 20.22, undefined ], - [ 10.01, undefined, undefined, 20.505, 20, undefined ] ]; - - let result = [ [ 10.01, 2.2, NaN, 20.505, 20.22, NaN ], - [ 10.01, NaN, NaN, 20.505, 20, NaN ] ]; - assert.deepEqual(dfd.utils.replaceUndefinedWithNaN(data, false), result); - }); - it("replace null in Series with NaN", function () { - let data = [ 10.01, 2.2, null, 20.505, 20.22, null ]; - assert.deepEqual(dfd.utils.replaceUndefinedWithNaN(data, true), [ 10.01, 2.2, NaN, 20.505, 20.22, NaN ]); - }); - it("replace null in DataFrame with NaN", function () { - let data = [ [ 10.01, 2.2, null, 20.505, 20.22, null ], - [ 10.01, null, null, 20.505, 20, null ] ]; - - let result = [ [ 10.01, 2.2, NaN, 20.505, 20.22, NaN ], - [ 10.01, NaN, NaN, 20.505, 20, NaN ] ]; - assert.deepEqual(dfd.utils.replaceUndefinedWithNaN(data, false), result); - }); - }); - - describe("__convert_2D_to_1D", function () { - it("convert 2D array of array to 1D of string values", function () { - let data = [ [ 10.01, 2.2, "a" ], [ 20.505, 20.22, "boy" ] ]; - assert.deepEqual(dfd.utils.convert2DArrayToSeriesArray(data), [ "10.01,2.2,a", "20.505,20.22,boy" ]); - }); - - }); - - // describe("_throw_wrong_params_error", function () { - // it("check if the right params are passed to a function", function () { - // let params_needed = ["replace", "with", "inplace"] - // let kwargs = { "replae": 2, "with": 12, "inplace": true } - // assert.equal(dfd.utils._throw_wrong_params_error(kwargs, params_needed), false) - // }) - // it("check if the right params are passed to a function 2", function () { - // let params_needed = ["replace", "with", "inplace"] - // let kwargs = { "replace": 2, "with": 12, "inplace": true } - // assert.equal(dfd.utils._throw_wrong_params_error(kwargs, params_needed), true) - // }) - - // }) - - describe("_get_row_and_col_values", function () { - it("retreive rows and labels from column object", function () { - let data = { "Alpha": [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; - let res = [ [ "A", 1, 20.3 ], [ "B", 2, 30.456 ], [ "C", 3, 40.90 ], [ "D", 4, 90.1 ] ]; - assert.deepEqual(dfd.utils.getRowAndColValues(data)[0], res); - assert.deepEqual(dfd.utils.getRowAndColValues(data)[1], [ "Alpha", "count", "sum" ]); - - }); - - - }); - - - describe("_get_duplicate", function(){ - it("obtain duplicate and their index", function(){ - - let data = [ 1, 2, 3, 4, 5, 3, 4, 6, 4, 5 ]; - let res = { '3': { count: 2, index: [ 2, 5 ] }, - '4': { count: 3, index: [ 3, 6, 8 ] }, - '5': { count: 2, index: [ 4, 9 ] } }; - - assert.deepEqual(dfd.utils.getDuplicate(data), res); - }); - }); - -}); diff --git a/danfojs-browser/tests/io/reader.js b/danfojs-browser/tests/io/reader.js deleted file mode 100644 index 9a0c484c..00000000 --- a/danfojs-browser/tests/io/reader.js +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint-disable no-undef */ - -describe("read_csv", async function () { - this.timeout(100000); // all tests in this suite get 10 seconds before timeout - it("reads a csv file from source over the internet", async function () { - const csvUrl = - "https://storage.googleapis.com/tfjs-examples/multivariate-linear-regression/data/boston-housing-train.csv"; - - const df = await dfd.read_csv(csvUrl); - const num_of_columns = df.columns.length; - assert.equal(num_of_columns, 13); - - }); -}); - -describe("read_json", async function () { - this.timeout(100000); // all tests in this suite get 10 seconds before timeout - it("reads a json file from source over the internet", async function () { - const jUrl = - "https://raw.githubusercontent.com/opensource9ja/danfojs/dev/danfojs-node/tests/samples/book.json"; - - const df = await dfd.read_json(jUrl); - assert.deepEqual(df.columns, [ - 'book_id', - 'title', - 'image_url', - 'authors' - ]); - assert.deepEqual(df.dtypes, [ - 'int32', 'string', - 'string', 'string' - ]); - - }); - -}); - -describe("read_excel", async function () { - this.timeout(100000); // all tests in this suite get 10 seconds before timeout - it("reads an excel file from source over the internet", async function () { - const remote_url = - "https://raw.githubusercontent.com/opensource9ja/danfojs/dev/danfojs-node/tests/samples/SampleData.xlsx"; - const df = await dfd.read_excel(remote_url); - assert.deepEqual(df.columns, [ - 'Year', - 'Stocks', - 'T.Bills', - 'T.Bonds' - ]); - assert.deepEqual(df.dtypes, [ - 'int32', 'float32', - 'float32', 'float32' - ]); - assert.deepEqual(df.shape, [ 82, 4 ]); - }); - -}); diff --git a/danfojs-browser/tests/preprocessing/encodings.js b/danfojs-browser/tests/preprocessing/encodings.js deleted file mode 100644 index fff0015f..00000000 --- a/danfojs-browser/tests/preprocessing/encodings.js +++ /dev/null @@ -1,95 +0,0 @@ -/* eslint-disable no-undef */ - -describe("Encodings", function () { - - describe("LabelEncoder", function () { - - it("test the label encoding on array", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let encode = new dfd.LabelEncoder(); - let fit_data = [ - 0, 1, 2, 0, - 1, 2, 2, 1 - ]; - assert.deepEqual(encode.fit(data).values, fit_data); - assert.deepEqual(encode.transform([ "dog", "man" ]).values, [ 0, 2 ]); - }); - it("test the label encoding on Series", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let series = new dfd.Series(data); - let encode = new dfd.LabelEncoder(); - let fit_data = [ - 0, 1, 2, 0, - 1, 2, 2, 1 - ]; - assert.deepEqual(encode.fit(series).values, fit_data); - assert.deepEqual(encode.transform([ "dog", "man" ]).values, [ 0, 2 ]); - }); - it("label encoding directly from a Series", function () { - let data = new dfd.Series([ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]); - let to_label_encode = new dfd.Series([ "dog", "man" ]); - let encode = new dfd.LabelEncoder(); - let fit_data = [ - 0, 1, 2, 0, - 1, 2, 2, 1 - ]; - assert.deepEqual(encode.fit(data).values, fit_data); - assert.deepEqual(encode.transform(to_label_encode).values, [ 0, 2 ]); - }); - // it("Label encoding on Series", function () { - // let data = ["dog", "cat", "man", "dog", "cat", "man", "man", "cat"] - // let series = new dfd.Series(data) - // let encode = new dfd.LabelEncoder() - // let fit_data = [ - // 0, 1, 2, 0, - // 1, 2, 2, 1 - // ] - // assert.deepEqual(encode.fit(series).values, fit_data) - // assert.deepEqual(encode.transform(["dog", "man"]).values, [0, 2]) - // }); - - }); - - describe("OneHotEncoder", function () { - - it("test onehotencoding on array", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let encode = new dfd.OneHotEncoder(); - let fit_data = [ - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 0, 0, 1 ], - [ 0, 1, 0 ] - ]; - let transform_data = [ [ 0, 0, 1 ], [ 0, 1, 0 ] ]; - - assert.deepEqual(encode.fit(data).values, fit_data); - assert.deepEqual(encode.transform([ "man", "cat" ]).values, transform_data); - }); - it("test onehotencoding on Series", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let series = new dfd.Series(data); - let encode = new dfd.OneHotEncoder(); - let fit_data = [ - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 0, 0, 1 ], - [ 0, 1, 0 ] - ]; - let transform_data = [ [ 0, 0, 1 ], [ 0, 1, 0 ] ]; - - assert.deepEqual(encode.fit(series).values, fit_data); - assert.deepEqual(encode.transform(new dfd.Series([ "man", "cat" ])).values, transform_data); - }); - }); - - -}); diff --git a/danfojs-browser/tests/preprocessing/scaler.js b/danfojs-browser/tests/preprocessing/scaler.js deleted file mode 100644 index 2cb4d7bb..00000000 --- a/danfojs-browser/tests/preprocessing/scaler.js +++ /dev/null @@ -1,85 +0,0 @@ -/* eslint-disable no-undef */ - - -describe("Preprocessing", function(){ - - describe("MinMaxscaler", function(){ - - it("Standardize values in a DataFrame", function(){ - let data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; - let scaler = new dfd.MinMaxScaler(); - let fit_data = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; - let transform_data = [ [ 1.5, 0. ] ]; - scaler.fit(new dfd.DataFrame(data)); - assert.deepEqual(scaler.transform(new dfd.DataFrame(data)).values, fit_data); - assert.deepEqual(scaler.transform([ [ 2, 2 ] ]).values, transform_data); - }); - it("Standardize values in a Series", function(){ - let data = [ -1, 2, -0.5, 60, 101, 18 ]; - let scaler = new dfd.MinMaxScaler(); - let result = [ 0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677 ]; - let transform_data = [ 0.029411764815449715, 0.029411764815449715 ]; - scaler.fit(new dfd.Series(data)); - assert.deepEqual(scaler.transform(new dfd.Series(data)).values, result); - assert.deepEqual(scaler.transform([ 2, 2 ]).values, transform_data); - }); - it("should be able to inverse the normalization of a Series", function() { - let data = [ -1, 2, -0.5, 60, 101, 18 ]; - let result = [ 0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677 ]; - let scaler = new dfd.MinMaxScaler(); - scaler.fit(new dfd.Series(data)); - assert.deepEqual(scaler.inverse_transform(new dfd.Series(result)).values, data); - }); - it("should be able to inverse the normalization of a DataFrame", function(){ - let data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; - let result = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; - let scaler = new dfd.MinMaxScaler(); - scaler.fit(new dfd.DataFrame(data)); - assert.deepEqual(scaler.inverse_transform(new dfd.DataFrame(result)).values, data); - }); - }); - - describe("StandardScaler", function(){ - - it("basic test", function(){ - let data = [ [ 0, 0 ], [ 0, 0 ], [ 1, 1 ], [ 1, 1 ] ]; - - let scaler = new dfd.StandardScaler(); - let fit_data = [ [ -1, -1 ], [ -1, -1 ], [ 1, 1 ], [ 1, 1 ] ]; - let transform_data = [ [ 3, 3 ] ]; - - assert.deepEqual(scaler.fit(new dfd.DataFrame(data)).round().values, fit_data); - assert.deepEqual(scaler.transform([ [ 2, 2 ] ]).round().values, transform_data); - }); - it("should be able to inverse the normalization of a Series", function() { - let data = [ -1, 2, -0.5, 60, 101, 18 ]; - let result = [ 0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677 ]; - let scaler = new dfd.MinMaxScaler(); - scaler.fit(new dfd.Series(data)); - assert.deepEqual(scaler.inverse_transform(new dfd.Series(result)).values, data); - }); - it("should be able to inverse the normalization of a DataFrame", function(){ - let data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; - let result = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; - let scaler = new dfd.MinMaxScaler(); - scaler.fit(new dfd.DataFrame(data)); - assert.deepEqual(scaler.inverse_transform(new dfd.DataFrame(result)).values, data); - }); - }); - - - // describe("RobustScaler", function(){ - // it("basic test", function(){ - - // let data = [[3,1], [7,3], [8,4], [5,6], [12,5], [14,12], [21,23], [15,15], [18,2], [14,15]] - // // let data2 = [[4,100,900],[5,110,800],[21,220,890],[20,300,500]] - // let data2 = [0, 4, 4, 4, 7, 10, 11, 12, 14, 16, 17, 25] - - - // let scaler = new RobustScaler() - - // // console.log(scaler.quantile(data2,true)) - - // }); - // }); -}); diff --git a/danfojs-browser/types/core/concat.d.ts b/danfojs-browser/types/core/concat.d.ts deleted file mode 100644 index 269f31e2..00000000 --- a/danfojs-browser/types/core/concat.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class Concat { - constructor(kwargs?: any); -} -export function concat(kwargs?: any): DataFrame; -import { DataFrame } from "./frame"; diff --git a/danfojs-browser/types/core/date_range.d.ts b/danfojs-browser/types/core/date_range.d.ts deleted file mode 100644 index 58f7060a..00000000 --- a/danfojs-browser/types/core/date_range.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Generate date range between a specified set of date - * @param {kwargs} kwargs { - * start : string - * end : string - * period: int - * freq : string - * } - * @returns Array - */ -export class date_range { - constructor(kwargs?: any); - offset: number; - start?: any; - end?: any; - period?: any; - freq?: any; - freq_list: string[]; - range(start?: any, end?: any, period?: any, offset?: any): any; - freq_type(date?: any, ftype?: any): any; - offset_count(d_array?: any, offset?: any): any[]; - set_dateProps(date?: any, ftype?: any, val?: any): Date; - toLocalString(d_array?: any): any; - month_end(start_date?: any, end_date?: any): any; - month_range(range?: any): any; - day_end(start_date?: any, end_date?: any): number; -} diff --git a/danfojs-browser/types/core/datetime.d.ts b/danfojs-browser/types/core/datetime.d.ts deleted file mode 100644 index 77c6d23e..00000000 --- a/danfojs-browser/types/core/datetime.d.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -import { ArrayType1D, DateTime } from "../shared/types"; -/** - * Format and handle all datetime operations on Series or Array of date strings - * @param data Series or Array of date strings - */ -export default class TimeSeries implements DateTime { - private $dateObjectArray; - constructor(data: Series | ArrayType1D); - /** - * Processed the data values into internal structure for easy access - * @param dateArray An array of date strings - */ - private processData; - /** - * Returns the month, in local time. - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2019-03-01", - * "2019-04-01", - * ] - * const df = new Dataframe(data) - * const dfNew = df.dt.month() - * console.log(dfNew.values) - * // [1, 2, 3, 4] - * ``` - */ - month(): Series; - /** - * Returns the day of the week, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2019-03-01", - * "2019-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfWeek = df.dt.day() - * console.log(day.values) - * ``` - */ - day(): Series; - /** - * Returns the year, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const year = df.dt.year() - * console.log(year.values) - * // [2019, 2019, 2021, 2020] - * ``` - */ - year(): Series; - /** - * Returns the name of the month, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const monthName = df.dt.month_name().values - * console.log(monthName) - * // ["January", "February", "March", "April"] - * ``` - */ - month_name(): Series; - /** - * Returns the name of the day, of the week, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfWeekName = df.dt.weekdays().values - * console.log(dayOfWeekName) - * ``` - */ - weekdays(): Series; - /** - * Returns the day of the month, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfMonth = df.dt.monthday().values - * console.log(dayOfMonth) - * // [1, 5, 2, 1] - * ``` - */ - monthday(): Series; - /** - * Returns the hour of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const hour = df.dt.hour().values - * console.log(hour) - * // [0, 0, 0, 0] - * ``` - */ - hours(): Series; - /** - * Returns the second of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const second = df.dt.second().values - * console.log(second) - * ``` - */ - seconds(): Series; - /** - * Returns the minute of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const minute = df.dt.minute().values - * console.log(minute) - * ``` - */ - minutes(): Series; -} -export declare const toDateTime: (data: Series | ArrayType1D) => TimeSeries; diff --git a/danfojs-browser/types/core/frame.d.ts b/danfojs-browser/types/core/frame.d.ts deleted file mode 100644 index d115dbd4..00000000 --- a/danfojs-browser/types/core/frame.d.ts +++ /dev/null @@ -1,555 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { ArrayType1D, ArrayType2D, DataFrameInterface, BaseDataOptionType } from "../shared/types"; -import NDframe from "./generic"; -import Series from './series'; -import { GroupBy } from "./groupby"; - - -/** - * A 2D frame object that stores data in structured tabular format - * @param {data} data, JSON, Array, 2D Tensor - * @param {kwargs} Object {columns: Array of column names, defaults to ordered numbers when not specified - * dtypes: strings of data types, automatically inferred when not specified - * index: row index for subseting array, defaults to ordered numbers when not specified} - * - * @returns DataFrame - */ -export class DataFrame extends NDframe implements DataFrameInterface { - [key: string]: any; - constructor(data: any, options?: BaseDataOptionType); - - /** - * Drop columns or rows with missing values. Missing values are NaN, undefined or null. - * @param options.columns Array of column names to drop - * @param options.index Array of index to drop - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop(options?: { - columns?: string | Array; - index?: Array; - inplace?: boolean; - }): DataFrame | void; - /** - * Access a group of rows and columns by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc({ rows, columns }: { - rows?: Array | Series; - columns?: Array; - }): DataFrame; - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc({ rows, columns }: { - rows?: Array | Series; - columns?: Array; - }): DataFrame; - /** - * Prints the first n values in a dataframe - * @param {rows} rows --> int - * @returns DataFrame - */ - head(rows?: number): DataFrame; - /** - * Prints the last n values in a dataframe - * @param {rows} rows --> int - * @returns DataFrame - */ - tail(rows?: number): DataFrame; - /** - * Gets n number of random rows in a dataframe. Sample is reproducible if seed is provided. - * @param num The number of rows to return. Default to 5. - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - sample(num?: number, options?: { - seed?: number; - }): Promise; - - /** - * Return Addition of DataFrame and other, element-wise (binary operator add). - * @param other DataFrame, Series, Array or Scalar number to add - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return substraction between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to substract from DataFrame - * @param options.axis 0 or 1. If 0, compute the subtraction column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return multiplciation between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to multiply with. - * @param options.axis 0 or 1. If 0, compute the multiplication column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return division of DataFrame with other. - * @param other DataFrame, Series, Array or Scalar number to divide with. - * @param options.axis 0 or 1. If 0, compute the division column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return DataFrame raised to the power of other. - * @param other DataFrame, Series, Array or Scalar number to to raise to. - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return modulus between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to modulus with. - * @param options.axis 0 or 1. If 0, compute the mod column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return mean of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mean column-wise, if 1, row-wise. Defaults to 1 - */ - mean(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return median of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the median column-wise, if 1, row-wise. Defaults to 1 - */ - median(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return mode of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mode column-wise, if 1, row-wise. Defaults to 1 - * @param options.keep If there are more than one modes, returns the mode at position [keep]. Defaults to 0 - */ - mode(options?: { - axis?: 0 | 1; - keep?: number; - }): Series; - /** - * Return minimum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the minimum value column-wise, if 1, row-wise. Defaults to 1 - */ - min(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return maximum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the maximum column-wise, if 1, row-wise. Defaults to 1 - */ - max(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return standard deviation of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the standard deviation column-wise, if 1, row-wise. Defaults to 1 - */ - std(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return variance of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the variance column-wise, if 1, add row-wise. Defaults to 1 - */ - var(options?: { - axis?: 0 | 1; - }): Series; - /** - * Get Less than of dataframe and other, element-wise (binary operator lt). - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - lt(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "greater than" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - gt(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "equals to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - eq(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "not equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ne(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "less than or equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - le(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "greater than or equal to" between dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ge(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Return number of non-null elements in a Series - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - count(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return the sum of values across an axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - sum(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return the absolute value of elements in a DataFrame. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Rounds all element in the DataFrame to specified number of decimal places. - * @param dp Number of decimal places to round to. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp?: number, options?: { - inplace: boolean; - }): DataFrame | void; - /** - * Returns cumulative product accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumprod(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Returns cumulative sum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumsum(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Returns cumulative minimum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummin(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Returns cumulative maximum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummax(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - - /** - * Generate descriptive statistics for all numeric columns - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - * @returns {Series} - */ - describe(): DataFrame; - /** - * Drops all rows or columns with missing values (NaN) - * @param axis 0 or 1. If 0, drop columns with NaNs, if 1, drop rows with NaNs - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(axis?: 0 | 1, options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Adds a new column to the DataFrame. If column exists, then the column values is replaced. - * @param column The name of the column to add or replace. - * @param values An array of values to be inserted into the DataFrame. Must be the same length as the columns - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - addColumn(options: { - column: string, - values: Series | ArrayType1D, - inplace?: boolean; - }): DataFrame | void; - /** - * Makes a new copy of a DataFrame - */ - copy(): DataFrame; - /** - * Return a boolean same-sized object indicating where elements are empty (NaN, undefined, null). - * NaN, undefined and null values gets mapped to true, and everything else gets mapped to false. - */ - isna(): DataFrame; - /** - * Replace all empty elements with a specified value. Replace params expect columns array to map to values array. - * @param columns The list of column names to be replaced - * @param options.values The list of values to use for replacement. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(values: number | string | boolean | ArrayType1D, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - - /** - * Sorts a Dataframe by a specified column values - * @param options.column Column name to sort by - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options?: { - by: string, - ascending?: boolean; - inplace?: boolean; - }): DataFrame | void; - /** - * Sets the index of the DataFrame to the specified index. - * @param options.index An array of index values to set - * @param options.column A column name to set the index to - * @param options.drop Whether to drop the column whose index was set. Defaults to false - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options: { - index?: Array; - column?: string; - drop?: boolean; - inplace?: boolean; - }): DataFrame | void; - /** - * Resets the index of the DataFrame to the default index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - reset_index(options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Apply a function along an axis of the DataFrame. To apply a function element-wise, use `applyMap`. - * Objects passed to the function are Series values whose - * index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1) - * @param callable Function to apply to each column or row - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - */ - apply(callable: any, options?: { - axis?: 0 | 1; - }): DataFrame | Series; - /** - * Apply a function to a Dataframe values element-wise. - * @param callable Function to apply to each column or row - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply_map(callable: any, options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Returns the specified column data as a Series object. - * @param column The name of the column to return - */ - column(column: string): Series; - /** - * Return a subset of the DataFrame’s columns based on the column dtypes. - * @param include An array of dtypes or strings to be included. - */ - select_dtypes(include: Array): DataFrame; - /** - * Returns the transposes the DataFrame. - **/ - transpose(options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Returns the Transpose of the DataFrame. Similar to `transpose`, but does not change the original DataFrame. - **/ - get T(): DataFrame; - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.columns An array of column names you want to replace. If not provided replace accross all columns. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace(oldValue: number | string | boolean, newValue: number | string | boolean, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - /** - * Cast the values of a column to specified data type - * @param column The name of the column to cast - * @param dtype Data type to cast to. One of [float32, int32, string, boolean] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(options?: { - column: string, - dtype: "float32" | "int32" | "string" | "boolean", - inplace?: boolean; - }): DataFrame | void; - /** - * Return the number of unique elements in a across the specified axis. - * To get the values use `.unique()` instead. - * @param axis The axis to count unique elements across. Defaults to 1 - */ - nunique(axis?: 0 | 1): Series; - /** - * Renames a column or index. - * @param mapper An object that maps each column or index in the DataFrame to a new value - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.axis The axis to perform the operation on. Defaults to 1 - */ - rename(options?: { - mapper: any, - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Sorts the Dataframe by the index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - */ - sort_index(options?: { - inplace?: boolean; - ascending?: boolean; - }): DataFrame | void; - /** - * Add new rows to the end of the DataFrame. - * @param newValues Array, Series or DataFrame to append to the DataFrame - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append(newValues: ArrayType1D | ArrayType2D | Series | DataFrame, index: Array | number | string, options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Queries the DataFrame for rows that meet the boolean criteria. - * @param condition An array of boolean mask, one for each row in the DataFrame. Rows where the value are true will be returned. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - **/ - query(options: { - column?: string, - is?: string, - to?: any, - condition?: Series | Array, - inplace?: boolean; - }): DataFrame | void; - /** - * Returns the data types for each column as a Series. - */ - get ctypes(): Series; - /** - * One-hot encode specified columns in the DataFrame. If columns are not specified, all columns of dtype string will be encoded. - * @param options Options for the operation. The following options are available: - * - `columns`: A single column name or an array of column names to encode. Defaults to all columns of dtype string. - * - `prefix`: Prefix to add to the column names. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * - `inplace`: Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @returns A DataFrame with the one-hot encoded columns. - * @example - * df.getDummies({ columns: ['a', 'b'] }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-', inplace: true }) - * df.getDummies({ columns: ['a', 'b'], prefix: ['col1', 'col2'], prefixSeparator: '-', inplace: true }) - */ - get_dummies(options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string | Array; - inplace?: boolean; - }): DataFrame | void; - - groupby(column: Array): GroupBy; -} \ No newline at end of file diff --git a/danfojs-browser/types/core/generic.d.ts b/danfojs-browser/types/core/generic.d.ts deleted file mode 100644 index 26a40cf5..00000000 --- a/danfojs-browser/types/core/generic.d.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Configs from "../shared/config"; -import { - NDframeInterface, - NdframeInputDataType, - AxisType, - ArrayType1D, - ArrayType2D, - CsvOutputOptionsBrowser -} from '../shared/types'; -/** - * N-Dimension data structure. Stores multi-dimensional - * data in a size-mutable, labeled data structure. Analogous to the Python Pandas DataFrame. - * - * @param Object - * - * data: 1D or 2D Array, JSON, Tensor, Block of data. - * - * index: Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * - * columns: Array of column names. If not specified, column names are auto generated. - * - * dtypes: Array of data types for each the column. If not specified, dtypes inferred. - * - * config: General configuration object for NDframe - * - * @returns NDframe - */ -export default class NDframe implements NDframeInterface { - $isSeries: boolean; - protected $data: any; - protected $dataIncolumnFormat: ArrayType1D | ArrayType2D; - protected $index: Array; - protected $columns: string[]; - protected $dtypes: Array; - protected $config: Configs; - constructor({ data, index, columns, dtypes, config, isSeries }: NdframeInputDataType); - /** - * Internal function to load array of data into NDFrame - * @param data The array of data to load into NDFrame - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - private loadArrayIntoNdframe; - /** - * Internal function to format and load a Javascript object or object of arrays into NDFrame. - * @param data Object or object of arrays. - * @param type The type of the object. There are two recognized types: - * - * - type 1 object are in JSON format `[{a: 1, b: 2}, {a: 30, b: 20}]`. - * - * - type 2 object are of the form `{a: [1,2,3,4], b: [30,20, 30, 20}]}` - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - private loadObjectIntoNdframe; - /** - * Converts and returns the data in the NDframe as a Tensorflow.js Tensor. - */ - get tensor(): import("@tensorflow/tfjs-node").Tensor1D | import("@tensorflow/tfjs-node").Tensor2D; - /** - * Returns the dtypes of the columns - */ - get dtypes(): Array; - /** - * Internal function to set the Dtypes of the NDFrame from an array. This function - * performs the necessary checks. - */ - $setDtypes(dtypes: Array | undefined): void; - /** - * Returns the dimension of the data. Series have a dimension of 1, - * while DataFrames have a dimension of 2. - */ - get ndim(): number; - /** - * Returns the axis labels of the NDFrame. - */ - get axis(): AxisType; - /** - * Returns the configuration object of the NDFrame. - */ - get config(): Configs; - /** - * Internal function to set the configuration of the ndframe - */ - $setConfig(config: Configs): void; - /** - * Returns the indices of the NDFrame - */ - get index(): Array; - /** - * Internal function to set the index of the NDFrame with the specified - * array of indices. Performs all necessary checks to ensure that the - * index is valid. - */ - $setIndex(index: Array | undefined): void; - /** - * Internal function to reset the index of the NDFrame using a range of indices. - */ - $resetIndex(): void; - /** - * Returns the column names of the NDFrame - */ - get columns(): string[]; - /** - * Internal function to set the column names for the NDFrame. This function - * performs a check to ensure that the column names are unique, and same length as the - * number of columns in the data. - */ - $setColumnNames(columns?: string[]): void; - /** - * Returns the shape of the NDFrame. Shape is determined by [row lenght, column length] - */ - get shape(): Array; - /** - * Returns the underlying data in Array format. - */ - get values(): ArrayType1D | ArrayType2D; - /** - * Updates the internal $data property to the specified value - * @param values An array of values to set - * @param checkLength Whether to check the length of the new values and the existing row length - * @param checkColumnLength Whether to check the length of the new values and the existing column length - * */ - $setValues(values: ArrayType1D | ArrayType2D, checkLength?: boolean, checkColumnLength?: boolean): void; - /** - * Returns the size of the NDFrame object - * - */ - get size(): number; - /** - * Converts a DataFrame or Series to CSV. - * @param options Configuration object. Supports the following options: - * - `fileName`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - */ - to_csv(options?: CsvOutputOptionsBrowser): string | void; - /** - * Converts a DataFrame or Series to JSON. - * @param options Configuration object. Supported options: - * - `fileName`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - */ - to_json(options?: { - format?: "row" | "column"; - fileName?: string; - }): object | void; - /** - * Converts a DataFrame or Series to Excel Sheet. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `fileName`: The fileName to be written to. Defaults to `'./output.xlsx'`. - */ - to_excel(options?: { - fileName?: string; - sheetName?: string; - }): void; - /** - * Pretty prints a DataFrame or Series to the console - */ - print(): void; -} diff --git a/danfojs-browser/types/core/get_dummies.d.ts b/danfojs-browser/types/core/get_dummies.d.ts deleted file mode 100644 index b4daef13..00000000 --- a/danfojs-browser/types/core/get_dummies.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { DataFrame } from "./frame"; -import Series from "./series"; -/** - * Generate one-hot encoding for categorical columns in an Array, Series or Dataframe. - * @param data Series or Dataframe - * @param columns Columns to encode - * @param prefix Prefix for the new columns - * @param prefixSeparator Separator for the prefix and the column name - * @returns Encoded Dataframe - * @example - * import { DataFrame, DummyEncoder }from 'danfojs'; - * const df = new DataFrame([[1,2,3], [4,5,6]], { columns: ['a', 'b', 'c'] }); - * const df2 = new DummyEncoder({data: df, columns: ['a', 'b'], prefix: 'enc', prefixSeparator: '#'}).encode(); - * df2.print(); - */ -declare function dummyEncode(data: Series | DataFrame, options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string | Array; -}): DataFrame; -export default dummyEncode; diff --git a/danfojs-browser/types/core/groupby.d.ts b/danfojs-browser/types/core/groupby.d.ts deleted file mode 100644 index c8231934..00000000 --- a/danfojs-browser/types/core/groupby.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The class performs all groupby operation on a dataframe - * involveing all aggregate funciton - * @param {col_dict} col_dict Object of unique keys in the group by column - * @param {key_col} key_col Array contains the column names - * @param {data} Array the dataframe data - * @param {column_name} Array of all column name in the dataframe. - */ -export class GroupBy { - constructor(col_dict?: any, key_col?: any, data?: any, column_name?: any); - key_col?: any; - col_dict?: any; - data?: any; - column_name?: any; - data_tensors: {}; - /** - * Group the dataframe by the column by - * creating an object to store the grouping - * @returns Groupby data structure - */ - group(): GroupBy; - /** - * obtain the column for each group - * @param {col_name} col_name [Array]--> array of column names - * @return Groupby data structure - */ - col(col_names?: any): GroupBy; - group_col_name?: any[]; - group_col: {}; - /** - * Basic root of all column arithemetic in groups - * @param {operation} operatioin String - */ - arithemetic(operation?: any): {}; - count(): DataFrame; - sum(): DataFrame; - std(): DataFrame; - var(): DataFrame; - mean(): DataFrame; - cumsum(): DataFrame; - cummax(): DataFrame; - cumprod(): DataFrame; - cummin(): DataFrame; - max(): DataFrame; - min(): DataFrame; - /** - * returns dataframe of a group - * @param {*} key [Array] - */ - get_groups(key?: any): any; - /** - * Map every column to an operaton - * @param {kwargs} kwargs {column name: math operation} - * @example .agg({"A": "mean","B": "sum","C":"count"}) - */ - agg(kwargs?: any): DataFrame; - to_DataFrame(key_col?: any, col?: any, data?: any, ops?: any): DataFrame; -} -import { DataFrame } from "./frame"; diff --git a/danfojs-browser/types/core/indexing.d.ts b/danfojs-browser/types/core/indexing.d.ts deleted file mode 100644 index c89625e7..00000000 --- a/danfojs-browser/types/core/indexing.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -import { DataFrame } from "./frame"; -import { NDframeInterface } from "../shared/types"; -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export declare function _iloc({ ndFrame, rows, columns }: { - ndFrame: NDframeInterface; - rows?: Array | Series; - columns?: Array; -}): Series | DataFrame; -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export declare function _loc({ ndFrame, rows, columns }: { - ndFrame: NDframeInterface; - rows?: Array | Series; - columns?: Array; -}): Series | DataFrame | void; diff --git a/danfojs-browser/types/core/math.ops.d.ts b/danfojs-browser/types/core/math.ops.d.ts deleted file mode 100644 index dff9a543..00000000 --- a/danfojs-browser/types/core/math.ops.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -/** - * Generic function for performing add, sub, pow, mul and mod operation on a series - * @param object - * - * ndframe ==> The current Series - * - * other ==> The Series or number to perform math operation with - * - * operation ==> The type of operation to perform -*/ -export declare function _genericMathOp({ ndFrame, other, operation }: { - ndFrame: Series; - other: Series | number | Array; - operation: string; -}): number[] | undefined; diff --git a/danfojs-browser/types/core/merge.d.ts b/danfojs-browser/types/core/merge.d.ts deleted file mode 100644 index 8162a6c9..00000000 --- a/danfojs-browser/types/core/merge.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -export class Merge { - constructor(kwargs?: any); - how?: any; - left: DataFrame; - right: DataFrame; - on?: any[]; - left_col_index?: any[]; - right_col_index?: any[]; - left_key_dict: {}; - right_key_dict: {}; - __create_columns(): void; - outer(): any[]; - inner(): any[]; - left_merge(): any[]; - right_merge(): any[]; - basic(keys?: any): any[]; -} -export function merge(kwargs?: any): DataFrame; -import { DataFrame } from "./frame"; diff --git a/danfojs-browser/types/core/series.d.ts b/danfojs-browser/types/core/series.d.ts deleted file mode 100644 index 440360df..00000000 --- a/danfojs-browser/types/core/series.d.ts +++ /dev/null @@ -1,462 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { ArrayType1D, BaseDataOptionType, SeriesInterface } from "../shared/types"; -import NDframe from "./generic"; -import Str from './strings'; -import Dt from './datetime'; -import { DataFrame } from "./frame"; -/** - * One-dimensional ndarray with axis labels. - * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. - * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. - * @param data 2D Array, JSON, Tensor, Block of data. - * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * @param options.columns Array of column names. If not specified, column names are auto generated. - * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. - * @param options.config General configuration object for extending or setting NDframe behavior. - */ -export default class Series extends NDframe implements SeriesInterface { - constructor(data?: any, options?: BaseDataOptionType); - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc(rows: Array): Series; - /** - * Access a group of rows by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc(rows: Array): Series; - /** - * Returns the first n values in a Series - * @param rows The number of rows to return - */ - head(rows?: number): Series; - /** - * Returns the last n values in a Series - * @param rows The number of rows to return - */ - tail(rows?: number): Series; - /** - * Returns specified number of random rows in a Series - * @param num The number of rows to return - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - sample(num?: number, options?: { - seed?: number; - }): Promise; - /** - * Return Addition of series and other, element-wise (binary operator add). - * Equivalent to series + other - * @param other Series, Array of same length or scalar number to add - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other: Series | Array | number, options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns the subtraction between a series and other, element-wise (binary operator subtraction). - * Equivalent to series - other - * @param other Number to subtract - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return Multiplication of series and other, element-wise (binary operator mul). - * Equivalent to series * other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return division of series and other, element-wise (binary operator div). - * Equivalent to series / other - * @param other Series or number to divide with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return Exponential power of series and other, element-wise (binary operator pow). - * Equivalent to series ** other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return Modulo of series and other, element-wise (binary operator mod). - * Equivalent to series % other - * @param other Number to modulo with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Checks if the array value passed has a compatible dtype, removes NaN values, and if - * boolean values are present, converts them to integer values. - * */ - private $checkAndCleanValues; - /** - * Returns the mean of elements in Series - */ - mean(): number; - /** - * Returns the median of elements in Series - */ - median(): number; - /** - * Returns the modal value of elements in Series - */ - mode(): any; - /** - * Returns the minimum value in a Series - */ - min(): number; - /** - * Returns the maximum value in a Series - * @returns {Number} - */ - max(): number; - /** - * Return the sum of the values in a series. - */ - sum(): number; - /** - * Return number of non-null elements in a Series - */ - count(): number; - /** - * Return maximum of series and other. - * @param other Series or number to check against - */ - maximum(other: Series | number | Array): Series; - /** - * Return minimum of series and other. - * @param other Series, Numbers to check against - */ - minimum(other: Series | number | Array): Series; - /** - * Round each value in a Series to the specified number of decimals. - * @param dp Number of Decimal places to round to - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp?: number, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return sample standard deviation of elements in Series - */ - std(): number; - /** - * Return unbiased variance of elements in a Series. - */ - var(): number; - /** - * Return a boolean same-sized object indicating where elements are NaN. - * NaN and undefined values gets mapped to true, and everything else gets mapped to false. - */ - isna(): Series; - /** - * Replace all NaN with a specified value - * @param value The value to replace NaN with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(options?: { - value: number | string | boolean, - inplace?: boolean; - }): Series | void; - /** - * Sort a Series in ascending or descending order by some criterion. - * @param options Method options - * @param ascending Whether to return sorted values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options?: { - ascending?: boolean, - inplace?: boolean; - }): Series | void; - /** - * Makes a deep copy of a Series - */ - copy(): Series; - /** - * Generate descriptive statistics. - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - */ - describe(): Series; - /** - * Returns Series with the index reset. - * This is useful when index is meaningless and needs to be reset to the default before another operation. - */ - reset_index(options?: { - inplace?: boolean; - }): Series | void; - /** - * Set the Series index (row labels) using an array of the same length. - * @param index Array of new index values, - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options?: { - index: Array, - inplace?: boolean; - }): Series | void; - /** - * map all the element in a column to a variable or function - * @param callable callable can either be a funtion or an object - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - map(callable: any, options?: { - inplace?: boolean; - }): Series | void; - /** - * Applies a function to each element of a Series - * @param callable Function to apply to each element of the series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply(callable: any, options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns a Series with only the unique value(s) in the original Series - */ - unique(): Series; - /** - * Return the number of unique elements in a Series - */ - nunique(): number; - /** - * Returns unique values and their counts in a Series - */ - value_counts(): Series; - /** - * Returns the absolute values in Series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns the cumulative sum over a Series - */ - cumsum(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns cumulative minimum over a Series - */ - cummin(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns cumulative maximum over a Series - */ - cummax(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns cumulative product over a Series - */ - cumprod(options?: { - inplace?: boolean; - }): Series | void; - /** - * perform cumulative operation on series data - */ - private cumOps; - /** - * Returns less than of series and other. Supports element wise operations - * @param other Series or number to compare against - */ - lt(other: Series | number): Series; - /** - * Returns Greater than of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - gt(other: Series | number | Array): Series; - /** - * Returns Less than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - le(other: Series | number | Array): Series; - /** - * Returns Greater than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ge(other: Series | number | Array): Series; - /** - * Returns Not Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ne(other: Series | number | Array): Series; - /** - * Returns Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - eq(other: Series | number | Array): Series; - /** - * Perform boolean operations on bool values - * @param other Other Series or number to compare with - * @param bOps Name of operation to perform [ne, ge, le, gt, lt, eq] - */ - private boolOps; - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace(options?: { - oldValue: string | number | boolean, - newValue: string | number | boolean, - inplace?: boolean; - }): Series | void; - /** - * Drops all missing values (NaN) from a Series. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(options?: { - inplace?: boolean; - }): Series | undefined; - /** - * Return the integer indices that would sort the Series. - * @param ascending boolean true: will sort the Series in ascending order, false: will sort in descending order - */ - argsort(ascending?: boolean): Series; - /** - * Return int position of the largest value in the Series. - */ - argmax(): number; - /** - * Return int position of the smallest value in the Series. - */ - argmin(): number; - /** - * Remove duplicate values from a Series - * @param keep "first" | "last", which dupliate value to keep. Defaults to "first". - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop_duplicates(options?: { - keep?: "first" | "last"; - inplace?: boolean; - }): Series | void; - /** - * Cast Series to specified data type - * @param dtype Data type to cast to. One of [float32, int32, string, boolean, undefined] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(dtype: "float32" | "int32" | "string" | "boolean" | "undefined", options?: { - inplace?: boolean; - }): Series | void; - /** - * Add a new value or values to the end of a Series - * @param newValues Single value | Array | Series to append to the Series - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append(newValue: string | number | boolean | Series | ArrayType1D, index: Array | number | string, options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns dtype of Series - */ - get dtype(): string; - /** - * Exposes numerous string methods to manipulate Series of type string - */ - get str(): Str; - /** - * Returns time class that exposes different date time method - */ - get dt(): Dt; - /** - * Prints Series to console as a grid of row and columns. - */ - toString(): string; - /** - * Returns the logical AND between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - and(other: any): Series; - /** - * Returns the logical OR between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - or(other: any): Series; - /** - * One-hot encode values in the Series. - * @param options Options for the operation. The following options are available: - * - `prefix`: Prefix to add to the new column. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * @returns A DataFrame with the one-hot encoded columns. - * @example - * sf.get_dummies() - * sf.get_dummies({prefix: 'cat' }) - * sf.get_dummies({ prefix: 'cat', prefixSeparator: '-' }) - */ - get_dummies(options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string; - }): DataFrame; -} diff --git a/danfojs-browser/types/core/strings.d.ts b/danfojs-browser/types/core/strings.d.ts deleted file mode 100644 index 24b31577..00000000 --- a/danfojs-browser/types/core/strings.d.ts +++ /dev/null @@ -1,341 +0,0 @@ -import Series from "./series"; -/** - * Exposes numerous String methods. All methods are applied Element-wise - */ -export default class Str { - private series; - private values; - constructor(series: Series); - /** - * Converts all characters to lowercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toLowerCase() - * console.log(newSf.values) - * // ["good", "bad", "crazy"] - * ``` - */ - toLowerCase(options?: { - inplace: boolean; - }): Series | void; - /** - * Converts all characters to uppercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toUpperCase() - * console.log(newSf.values) - * // ["GOOD", "BAD", "CRAZY"] - * ``` - */ - toUpperCase(options?: { - inplace: boolean; - }): Series | void; - /** - * Capitalize first string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.capitalize() - * console.log(newSf.values) - * // ["Good", "Bad", "Crazy"] - * ``` - */ - capitalize(options?: { - inplace: boolean; - }): Series | void; - /** - * Returns the character at the specified index (position) - * @param index position of character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.charAt(1) - * console.log(newSf.values) - * // ["o", "a", "r"] - * ``` - */ - charAt(index?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Joins specified `other` with values in the Series. - * @param other string|values to concatenate with. - * @param position where to concat the string from. O concats from the start, 1 concats from the end. Defaults to 1. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.concat("_new") - * console.log(newSf.values) - * // ["Good_new", "bad_new", "crazy_new" - * ``` - */ - concat(other: Array | string, position?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Checks whether a string begins with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.startsWith("G") - * console.log(newSf.values) - * // [true, false, false] - * ``` - */ - startsWith(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Checks whether a string ends with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.endsWith("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - endsWith(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Checks whether a string contains the specified string/characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.includes("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - includes(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Returns the position of the first occurrence of a specified value in a string. - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.indexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - indexOf(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Returns the position of the last found occurrence of a specified value in a string - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.lastIndexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - lastIndexOf(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced - * @param searchValue String | Character value to replace - * @param replaceValue String | Character string to replace with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace("d", 7) - * console.log(newSf.values) - * // ["Goo7", "o77", "crazy"] - * ``` - */ - replace(searchValue?: string, replaceValue?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Returns a new string with a specified number of copies of an existing string - * @param num Number of times to repeat - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace(2) - * console.log(newSf.values) - * // ["GoodGood", "oddodd", "crazycrazy"] - * ``` - */ - repeat(num?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Searches a string for a specified value, or regular expression, and returns the position of the match - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.search("d") - * console.log(newSf.values) - * ``` - */ - search(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Extracts a part of a string and returns a new string - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.slice(0,1) - * console.log(newSf.values) - * // ["G", "o", "c"] - * ``` - */ - slice(startIndex?: number, endIndex?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Splits a string into an values of substrings - * @param splitVal string or character to split at - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.split(d) - * console.log(newSf.values) - * ``` - */ - split(splitVal?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Extracts the characters from a string, beginning at a specified start position, and through the specified number of character - * @param startIndex index position of start character - * @param num number of characters to return - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substr(d) - * ``` - */ - substr(startIndex?: number, num?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Extracts the characters from a string, between two specified indices - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substring(d) - * ``` - */ - substring(startIndex?: number, endIndex?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Removes whitespace from both ends of a string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series([" Good", "odd ", " grade "]) - * const newSf = sf.str.trim(d) - * ["Good", "odd", "grade"] - * ``` - */ - trim(options?: { - inplace: boolean; - }): Series | void; - /** - * Joins strings to specified value - * @param valToJoin string value to join to the values - * @param joinChar Character to Join with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.join("new", "_") - * // ["Good_new", "odd_new", "grade_new"] - * ``` - */ - join(valToJoin?: string, joinChar?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Counts the number of characters in string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.len(d) - * // [4,3,5] - * ``` - */ - len(options?: { - inplace: boolean; - }): Series | void; -} diff --git a/danfojs-browser/types/index.d.ts b/danfojs-browser/types/index.d.ts deleted file mode 100644 index c254dda1..00000000 --- a/danfojs-browser/types/index.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import NDframe from "./core/generic"; -import Utils from './shared/utils'; -import Series from "./core/series"; -import { DataFrame } from "./core/frame"; -import { concat } from "./core/concat"; -import { merge } from "./core/merge"; -import { LabelEncoder, OneHotEncoder } from "./preprocessing/encodings"; -import { MinMaxScaler, StandardScaler } from "./preprocessing/scalers"; -import { date_range } from "./core/date_range"; -import get_dummies from "./core/get_dummies"; -import Str from "./core/strings"; -import Dt, { toDateTime } from "./core/datetime"; -import { - readCSV as read_csv, - toCSV as to_csv, - readJSON as read_json, - toJSON as to_json, - readExcel as read_excel, - toExcel as to_excel -} from "./io"; - - -export { - date_range, - toDateTime, - concat, - merge, - NDframe, - Utils, - Str, - Dt, - Series, - DataFrame, - read_csv, - to_csv, - read_json, - to_json, - read_excel, - to_excel, - MinMaxScaler, - StandardScaler, - LabelEncoder, - OneHotEncoder, - get_dummies -}; diff --git a/danfojs-browser/types/io/index.d.ts b/danfojs-browser/types/io/index.d.ts deleted file mode 100644 index 880a7061..00000000 --- a/danfojs-browser/types/io/index.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { $readCSV, $toCSV} from "./io.csv"; -import { $readJSON, $toJSON } from "./io.json"; -import { $readExcel, $toExcel } from "./io.excel"; - -export { - $readCSV as readCSV, - $toCSV as toCSV, - $readJSON as readJSON, - $toJSON as toJSON, - $readExcel as readExcel, - $toExcel as toExcel - }; - \ No newline at end of file diff --git a/danfojs-browser/types/io/io.csv.d.ts b/danfojs-browser/types/io/io.csv.d.ts deleted file mode 100644 index 1485484b..00000000 --- a/danfojs-browser/types/io/io.csv.d.ts +++ /dev/null @@ -1,60 +0,0 @@ -/// -import { DataFrame, NDframe, Series } from '../index'; -import { CsvInputOptions, CsvOutputOptionsBrowser } from "../shared/types"; -/** - * Reads a CSV file from local or remote location into a DataFrame. - * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, - * hence all PapaParse options are supported. - * @param options Configuration object. Supports all Papaparse parse config options. - * @returns DataFrame containing the parsed CSV file. - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv") - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv", { - * delimiter: ",", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("./data/sample.csv") - * ``` - */ -declare const $readCSV: (filePath: string, options: CsvInputOptions) => Promise; - -/** - * Converts a DataFrame or Series to CSV. - * @param df DataFrame or Series to be converted to CSV. - * @param options Configuration object. Supports the following options: - * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const csv = toCSV(df) - * ``` - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toCSV(df, { - * filePath: "./data/sample.csv", - * header: true, - * sep: "+" - * }) - * ``` - */ -declare const $toCSV: (df: NDframe | DataFrame | Series, options?: CsvOutputOptionsBrowser | undefined) => string | void; - -export { $readCSV, $streamCSV, $toCSV }; diff --git a/danfojs-browser/types/io/io.excel.d.ts b/danfojs-browser/types/io/io.excel.d.ts deleted file mode 100644 index b91d6c90..00000000 --- a/danfojs-browser/types/io/io.excel.d.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { HeadersInit } from "node-fetch"; -import { DataFrame, NDframe, Series } from '../index'; -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param filePath URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx") - * ``` - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx", { - * method: "GET", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("./data/sample.xlsx") - * ``` - */ -declare const $readExcel: (filePath: string, options?: { - sheet?: number | undefined; - method?: string | undefined; - headers?: HeadersInit | undefined; -}) => Promise; -/** - * Converts a DataFrame or Series to Excel Sheet. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. - * @example - * ``` - * import { toExcel } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toExcel(df, { - * filePath: "./data/sample.xlsx", - * sheetName: "MySheet", - * }) - * ``` - */ -declare const $toExcel: (df: NDframe | DataFrame | Series, options?: { - filePath?: string | undefined; - sheetName?: string | undefined; -} | undefined) => void; -export { $readExcel, $toExcel }; diff --git a/danfojs-browser/types/io/io.json.d.ts b/danfojs-browser/types/io/io.json.d.ts deleted file mode 100644 index 49d0ae3f..00000000 --- a/danfojs-browser/types/io/io.json.d.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { HeadersInit } from "node-fetch"; -import { DataFrame, NDframe, Series } from '../index'; -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param filePath URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json") - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json", { - * headers: { - * Accept: "text/json", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("./data/sample.json") - * ``` - */ -declare const $readJSON: (filePath: string, options?: { - method?: string | undefined; - headers?: HeadersInit | undefined; -}) => Promise; - -/** - * Converts a DataFrame or Series to JSON. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const json = toJSON(df) - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toJSON(df, { - * filePath: "./data/sample.json", - * format: "row" - * }) - * ``` - */ -declare const $toJSON: (df: NDframe | DataFrame | Series, options?: { - format?: "row" | "column" | undefined; - fileName?: string | undefined; - download?: boolean | undefined; -} | undefined) => object | void; -export { $readJSON, $toJSON }; diff --git a/danfojs-browser/types/plotting/plot.d.ts b/danfojs-browser/types/plotting/plot.d.ts deleted file mode 100644 index de3963e9..00000000 --- a/danfojs-browser/types/plotting/plot.d.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Plotting methods and Functions performed on Series and DataFrames - */ -export class Plot { - constructor(ndframe?: any, div?: any); - div?: any; - ndframe?: any; - /** - * Plot Series or DataFrame as lines. This function is useful to plot lines using DataFrame’s values as coordinates. - * Make plots of Series or DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - line(config?: any): void; - /** - * Plot Series or DataFrame as Bars. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - bar(config?: any): void; - /** - * Plot two or more columns in a DataFrame as scatter points. If Series, plot against its index - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - scatter(config?: any): void; - /** - * Plot columns in a Series/DataFrame as Histograms. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - hist(config?: any): void; - /** - * Makes Pie Plots from two Columns in a DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - pie(config?: any): void; - /** - * Plot Box plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - box(config?: any): void; - /** - * Plot Violin plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - violin(config?: any): void; - /** - * Display DataFrame in a div using D3.js format - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - table(config?: any): void; - __get_plot_params(config?: any): (string[] | { - layout: {}; - })[]; - ____check_if_cols_exist(cols?: any): any; -} diff --git a/danfojs-browser/types/preprocessing/encodings.d.ts b/danfojs-browser/types/preprocessing/encodings.d.ts deleted file mode 100644 index 77cb5771..00000000 --- a/danfojs-browser/types/preprocessing/encodings.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import Series from "../core/series"; -import { DataFrame } from "../core/frame"; - -export class LabelEncoder { - /** - * - * @param {data} data [Array|Series] - * @returns Array. - */ - fit(data?: any): Series; - label?: any; - /** - * Transform data using the label generated from fitting - * @param {data} data [Array|Series] - * @returns Array - */ - transform(data?: any): Series; -} -export class OneHotEncoder { - fit(data?: any): DataFrame; - label?: any; - transform(data?: any): DataFrame; -} diff --git a/danfojs-browser/types/preprocessing/scalers.d.ts b/danfojs-browser/types/preprocessing/scalers.d.ts deleted file mode 100644 index 73e97a7f..00000000 --- a/danfojs-browser/types/preprocessing/scalers.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -import Series from "../core/series"; -import { DataFrame } from "../core/frame"; -export class MinMaxScaler { - /** - * Fit minmax scaler on data, to obtain their min and max value - * @param {data} data [DataRame | Series | Array] - * @returns Array - */ - fit(data?: any): Series | DataFrame; - max?: any; - min?: any; - /** - * Transform an array using the min and max generated from the fitting on data - * @param {data} data [Array] - * @returns array - */ - transform(data?: any): Series | DataFrame; - - /** - * Restore a transformed array to their original values, - * using the min and max generated from the fitting on data - * @param {Series|Array|DataFrame} data - * @returns Series|DataFrame - */ - inverse_transform(data?: any): Series | DataFrame; -} -export class StandardScaler { - /** - * - * @param {data} data [DataRame | Series | Array] - * @returns Array - */ - fit(data?: any): Series | DataFrame; - std?: any; - mean?: any; - transform(data?: any): Series | DataFrame; - inverse_transform(data?: any): Series | DataFrame; -} - diff --git a/danfojs-browser/types/shared/config.d.ts b/danfojs-browser/types/shared/config.d.ts deleted file mode 100644 index 3aac789b..00000000 --- a/danfojs-browser/types/shared/config.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { BaseUserConfig, TableUserConfig } from 'table'; -import { ConfigsType } from './types'; -/** - * Package wide configuration class - */ -export default class Configs { - tableDisplayConfig: BaseUserConfig & TableUserConfig; - tableMaxRow: number; - tableMaxColInConsole: number; - dtypeTestLim: number; - lowMemoryMode: boolean; - constructor(options: ConfigsType); - setTableDisplayConfig(config: BaseUserConfig & TableUserConfig): void; - get getTableDisplayConfig(): BaseUserConfig & TableUserConfig; - setTableMaxColInConsole(val: number): void; - get getTableMaxColInConsole(): number; - setMaxRow(val: number): void; - get getMaxRow(): number; - get getDtypeTestLim(): number; - setDtypeTestLim(val: number): void; - get isLowMemoryMode(): boolean; - setIsLowMemoryMode(val: boolean): void; -} diff --git a/danfojs-browser/types/shared/errors.d.ts b/danfojs-browser/types/shared/errors.d.ts deleted file mode 100644 index d7bd325c..00000000 --- a/danfojs-browser/types/shared/errors.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { DataFrame } from "../core/frame"; -import NDframe from "../core/generic"; -/** - * Package wide error throwing class - */ -declare class ErrorThrower { - throwColumnNamesLengthError: (ndframe: NDframe, columns: Array) => void; - throwIndexLengthError: (ndframe: NDframe, index: Array) => void; - throwIndexDuplicateError: () => void; - throwColumnDuplicateError: () => void; - throwDtypesLengthError: (ndframe: NDframe, dtypes: Array) => void; - throwDtypeNotSupportedError: (dtype: string) => void; - throwColumnLengthError: (ndframe: NDframe | DataFrame, arrLen: number) => void; - throwRowLengthError: (ndframe: NDframe, arrLen: number) => void; - throwColumnNotFoundError: (ndframe: DataFrame | NDframe) => void; - throwNotImplementedError: () => void; - throwIlocRowIndexError: () => void; - throwIlocColumnsIndexError: () => void; - throwStringDtypeOperationError: (operation: string) => void; - throwSeriesMathOpLengthError: (ndframe: NDframe, other: NDframe) => void; -} -declare const _default: ErrorThrower; -export default _default; diff --git a/danfojs-browser/types/shared/types.d.ts b/danfojs-browser/types/shared/types.d.ts deleted file mode 100644 index 407430be..00000000 --- a/danfojs-browser/types/shared/types.d.ts +++ /dev/null @@ -1,423 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { DataFrame } from '../core/frame'; -import { Tensor } from '@tensorflow/tfjs-node'; -import Series from '../core/series'; -import { BaseUserConfig, TableUserConfig } from "table"; -import Str from '../core/strings'; -import Dt from '../core/datetime'; -import { ParseConfig } from 'papaparse'; -import { GroupBy } from '../core/groupby'; -import { Plot } from "../plotting/plot"; - -export declare type DTYPES = "float32" | "int32" | "string" | "boolean" | "undefined"; -export declare type ArrayType2D = Array; -export declare type ArrayType1D = Array; -export declare type ConfigsType = { - tableDisplayConfig?: BaseUserConfig & TableUserConfig; - tableMaxRow?: number; - tableMaxColInConsole?: number; - dtypeTestLim?: number; - lowMemoryMode?: boolean; - tfInstance?: any; -}; -export interface BaseDataOptionType { - type?: number; - index?: Array; - columns?: string[]; - dtypes?: Array; - config?: ConfigsType; -} -export interface NdframeInputDataType { - data: any; - type?: number; - index?: Array; - columns?: string[]; - dtypes?: Array; - config?: ConfigsType; - isSeries: boolean; -} -export interface LoadArrayDataType { - data: ArrayType1D | ArrayType2D; - index?: Array; - columns?: string[]; - dtypes?: Array; -} -export interface LoadObjectDataType { - data: object | Array; - type?: number; - index?: Array; - columns?: string[]; - dtypes?: Array; -} -export declare type AxisType = { - index: Array; - columns: Array; -}; -export interface NDframeInterface { - config?: ConfigsType; - $setDtypes(dtypes: Array, infer: boolean): void; - $setIndex(index: Array): void; - $resetIndex(): void; - $setColumnNames(columns: string[]): void; - get dtypes(): Array; - get ndim(): number; - get axis(): AxisType; - get index(): Array; - get columns(): string[]; - get shape(): Array; - get values(): ArrayType1D | ArrayType2D; - get tensor(): Tensor; - get size(): number; - to_csv(options?: CsvOutputOptionsNode): string | void; - to_json(options?: { - format?: "row" | "column"; - filePath?: string; - }): object | void; - to_excel(options?: { - filePath?: string; - sheetName?: string; - }): void; - print(): void; -} -export declare type CsvOutputOptionsNode = { - filePath?: string; - sep?: string; - header?: boolean; -}; -export type CsvOutputOptionsBrowser = { fileName?: string, sep?: string, header?: boolean, download?: boolean } -export interface CsvInputOptions extends ParseConfig { -} -export interface SeriesInterface extends NDframeInterface { - iloc(rows: Array): Series; - head(rows: number): Series; - tail(rows: number): Series; - sample(num: number, options?: { - seed?: number; - }): Promise; - add(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - sub(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - mul(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - div(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - pow(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - mod(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - mean(): number; - median(): number; - mode(): any; - min(): number; - max(): number; - sum(): number; - count(): number; - maximum(other: Series | number | Array): Series; - minimum(other: Series | number | Array): Series; - round(dp: number, options?: { - inplace?: boolean; - }): Series | void; - std(): number; - var(): number; - isna(): Series; - fillna(options?: { - value: number | string | boolean, - inplace?: boolean; - }): Series | void; - sort_values(options?: { - ascending?: boolean, - inplace?: boolean; - }): Series | void; - copy(): Series; - describe(): Series; - reset_index(options?: { - inplace?: boolean; - }): Series | void; - set_index(options?: { - index: Array, - inplace?: boolean; - }): Series | void; - map(callable: any, options?: { - inplace?: boolean; - }): Series | void; - apply(callable: any, options?: { - inplace?: boolean; - }): Series | void; - unique(): Series; - nunique(): number; - value_counts(): Series; - abs(options?: { - inplace?: boolean; - }): Series | void; - cumsum(options?: { - inplace?: boolean; - }): Series | void; - cummin(options?: { - inplace?: boolean; - }): Series | void; - cummax(options?: { - inplace?: boolean; - }): Series | void; - cumprod(options?: { - inplace?: boolean; - }): Series | void; - lt(other: Series | number | Array): Series; - gt(other: Series | number | Array): Series; - le(other: Series | number | Array): Series; - ge(other: Series | number | Array): Series; - ne(other: Series | number | Array): Series; - eq(other: Series | number | Array): Series; - replace(options?: { - oldValue: string | number | boolean, - newValue: string | number | boolean, - inplace?: boolean; - }): Series | void; - dropna(options?: { - inplace?: boolean; - }): Series | void; - argsort(): Series; - argmax(): number; - argmin(): number; - get dtype(): string; - drop_duplicates(options?: { - keep?: "first" | "last"; - inplace?: boolean; - }): Series | void; - astype(dtype: "float32" | "int32" | "string" | "boolean", options?: { - inplace?: boolean; - }): Series | void; - get str(): Str; - get dt(): Dt; - append(values: string | number | boolean | Series | ArrayType1D, index: Array | number | string, options?: { - inplace?: boolean; - }): Series | void; - toString(): string; - and(other: any): Series; - or(other: any): Series; - get_dummies(options?: { - prefix?: string | Array; - prefixSeparator?: string | Array; - inplace?: boolean; - }): DataFrame; - plot(div: string): Plot -} -export interface DataFrameInterface extends NDframeInterface { - [key: string]: any; - drop(options: { - columns?: string | Array; - index?: Array; - inplace?: boolean; - }): DataFrame | void; - loc(options: { - rows?: Array; - columns?: Array; - }): DataFrame; - iloc(options: { - rows?: Array; - columns?: Array; - }): DataFrame; - head(rows?: number): DataFrame; - tail(rows?: number): DataFrame; - sample(num: number, options?: { - seed?: number; - }): Promise; - add(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - sub(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - mul(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - div(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - pow(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - mod(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - mean(options?: { - axis?: 0 | 1; - }): Series; - median(options?: { - axis?: 0 | 1; - }): Series; - mode(options?: { - axis?: 0 | 1; - keep?: number; - }): Series; - min(options?: { - axis?: 0 | 1; - }): Series; - max(options?: { - axis?: 0 | 1; - }): Series; - std(options?: { - axis?: 0 | 1; - }): Series; - var(options?: { - axis?: 0 | 1; - }): Series; - sum(options?: { - axis?: 0 | 1; - }): Series; - count(options?: { - axis?: 0 | 1; - }): Series; - round(dp?: number, options?: { - inplace: boolean; - }): DataFrame | void; - cumsum(options?: { - axis?: 0 | 1; - }): DataFrame | void; - cummin(options?: { - axis?: 0 | 1; - }): DataFrame | void; - cummax(options?: { - axis?: 0 | 1; - }): DataFrame | void; - cumprod(options?: { - axis?: 0 | 1; - }): DataFrame | void; - copy(): DataFrame; - reset_index(options: { - inplace?: boolean; - }): DataFrame | void; - set_index(options: { - index: Array; - column?: string; - drop?: boolean; - inplace?: boolean; - }): DataFrame | void; - describe(): DataFrame; - select_dtypes(include: Array): DataFrame; - abs(options?: { - inplace?: boolean; - }): DataFrame | void; - query(options: { - column?: string, - is?: string, - to?: any, - condition?: Series | Array, - inplace?: boolean - }): DataFrame | void - addColumn(options: { - column: string, - values: Series | ArrayType1D, - inplace?: boolean; - }): DataFrame | void; - column(column: string): Series; - fillna(value: ArrayType1D, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - isna(): DataFrame; - dropna(axis?: 0 | 1, options?: { - inplace?: boolean; - }): DataFrame | void; - apply(callable: any, options?: { - axis?: 0 | 1; - }): DataFrame | Series; - apply_map(callable: any, options?: { - inplace?: boolean; - }): DataFrame | void; - lt(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - gt(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - le(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - ge(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - ne(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - eq(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - replace(oldValue: number | string | boolean, newValue: number | string | boolean, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - transpose(options?: { - inplace?: boolean; - }): DataFrame | void; - get T(): DataFrame; - get ctypes(): Series; - astype(options?: { - column: string, - dtype: "float32" | "int32" | "string" | "boolean", - inplace?: boolean; - }): DataFrame | void; - nunique(axis: 0 | 1): Series; - rename(mapper: object, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - sort_index(options?: { - inplace?: boolean; - ascending?: boolean; - }): DataFrame | void; - sort_values(options?: { - by: string, - ascending?: boolean; - inplace?: boolean; - }): DataFrame | void; - append(newValues: ArrayType1D | ArrayType2D | Series | DataFrame, index: Array | number | string, options?: { - inplace?: boolean; - }): DataFrame | void; - toString(): string; - get_dummies(options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string | Array; - inplace?: boolean; - }): DataFrame | void; - groupby(column: string): GroupBy; - plot(div: string): Plot - -} -export interface DateTime { - month(): Series; - day(): Series; - year(): Series; - month_name(): Series; - monthday(): Series; - weekdays(): Series; - hours(): Series; - seconds(): Series; - minutes(): Series; -} diff --git a/danfojs-browser/types/shared/utils.d.ts b/danfojs-browser/types/shared/utils.d.ts deleted file mode 100644 index 5556d505..00000000 --- a/danfojs-browser/types/shared/utils.d.ts +++ /dev/null @@ -1,259 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { ArrayType1D, ArrayType2D } from './types'; -import { Series } from '../'; -import { DataFrame } from '../'; -/** - * Utility class for working with Frames and Series - */ -export default class Utils { - /** - * Removes an element from a 1D array - * - * ```js - * - * ``` - * @param arr The array to filter. - * @param index The index to filter by. - */ - removeElementFromArray(arr: ArrayType1D, index: number): ArrayType1D; - /** - * Check if value is a string. - * @param value The value to check. - * @returns - */ - isString(value: T): boolean; - /** - * Checks if value is a number. - * @param value The value to check. - * @returns - */ - isNumber(value: T): boolean; - /** - * Checks if value is an object. - * @param value The value to check. - * @returns - */ - isObject(value: any): boolean; - /** - * Checks if a value is null - * @param value The value to check. - * @returns - */ - isNull(value: T): boolean; - /** - * Checks if a value is undefined - * @param value The value to check. - * @returns - */ - isUndefined(value: T): boolean; - /** - * Checks if a value is empty. Empty means it's either null, undefined or NaN - * @param value The value to check. - * @returns - */ - isEmpty(value: T): boolean; - /** - * Generates an array of integers between specified range - * @param start The starting number. - * @param end The ending number. - */ - range(start: number, end: number): Array; - /** - * Checks if object has the specified key - * @param obj The object to check. - * @param key The key to find. - */ - keyInObject(obj: object, key: number | string): boolean; - /** - * Transposes an array of array - * @param obj The object to check. - * @param key The key to find. - */ - transposeArray(arr: ArrayType1D | ArrayType2D): ArrayType1D | ArrayType2D; - /** - * Retrieve row array and column names from an object of the form {a: [1,2,3,4], b: [30,20, 30, 20]} - * @param obj The object to retrieve rows and column names from. - */ - getRowAndColValues(obj: object): [ArrayType1D | ArrayType2D, string[]]; - /** - * Converts a 2D array of array to 1D array for Series Class - * @param arr The array to convert. - */ - convert2DArrayToSeriesArray(arr: ArrayType2D): Array; - /** - * Replaces all missing values with NaN. Missing values are undefined, Null and Infinity - * @param arr The array - * @param isSeries Whether the arr is a series or not - */ - replaceUndefinedWithNaN(arr: ArrayType1D | ArrayType2D, isSeries: boolean): ArrayType1D | ArrayType2D; - /** - * Infer data type from an array or array of arrays - * @param arr An array or array of arrays - */ - inferDtype(arr: ArrayType1D | ArrayType2D): string[]; - /** - * Private type checker used by inferDtype function - * @param arr The array - */ - private $typeChecker; - /** - * Returns the unique values in an 1D array - * @param arr The array - */ - unique(arr: ArrayType1D): ArrayType1D; - /** - * Checks if array is 1D - * @param arr The array - */ - is1DArray(arr: ArrayType1D | ArrayType2D): boolean; - /** - * Converts an array to an object using array index as object keys - * @param arr The array - */ - convertArrayToObject(arr: ArrayType1D | ArrayType2D): any; - /** - * Count the NaN and non-NaN values present in an array - * @param arr Array object - * @param val whether to return the value count instead of the null count - * @param isSeries Whether the array is of type series or not - */ - countNaNs(arr: ArrayType1D | ArrayType2D, returnVal: boolean | undefined, isSeries: boolean): number | Array; - /** - * Round elements of an array or array of arrays to specified dp - * @param arr The Array to round - * @param dp The number of dp to round to - * @param isSeries Whether the array is of type Series or not - */ - round(arr: Array, dp: number | undefined, isSeries: boolean): ArrayType1D | ArrayType2D; - /** - * Checks if a func is a function - * @param func - */ - isFunction(func: object): boolean; - /** - * Generates n random numbers between start and end. - * @param start - * @param end - * @param size - */ - randNumberGenerator(start: number, end: number, size: number): number[]; - /** - * Throws error when a required parameter is missing. - * @param paramsObject The parameters passed to the function - * @param paramsNeeded The required parameters in the function - */ - throwErrorOnWrongParams(paramsObject: object, paramsNeeded: Array): void; - /** - * Maps integer values (0, 1) to boolean (false, true) - * @param arr The array of integers - * @param dim The dimension of the array - */ - mapIntegersToBooleans(arr: Array, dim: number): Array; - /** - * Maps boolean values (false, true) to integer equivalent (0, 1) - * @param arr The array of booleans - * @param dim The dimension of the array - */ - mapBooleansToIntegers(arr: Array, dim: number): Array; - /** - * Generates an array of dim (row x column) with inner values set to zero - * @param row - * @param column - */ - zeros(row: number, column: number): ArrayType1D | ArrayType2D; - /** - * Shuffles and returns a random slice of an array - * @param num - * @param array - */ - shuffle(array: ArrayType1D | ArrayType2D, num: number): ArrayType1D | ArrayType2D; - /** - * Sorts an array in specified order - * @param arr - * @param ascending - * @returns - */ - sort(arr: Array, ascending?: boolean): Array; - /** - * Checks if current environment is Browser - */ - isBrowserEnv(): any; - /** - * Checks if current environment is Node - */ - isNodeEnv(): any; - /** - * Remove NaN values from 1D array - * @param arr - */ - removeMissingValuesFromArray(arr: Array | ArrayType1D): (string | number | boolean)[]; - /** - * Replace NaN with null before tensor operations - * @param arr - */ - replaceNanWithNull(arr: ArrayType1D | ArrayType2D): (string | number | boolean | (string | number | boolean)[] | null)[]; - /** - * Get duplicate values in a array - * @param arr - */ - getDuplicate(arr: Array): any; - /** - * Returns the index of a sorted array - * @param arr1 The first array - * @param arr2 The second array - * @param dtype The data type of the arrays - * - * @returns sorted index - */ - sortArrayByIndex(arr1: ArrayType1D | ArrayType2D, arr2: ArrayType1D | ArrayType2D, dtype: string): number[]; - /** - * Returns a new series with properties of the old series - * - * @param series The series to copy - */ - createNdframeFromNewDataWithOldProps({ ndFrame, newData, isSeries }: { - ndFrame: Series; - newData: any; - isSeries: boolean; - }): Series | DataFrame; - /** - * Checks if two series are compatible for a mathematical operation - * @param object - * - * firstSeries ==> First Series object - * - * secondSeries ==> Second Series object to comapre with - * - * operation ==> The mathematical operation - */ - checkSeriesOpCompactibility({ firstSeries, secondSeries, operation }: { - firstSeries: Series; - secondSeries: Series; - operation: string; - }): void; - /** - * Custom sort for an array of index and values - * @param arr The array of objects to sort - * @param ascending Whether to sort in ascending order or not - */ - sortObj(arr: Array<{ - index: number | string; - value: number | string | boolean; - }>, ascending: boolean): { - index: number | string; - value: number | string | boolean; - }[]; -} diff --git a/danfojs-node/.editorconfig b/danfojs-node/.editorconfig deleted file mode 100644 index cb8b48c7..00000000 --- a/danfojs-node/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -# Editor configuration, see http://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true \ No newline at end of file diff --git a/danfojs-node/src/core/concat.js b/danfojs-node/src/core/concat.js deleted file mode 100644 index 0d3d28ad..00000000 --- a/danfojs-node/src/core/concat.js +++ /dev/null @@ -1,219 +0,0 @@ -import DataFrame from './frame'; -// import { utils } from "../shared/utils"; -import Series from './series'; - - -export class Concat { - constructor(kwargs) { - - - // check if keys exist in kwargs - // utils.__in_object(kwargs, "df_list", "df_list not found: specify the list of dataframe"); - // utils.__in_object(kwargs, "axis", "axis not found: specify the axis"); - - let df_list = null; //set the df_list to null - let axis = null; // set axis to null - let indexes = null; - - //check if df_list is an array - if (Array.isArray(kwargs["df_list"])) { - - df_list = kwargs["df_list"]; - } else { - throw new Error("df_list must be an Array of dataFrames/Series"); - } - - //check if axis is int and is either 0 or 1 - if (typeof kwargs["axis"] === "number") { - - if (kwargs["axis"] == 0 || kwargs["axis"] == 1) { - - axis = kwargs["axis"]; - } else { - axis = 1; - // throw new Error("Invalid axis: axis must be 0 or 1") - } - - } else { - throw new Error("axis must be a number"); - } - - - let df_object = Object.assign({}, df_list); // convert the array to object - - if (axis == 1) { - - let columns = []; - let duplicate_col_count = {}; - let max_length = 0; - let a_key = Object.keys(df_object)[0]; - indexes = df_object[a_key].index; - for (let key in df_object) { - - let column = df_object[key].columns; - let length = df_object[key].values.length; - - if (length > max_length) { - max_length = length; - } - - for (let index in column) { - - let col_name = column[index]; - if (col_name in duplicate_col_count) { - - let count = duplicate_col_count[col_name]; - let name = `${col_name}_${count + 1}`; - - columns.push(name); - - duplicate_col_count[col_name] = count + 1; - } else { - - columns.push(col_name); - duplicate_col_count[col_name] = 1; - } - } - - - } - - let data = new Array(max_length); - - for (let key in df_list) { - - let values = df_list[key].values; - - for (let index = 0; index < values.length; index++) { - - let val = values[index]; - if (typeof data[index] === "undefined") { - - if (Array.isArray(val)){ - data[index] = val; - } else { - data[index] = [ val ]; - } - - } else { - if (Array.isArray(val)){ - data[index].push(...val); - } else { - data[index].push(val); - } - - } - } - - if (values.length < max_length) { - let column_length = df_list[key].columns.length; - let null_array = Array(column_length); - - for (let col = 0; col < column_length; col++) { - null_array[col] = NaN; - } - - if (typeof data[max_length - 1] === "undefined") { - data[max_length - 1] = null_array; - } else { - data[max_length - 1].push(...null_array); - } - } - } - - let df = new DataFrame(data, { columns: columns, index: indexes }); //convert to dataframe - return df; - } else { - //concatenate base on axis 0 - let columns = []; - let row_indexes = []; - let col_i = 0; - for (let key in df_list) { - let column = df_list[key].columns; - columns.push(...column); - indexes = df_list[key].index; - let r_index = indexes.map((val) => { - return `${val}_row${col_i}`; - }); - row_indexes.push(...r_index); - col_i += 1; - } - - let column_set = new Set(columns); - - columns = Array.from(column_set); - - let data = []; - - for (let key in df_list) { - - let value = df_list[key].values; - - // let col_length = value[0].length - - let df_columns = df_list[key].columns; - - let not_exist = []; - for (let col_index in columns) { - let col_name = columns[col_index]; - - let is_index = df_columns.indexOf(col_name); - - if (is_index == -1) { - not_exist.push(col_name); - } - } - if (not_exist.length > 0) { - for (let i = 0; i < value.length; i++) { - let row_value = value[i]; - - let new_arr = Array(columns.length); - for (let j = 0; j < columns.length; j++) { - - let col_name = columns[j]; - if (not_exist.includes(col_name)) { - - new_arr[j] = NaN; - } else { - let index = df_columns.indexOf(col_name); - if (Array.isArray(row_value)){ - new_arr[j] = row_value[index]; - } else { - new_arr[j] = row_value; - } - - } - - } - data.push(new_arr); - } - } else { - data.push(...value); - } - - } - - if (Array.isArray(data[0])){ - let df = new DataFrame(data, { columns: columns, index: row_indexes }); - return df; - } else { - let sf = new Series(data, { index: row_indexes }); - return sf; - } - - - } - - } -} - - -/** -* Concatenate pandas objects along a particular axis with optional set logic along the other axes. -* @param {kwargs} {df_list: List of DataFrame to concatenate together axis: 0 for row axis and 1 for index axis -* @returns {DataFrame} -*/ -export const concat = (kwargs) => { - let concat_sf = new Concat(kwargs); - return concat_sf; -}; diff --git a/danfojs-node/src/core/date_range.js b/danfojs-node/src/core/date_range.js deleted file mode 100644 index b1805173..00000000 --- a/danfojs-node/src/core/date_range.js +++ /dev/null @@ -1,289 +0,0 @@ -import { utils } from "../shared/utils"; - -/** - * Generate date range between a specified set of date - * @param {kwargs} kwargs { - * start : string - * end : string - * period: int - * freq : string - * } - * @returns Array - */ -export class date_range { - constructor(kwargs){ - - this.offset = null; - - if (utils.keyInObject(kwargs, "start")){ - this.start = kwargs["start"]; - } else { - this.start = null; - } - - if (utils.keyInObject(kwargs, "end")){ - this.end = kwargs["end"]; - } else { - this.end = null; - } - - if (utils.keyInObject(kwargs, "period")){ - this.period = kwargs["period"]; - } else { - this.period = null; - } - - if (utils.keyInObject(kwargs, "freq")){ - this.freq = kwargs["freq"]; - } else { - this.freq = "D"; - } - - this.freq_list = [ "M", "D", "s", "H", "m", "Y" ]; - - if (this.freq.length == 1){ - if (!this.freq_list.includes(this.freq)){ - throw new Error(`invalid freq ${this.freq}`); - } - } else { - this.offset = parseInt(this.freq.slice(0, -1)); - if (!Number.isFinite(this.offset)){ - throw new Error(`invalid freq offset ${this.freq.slice(0, -1)}`); - } - this.freq = this.freq.slice(-1); - if (!this.freq_list.includes(this.freq)){ - throw new Error(`invalid freq ${this.freq}`); - } - } - - let rslt = this.range(this.start, this.end, this.period, this.offset); - return rslt; - - } - - range(start, end, period, offset = null){ - - let start_date = null; - let end_date = null; - let start_range = null; - let end_range = null; - if (start && end){ - start_date = new Date(start); - start_range = this.freq_type(start_date, this.freq); - end_date = new Date(end); - end_range = this.freq_type(end_date, this.freq); - - //check if the end year is greater than start year - let start_year = start_date.getFullYear(); - let end_year = end_date.getFullYear(); - if ((start_year < end_year)){ - // end_range = start_range + end_range - if (this.freq == "M"){ - end_range = this.month_end(start_date, end_date); - } else if (this.freq == "D"){ - end_range = this.day_end(start_date, end_date) - start_range; - - } - } - - let range_array = utils.range(start_range, end_range); - - if (offset){ - range_array = this.offset_count(range_array, offset); - } - - if (this.freq == "M"){ - range_array = this.month_range(range_array); - } - - let date_range = range_array.map((x) => { - return this.set_dateProps(start_date, this.freq, x); - }); - date_range[date_range.length - 1] = end_date; - - let date_string = this.toLocalString(date_range); - - return date_string; - } else if (start && !(end)){ - start_date = new Date(start); - start_range = this.freq_type(start_date, this.freq); - end_range = offset ? ((period * offset) - 1) : period - 1; - - if (start_range > end_range){ - end_range = end_range + start_range; - } - let range_array = utils.range(start_range, end_range); - - - if (offset){ - range_array = this.offset_count(range_array, offset); - } - - let date_range = range_array.map((x) => { - return this.set_dateProps(start_date, this.freq, x); - }); - - let date_string = this.toLocalString(date_range); - return date_string; - - } else if (end && !(start)){ - end_date = new Date(end); - end_range = this.freq_type(end_date, this.freq); - start_range = (end_range - period) + 1; - - let range_array = utils.range(start_range, end_range); - - if (offset){ - range_array = this.offset_count(range_array, offset); - } - - let date_range = range_array.map((x) => { - return this.set_dateProps(end_date, this.freq, x); - }); - - let date_string = this.toLocalString(date_range); - return date_string; - } - } - - freq_type(date, ftype){ - - let rslt = null; - switch (ftype){ - - case "M": - rslt = date.getMonth(); - break; - case "Y": - rslt = date.getFullYear(); - break; - case "s": - rslt = date.getSeconds(); - break; - case "D": - rslt = date.getDate(); - break; - case "H": - rslt = date.getHours(); - break; - case "m": - rslt = date.getMinutes(); - break; - } - return rslt; - } - - offset_count(d_array, offset){ - - let r_array = []; - - for (let i = 0; i < d_array.length; i += offset){ - r_array.push(d_array[i]); - } - return r_array; - } - - set_dateProps(date, ftype, val){ - - let new_date = new Date(date.valueOf()); - switch (ftype){ - - case "M": - if (val.length == 2){ - - new_date.setYear(new_date.getFullYear() + val[0]); - new_date.setMonth(parseInt(val[1])); - } else { - new_date.setMonth(val); - } - - break; - case "Y": - new_date.setYear(val); - break; - case "s": - new_date.setSeconds(val); - break; - case "D": - new_date.setDate(val); - break; - case "H": - new_date.setHours(val); - break; - case "m": - new_date.setMinutes(val); - break; - } - return new_date; - } - - toLocalString(d_array){ - - let r_array = d_array.map((x) => { - - return x.toLocaleString(); - }); - - return r_array; - } - - month_end(start_date, end_date){ - - let end_month = end_date.getMonth(); - - let diff_year = end_date.getFullYear() - start_date.getFullYear(); - - let end_range = (12 * diff_year) + end_month; - - return end_range; - } - - month_range(range){ - - let minus = null; - let y_val = 0; - let d_range = range.map((x) => { - - if (x > 11){ - if (x % 12 == 0){ - minus = x; - y_val = x / 12; - return [ y_val, (x - minus) ]; - } else { - return [ y_val, (x - minus) ]; - } - - } - return [ y_val, x ]; - }); - - return d_range; - } - - day_end(start_date, end_date){ - - let month_end = this.month_end(start_date, end_date); - let range = utils.range(start_date.getMonth(), month_end); - let m_range = this.month_range(range); - - // let s_date = new Date(start_date.getFullYear(),start_date.getMonth(),0) - let sum = 0; - for (let i = 0; i < m_range.length; i++){ - - let val = m_range[i]; - - let d_date = null; - if (i === m_range.length - 1) { - d_date = new Date(start_date.getFullYear() + val[0], val[1], end_date.getDate()).getDate(); - } else { - d_date = new Date(start_date.getFullYear() + val[0], val[1], 0).getDate(); - - } - - sum += d_date; - - } - return sum; - - } -} diff --git a/danfojs-node/src/core/datetime.js b/danfojs-node/src/core/datetime.js deleted file mode 100644 index 4a92a558..00000000 --- a/danfojs-node/src/core/datetime.js +++ /dev/null @@ -1,241 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; - -const MONTH_NAME = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; -const WEEK_NAME = ["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"]; - -/** - * Format and handle all datetime operations on Series or Array of date strings - * @param data Series or Array of date strings - */ -export default class TimeSeries { - - constructor(data) { - if (data instanceof Series) { - this.$dateObjectArray = this.processData(data.values); - } else { - this.$dateObjectArray = this.processData(data); - } - } - - /** - * Processed the data values into internal structure for easy access - * @param dateArray An array of date strings - */ - processData(dateArray) { - const values = dateArray.map((dateString) => new Date(`${dateString}`)); - return values; - } - - /** - * Returns the month, in local time. - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2019-03-01", - * "2019-04-01", - * ] - * const df = new Dataframe(data) - * const dfNew = df.dt.month() - * console.log(dfNew.values) - * // [1, 2, 3, 4] - * ``` - */ - month() { - const newValues = this.$dateObjectArray.map((date) => date.getMonth()); - return new Series(newValues); - } - - /** - * Returns the day of the week, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2019-03-01", - * "2019-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfWeek = df.dt.day() - * console.log(day.values) - * ``` - */ - day() { - const newValues = this.$dateObjectArray.map((date) => date.getDay()); - return new Series(newValues); - } - - /** - * Returns the year, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const year = df.dt.year() - * console.log(year.values) - * // [2019, 2019, 2021, 2020] - * ``` - */ - year() { - const newValues = this.$dateObjectArray.map((date) => date.getFullYear()); - return new Series(newValues); - } - - /** - * Returns the name of the month, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const monthName = df.dt.monthName().values - * console.log(monthName) - * // ["January", "February", "March", "April"] - * ``` - */ - month_name() { - const newValues = this.$dateObjectArray.map((date) => MONTH_NAME[date.getMonth()]); - return new Series(newValues); - } - - /** - * Returns the name of the day, of the week, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfWeekName = df.dt.dayOfWeekName().values - * console.log(dayOfWeekName) - * ``` - */ - weekdays() { - const newValues = this.$dateObjectArray.map((date) => WEEK_NAME[date.getDay()]); - return new Series(newValues); - } - - /** - * Returns the day of the month, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfMonth = df.dt.dayOfMonth().values - * console.log(dayOfMonth) - * // [1, 5, 2, 1] - * ``` - */ - monthday() { - const newValues = this.$dateObjectArray.map((date) => date.getDate()); - return new Series(newValues); - } - - /** - * Returns the hour of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const hour = df.dt.hour().values - * console.log(hour) - * // [0, 0, 0, 0] - * ``` - */ - hours() { - const newValues = this.$dateObjectArray.map((date) => date.getHours()); - return new Series(newValues); - } - - /** - * Returns the second of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const second = df.dt.second().values - * console.log(second) - * ``` - */ - seconds() { - const newValues = this.$dateObjectArray.map((date) => date.getSeconds()); - return new Series(newValues); - } - - /** - * Returns the minute of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const minute = df.dt.minute().values - * console.log(minute) - * ``` - */ - minutes() { - const newValues = this.$dateObjectArray.map((date) => date.getMinutes()); - return new Series(newValues); - } - -} - -export const toDateTime = (data) => { - return new TimeSeries(data); -}; diff --git a/danfojs-node/src/core/frame.js b/danfojs-node/src/core/frame.js deleted file mode 100644 index 45fcef58..00000000 --- a/danfojs-node/src/core/frame.js +++ /dev/null @@ -1,2383 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -import { variance, std, median, mode, mean } from 'mathjs'; -import { DATA_TYPES } from '../shared/defaults'; -import { scalar, tensor2d, data as tfData } from '@tensorflow/tfjs-node'; -import { _genericMathOp } from "./math.ops"; -import ErrorThrower from "../shared/errors"; -import { _iloc, _loc } from "./indexing"; -import { utils } from "../shared/utils"; -import NDframe from "./generic"; -import { table } from "table"; -import Series from './series'; -import { GroupBy } from "./groupby"; -import dummyEncode from "./get_dummies"; - - -// const utils = new Utils(); - -/** - * Two-dimensional ndarray with axis labels. - * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. - * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. - * @param data 2D Array, JSON, Tensor, Block of data. - * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * @param options.columns Array of column names. If not specified, column names are auto generated. - * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. - * @param options.config General configuration object for extending or setting NDframe behavior. - */ -/* @ts-ignore */ //COMMENT OUT WHEN METHODS HAVE BEEN IMPLEMENTED -export default class DataFrame extends NDframe { - constructor(data, options) { - const { index, columns, dtypes, config } = { index: undefined, columns: undefined, dtypes: undefined, config: undefined, ...options }; - super({ data, index, columns, dtypes, config, isSeries: false }); - this.$setInternalColumnDataProperty(); - } - - /** - * Maps all column names to their corresponding data, and return them objects. - * This makes column subsetting works. E.g this can work ==> `df["col1"]` - * @param column Optional, a single column name to map - */ - $setInternalColumnDataProperty(column) { - const self = this; - if (column && typeof column === "string") { - Object.defineProperty(self, column, { - get() { - return self.$getColumnData(column); - }, - set(arr) { - self.$setColumnData(column, arr); - } - }); - } else { - const columns = this.columns; - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - Object.defineProperty(this, column, { - get() { - return self.$getColumnData(column); - }, - set(arr) { - self.$setColumnData(column, arr); - } - }); - } - } - - } - - /** - * Returns the column data from the DataFrame by column name. - * @param column column name to get the column data - * @param returnSeries Whether to return the data in series format or not. Defaults to true - */ - $getColumnData(column, returnSeries = true) { - const columnIndex = this.columns.indexOf(column); - - if (columnIndex == -1) { - ErrorThrower.throwColumnNotFoundError(this); - } - - const dtypes = [this.$dtypes[columnIndex]]; - const index = [...this.$index]; - const columns = [column]; - const config = { ...this.$config }; - - if (this.$config.isLowMemoryMode) { - const data = []; - for (let i = 0; i < this.values.length; i++) { - const row = this.values[i]; - data.push(row[columnIndex]); - } - if (returnSeries) { - return new Series(data, { - dtypes, - index, - columns, - config - }); - } else { - return data; - } - - } else { - const data = this.$dataIncolumnFormat[columnIndex]; - if (returnSeries) { - return new Series(data, { - dtypes, - index, - columns, - config - }); - } else { - return data; - } - } - - } - - - /** - * Updates the internal column data via column name. - * @param column The name of the column to update. - * @param arr The new column data - */ - $setColumnData(column, arr) { - - const columnIndex = this.$columns.indexOf(column); - - if (columnIndex == -1) { - throw new Error(`ParamError: column ${column} not found in ${this.$columns}. If you need to add a new column, use the df.addColumn method. `); - } - - let colunmValuesToAdd; - - if (arr instanceof Series) { - colunmValuesToAdd = arr.values; - } else if (Array.isArray(arr)) { - colunmValuesToAdd = arr; - } else { - throw new Error("ParamError: specified value not supported. It must either be an Array or a Series of the same length"); - } - - if (colunmValuesToAdd.length !== this.shape[0]) { - ErrorThrower.throwColumnLengthError(this, colunmValuesToAdd.length); - } - - if (this.$config.isLowMemoryMode) { - //Update row ($data) array - for (let i = 0; i < this.$data.length; i++) { - (this.$data)[i][columnIndex] = colunmValuesToAdd[i]; - } - //Update the dtypes - this.$dtypes[columnIndex] = utils.inferDtype(colunmValuesToAdd)[0]; - } else { - //Update row ($data) array - for (let i = 0; i < this.values.length; i++) { - (this.$data)[i][columnIndex] = colunmValuesToAdd[i]; - } - //Update column ($dataIncolumnFormat) array since it's available in object - (this.$dataIncolumnFormat)[columnIndex] = arr; - - //Update the dtypes - this.$dtypes[columnIndex] = utils.inferDtype(colunmValuesToAdd)[0]; - } - - } - - /** - * Return data with missing values removed from a specified axis - * @param axis 0 or 1. If 0, column-wise, if 1, row-wise - */ - $getDataByAxisWithMissingValuesRemoved(axis) { - const oldValues = this.$getDataArraysByAxis(axis); - const cleanValues = []; - for (let i = 0; i < oldValues.length; i++) { - const values = oldValues[i]; - cleanValues.push(utils.removeMissingValuesFromArray(values)); - } - return cleanValues; - } - - /** - * Return data aligned to the specified axis. Transposes the array if needed. - * @param axis 0 or 1. If 0, column-wise, if 1, row-wise - */ - $getDataArraysByAxis(axis) { - axis = axis === 0 ? 1 : 0; - if (axis === 1) { - return this.values; - } else { - let dfValues; - if (this.config.isLowMemoryMode) { - dfValues = utils.transposeArray(this.values); - } else { - dfValues = this.$dataIncolumnFormat; - } - return dfValues; - } - } - - /* - * checks if DataFrame is compactible for arithmetic operation - * compatible Dataframe must have only numerical dtypes - **/ - $frameIsNotCompactibleForArithmeticOperation() { - const dtypes = this.dtypes; - const str = (element) => element == "string"; - return dtypes.some(str); - } - - /** - * Return Tensors in the right axis for math operations. - * @param other DataFrame or Series or number or array - * @param axis 0 or 1. If 0, column-wise, if 1, row-wise - * */ - $getTensorsForArithmeticOperationByAxis( - other, - axis - ) { - axis = axis === 0 ? 1 : 0; - if (typeof other === "number") { - return [this.tensor, scalar(other)]; - } else if (other instanceof DataFrame) { - return [this.tensor, other.tensor]; - } else if (other instanceof Series) { - if (axis === 1) { - return [this.tensor, tensor2d(other.values, [other.shape[0], 1])]; - } else { - return [this.tensor, tensor2d(other.values, [other.shape[0], 1]).transpose()]; - } - } else if (Array.isArray(other)) { - if (axis === 1) { - return [this.tensor, tensor2d(other, [other.length, 1])]; - } else { - return [this.tensor, tensor2d(other, [other.length, 1]).transpose()]; - } - } else { - throw new Error("ParamError: Invalid type for other parameter. other must be one of Series, DataFrame or number."); - } - - } - - /** - * Returns the dtype for a given column name - * @param column - */ - $getColumnDtype(column) { - const columnIndex = this.columns.indexOf(column); - if (columnIndex === -1) { - throw Error(`ColumnNameError: Column "${column}" does not exist`); - } - return this.dtypes[columnIndex]; - } - - $logicalOps(tensors, operation) { - let newValues = []; - - switch (operation) { - case 'gt': - newValues = tensors[0].greater(tensors[1]).arraySync(); - break; - case 'lt': - newValues = tensors[0].less(tensors[1]).arraySync(); - break; - case 'ge': - newValues = tensors[0].greaterEqual(tensors[1]).arraySync(); - break; - case 'le': - newValues = tensors[0].lessEqual(tensors[1]).arraySync(); - break; - case 'eq': - newValues = tensors[0].equal(tensors[1]).arraySync(); - break; - case 'ne': - newValues = tensors[0].notEqual(tensors[1]).arraySync(); - break; - - } - - const newData = utils.mapIntegersToBooleans(newValues, 2); - return new DataFrame( - newData, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - $MathOps(tensors, operation, inplace) { - let tensorResult; - - switch (operation) { - case 'add': - tensorResult = tensors[0].add(tensors[1]); - break; - case 'sub': - tensorResult = tensors[0].sub(tensors[1]); - break; - case 'pow': - tensorResult = tensors[0].pow(tensors[1]); - break; - case 'div': - tensorResult = tensors[0].div(tensors[1]); - break; - case 'mul': - tensorResult = tensors[0].mul(tensors[1]); - break; - case 'mod': - tensorResult = tensors[0].mod(tensors[1]); - break; - } - - if (inplace) { - const newData = tensorResult.arraySync(); - this.$setValues(newData); - } else { - return new DataFrame( - tensorResult, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - - } - } - - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc(args) { - const { rows, columns } = { rows: undefined, columns: undefined, ...args }; - return _iloc({ ndFrame: this, rows, columns }); - } - - - /** - * Access a group of rows and columns by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc(args) { - const { rows, columns } = args; - return _loc({ ndFrame: this, rows, columns }); - } - - /** - * Prints DataFrame to console as a formatted grid of row and columns. - */ - toString() { - const maxRow = this.config.getMaxRow; - const maxColToDisplayInConsole = this.config.getTableMaxColInConsole; - - // let data; - const dataArr = []; - const colLen = this.columns.length; - - let header = []; - - if (colLen > maxColToDisplayInConsole) { - //truncate displayed columns to fit in the console - let firstFourcolNames = this.columns.slice(0, 4); - let lastThreecolNames = this.columns.slice(colLen - 4); - //join columns with truncate ellipse in the middle - header = ["", ...firstFourcolNames, "...", ...lastThreecolNames]; - - let subIdx; - let firstHalfValues; - let lastHalfValueS; - - if (this.values.length > maxRow) { - //slice Object to show [max_rows] - let dfSubset1 = this.iloc({ - rows: [`0:${maxRow}`], - columns: ["0:4"] - }); - - let dfSubset2 = this.iloc({ - rows: [`0:${maxRow}`], - columns: [`${colLen - 4}:`] - }); - - subIdx = this.index.slice(0, maxRow); - firstHalfValues = dfSubset1.values; - lastHalfValueS = dfSubset2.values; - - } else { - let dfSubset1 = this.iloc({ columns: ["0:4"] }); - let dfSubset2 = this.iloc({ columns: [`${colLen - 4}:`] }); - - subIdx = this.index.slice(0, maxRow); - firstHalfValues = dfSubset1.values; - lastHalfValueS = dfSubset2.values; - } - - // merge subset - for (let i = 0; i < subIdx.length; i++) { - const idx = subIdx[i]; - const row = [idx, ...firstHalfValues[i], "...", ...lastHalfValueS[i]]; - dataArr.push(row); - } - - } else { - //display all columns - header = ["", ...this.columns]; - let subIdx; - let values; - if (this.values.length > maxRow) { - //slice Object to show a max of [max_rows] - let data = this.iloc({ rows: [`0:${maxRow}`] }); - subIdx = data.index; - values = data.values; - } else { - values = this.values; - subIdx = this.index; - } - - // merge subset - for (let i = 0; i < subIdx.length; i++) { - const idx = subIdx[i]; - const row = [idx, ...values[i]]; - dataArr.push(row); - } - } - - - const columnsConfig = {}; - columnsConfig[0] = { width: 10 }; //set column width for index column - - for (let index = 1; index < header.length; index++) { - columnsConfig[index] = { width: 17, truncate: 16 }; - } - - const tableData = [header, ...dataArr]; //Adds the column names to values before printing - - return table(tableData, { columns: columnsConfig, ...this.config.getTableDisplayConfig }); - } - - /** - * Returns the first n values in a DataFrame - * @param rows The number of rows to return - */ - head(rows = 5) { - if (rows > this.shape[0]) { - throw new Error("ParamError of rows cannot be greater than available rows in data"); - } - if (rows <= 0) { - throw new Error("ParamError of rows cannot be less than 1"); - } - - return this.iloc({ rows: [`0:${rows}`] }); - } - - /** - * Returns the last n values in a DataFrame - * @param rows The number of rows to return - */ - tail(rows = 5) { - if (rows > this.shape[0]) { - throw new Error("ParamError of rows cannot be greater than available rows in data"); - } - if (rows <= 0) { - throw new Error("ParamError of rows cannot be less than 1"); - } - rows = this.shape[0] - rows; - return this.iloc({ rows: [`${rows}:`] }); - } - - /** - * Gets n number of random rows in a dataframe. Sample is reproducible if seed is provided. - * @param num The number of rows to return. Default to 5. - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - async sample(num = 5, options) { - const { seed } = { seed: 1, ...options }; - - if (num > this.shape[0]) { - throw new Error("ParamError: Sample size cannot be bigger than number of rows"); - } - if (num <= 0) { - throw new Error("ParamError: Sample size cannot be less than 1"); - } - - const shuffledIndex = await tfData.array(this.index).shuffle(num, `${seed}`).take(num).toArray(); - const df = this.iloc({ rows: shuffledIndex }); - return df; - } - - /** - * Return Addition of DataFrame and other, element-wise (binary operator add). - * @param other DataFrame, Series, Array or Scalar number to add - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: add operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "add", inplace); - } - - /** - * Return substraction between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to substract from DataFrame - * @param options.axis 0 or 1. If 0, compute the subtraction column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: sub operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "sub", inplace); - - - } - /** - * Return multiplciation between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to multiply with. - * @param options.axis 0 or 1. If 0, compute the multiplication column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mul operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "mul", inplace); - - - } - - /** - * Return division of DataFrame with other. - * @param other DataFrame, Series, Array or Scalar number to divide with. - * @param options.axis 0 or 1. If 0, compute the division column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: div operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "div", inplace); - - - } - - /** - * Return DataFrame raised to the power of other. - * @param other DataFrame, Series, Array or Scalar number to to raise to. - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: pow operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "pow", inplace); - - - } - - /** - * Return modulus between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to modulus with. - * @param options.axis 0 or 1. If 0, compute the mod column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other, options) { - const { inplace, axis } = { inplace: false, axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mod operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$MathOps(tensors, "mod", inplace); - - } - - /** - * Return mean of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mean column-wise, if 1, row-wise. Defaults to 1 - */ - mean(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mean operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const meanArr = newData.map((arr) => arr.reduce((a, b) => a + b, 0) / arr.length); - if (axis === 1) { - return new Series(meanArr, { index: this.columns }); - } else { - return new Series(meanArr, { index: this.index }); - } - } - - /** - * Return median of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the median column-wise, if 1, row-wise. Defaults to 1 - */ - median(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: median operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const medianArr = newData.map((arr) => median(arr)); - if (axis === 1) { - return new Series(medianArr, { index: this.columns }); - } else { - return new Series(medianArr, { index: this.index }); - } - - } - - /** - * Return mode of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mode column-wise, if 1, row-wise. Defaults to 1 - * @param options.keep If there are more than one modes, returns the mode at position [keep]. Defaults to 0 - */ - mode(options) { - const { axis, keep } = { axis: 1, keep: 0, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: mode operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const modeArr = newData.map((arr) => { - const tempMode = mode(arr); - if (tempMode.length === 1) { - return tempMode[0]; - } else { - return tempMode[keep]; - } - }); - if (axis === 1) { - return new Series(modeArr, { index: this.columns }); - } else { - return new Series(modeArr, { index: this.index }); - } - } - - /** - * Return minimum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the minimum value column-wise, if 1, row-wise. Defaults to 1 - */ - min(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: min operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - - const minArr = newData.map((arr) => { - let smallestValue = arr[0]; - for (let i = 0; i < arr.length; i++) { - smallestValue = smallestValue < arr[i] ? smallestValue : arr[i]; - } - return smallestValue; - }); - - if (axis === 1) { - return new Series(minArr, { index: this.columns }); - } else { - return new Series(minArr, { index: this.index }); - } - - } - - /** - * Return maximum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the maximum column-wise, if 1, row-wise. Defaults to 1 - */ - max(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: max operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - - const maxArr = newData.map((arr) => { - let biggestValue = arr[0]; - for (let i = 0; i < arr.length; i++) { - biggestValue = biggestValue > arr[i] ? biggestValue : arr[i]; - } - return biggestValue; - }); - - if (axis === 1) { - return new Series(maxArr, { index: this.columns }); - } else { - return new Series(maxArr, { index: this.index }); - } - - } - - /** - * Return standard deviation of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the standard deviation column-wise, if 1, row-wise. Defaults to 1 - */ - std(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: std operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const stdArr = newData.map((arr) => std(arr)); - - if (axis === 1) { - return new Series(stdArr, { index: this.columns }); - } else { - return new Series(stdArr, { index: this.index }); - } - - } - - /** - * Return variance of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the variance column-wise, if 1, add row-wise. Defaults to 1 - */ - var(options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: var operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const varArr = newData.map((arr) => variance(arr)); - if (axis === 1) { - return new Series(varArr, { index: this.columns }); - } else { - return new Series(varArr, { index: this.index }); - } - } - - /** - * Get Less than of dataframe and other, element-wise (binary operator lt). - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - lt(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: lt operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "lt"); - } - - /** - * Returns "greater than" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - gt(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: gt operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "gt"); - } - - /** - * Returns "equals to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - eq(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: eq operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "eq"); - } - - /** - * Returns "not equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ne(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: ne operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "ne"); - } - - /** - * Returns "less than or equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - le(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: le operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "le"); - } - - /** - * Returns "greater than or equal to" between dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ge(other, options) { - const { axis } = { axis: 1, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: ge operation is not supported for string dtypes"); - } - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); - return this.$logicalOps(tensors, "ge"); - } - - /** - * Return number of non-null elements in a Series - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - count(options) { - const { axis } = { axis: 1, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newData = this.$getDataByAxisWithMissingValuesRemoved(axis); - const countArr = newData.map((arr) => arr.length); - - if (axis === 1) { - return new Series(countArr, { index: this.columns }); - } else { - return new Series(countArr, { index: this.index }); - } - - } - - /** - * Return the sum of values across an axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - sum(options) { - const { axis } = { axis: 1, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const result = this.$getDataByAxisWithMissingValuesRemoved(axis); - const sumArr = result.map((innerArr) => { - return innerArr.reduce((a, b) => Number(a) + Number(b), 0); - }); - if (axis === 1) { - return new Series(sumArr, { - index: [...this.columns] - }); - } else { - return new Series(sumArr, { - index: [...this.index] - }); - } - - } - - /** - * Return the absolute value of elements in a DataFrame. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options) { - const { inplace } = { inplace: false, ...options }; - - const newData = (this.values).map((arr) => arr.map((val) => Math.abs(val))); - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - /** - * Rounds all element in the DataFrame to specified number of decimal places. - * @param dp Number of decimal places to round to. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp = 1, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.$frameIsNotCompactibleForArithmeticOperation()) { - throw Error("TypeError: round operation is not supported for string dtypes"); - } - - if (typeof dp !== "number") { - throw Error("ParamError: dp must be a number"); - } - - const newData = utils.round(this.values, dp, false); - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame( - newData, - { - index: [...this.index], - columns: [...this.columns], - config: { ...this.config } - }); - } - } - - /** - * Returns cumulative product accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumprod(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("prod", axis, inplace); - } - - /** - * Returns cumulative sum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumsum(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("sum", axis, inplace); - } - - /** - * Returns cumulative minimum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummin(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("min", axis, inplace); - } - - /** - * Returns cumulative maximum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummax(options) { - const { axis, inplace } = { axis: 1, inplace: false, ...options }; - return this.cumOps("max", axis, inplace); - } - - /** - * Internal helper function for cumulative operation on DataFrame - */ - cumOps(ops, axis, inplace) { - if (this.dtypes.includes("string")) ErrorThrower.throwStringDtypeOperationError(ops); - - const result = this.$getDataByAxisWithMissingValuesRemoved(axis); - - let newData = result.map((sData) => { - let tempval = sData[0]; - const data = [tempval]; - - for (let i = 1; i < sData.length; i++) { - let currVal = sData[i]; - switch (ops) { - case "max": - if (currVal > tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "min": - if (currVal < tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "sum": - tempval = (tempval) + (currVal); - data.push(tempval); - break; - case "prod": - tempval = (tempval) * (currVal); - data.push(tempval); - break; - - } - } - return data; - }); - - if (axis === 1) { - newData = utils.transposeArray(newData); - } - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - /** - * Generate descriptive statistics for all numeric columns - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - * @returns {Series} - */ - describe() { - const numericColumnNames = this.columns.filter((name) => this.$getColumnDtype(name) !== "string"); - const index = ["count", "mean", "std", "min", "median", "max", "variance"]; - const statsObject = {}; - for (let i = 0; i < numericColumnNames.length; i++) { - const colName = numericColumnNames[i]; - const $count = (this.$getColumnData(colName)).count(); - const $mean = mean(this.$getColumnData(colName, false)); - const $std = std(this.$getColumnData(colName, false)); - const $min = (this.$getColumnData(colName)).min(); - const $median = median(this.$getColumnData(colName, false)); - const $max = (this.$getColumnData(colName)).max(); - const $variance = variance(this.$getColumnData(colName, false)); - - const stats = [$count, $mean, $std, $min, $median, $max, $variance]; - statsObject[colName] = stats; - - } - - const df = new DataFrame(statsObject, { index }); - return df; - } - - /** - * Drops all rows or columns with missing values (NaN) - * @param axis 0 or 1. If 0, drop columns with NaNs, if 1, drop rows with NaNs - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(axis = 1, options) { - const { inplace } = { inplace: false, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error("ParamError: Axis must be 0 or 1"); - } - - const newIndex = []; - - if (axis == 0) { - const newData = []; - - const dfValues = this.values; - for (let i = 0; i < dfValues.length; i++) { - const values = dfValues[i]; - if (!values.includes(NaN) && !values.includes(undefined) && !values.includes(null)) { - newData.push(values); - newIndex.push(this.index[i]); - } - } - - if (inplace) { - this.$setValues(newData, false); - this.$setIndex(newIndex); - } else { - return new DataFrame( - newData, - { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - } else { - const newColumnNames = []; - const newDtypes = []; - let dfValues = []; - - if (this.config.isLowMemoryMode) { - dfValues = utils.transposeArray(this.values); - } else { - dfValues = this.$dataIncolumnFormat; - } - const tempColArr = []; - - for (let i = 0; i < dfValues.length; i++) { - const values = dfValues[i]; - if (!values.includes(NaN)) { - tempColArr.push(values); - newColumnNames.push(this.columns[i]); - newDtypes.push(this.dtypes[i]); - } - } - - const newData = utils.transposeArray(tempColArr); - - if (inplace) { - this.$setValues(newData, false, false); - this.$setColumnNames(newColumnNames); - this.$setDtypes(newDtypes); - } else { - return new DataFrame( - newData, - { - index: [...this.index], - columns: newColumnNames, - dtypes: newDtypes, - config: { ...this.config } - }); - } - } - - } - - /** - * Adds a new column to the DataFrame. If column exists, then the column values is replaced. - * @param column The name of the column to add or replace. - * @param values An array of values to be inserted into the DataFrame. Must be the same length as the columns - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - addColumn(options) { - const { column, values, inplace } = { inplace: false, ...options }; - - if (!column) { - throw new Error("ParamError: column must be specified"); - } - - if (!values) { - throw new Error("ParamError: values must be specified"); - } - - const columnIndex = this.$columns.indexOf(column); - - if (columnIndex === -1) { - let colunmValuesToAdd; - - if (values instanceof Series) { - colunmValuesToAdd = values.values; - } else if (Array.isArray(values)) { - colunmValuesToAdd = values; - } else { - throw new Error("ParamError: specified value not supported. It must either be an Array or a Series of the same length"); - } - - if (colunmValuesToAdd.length !== this.shape[0]) { - ErrorThrower.throwColumnLengthError(this, colunmValuesToAdd.length); - } - - const newData = []; - const oldValues = this.$data; - for (let i = 0; i < oldValues.length; i++) { - const innerArr = [...oldValues[i]]; - innerArr.push(colunmValuesToAdd[i]); - newData.push(innerArr); - } - - if (inplace) { - this.$setValues(newData, true, false); - this.$setColumnNames([...this.columns, column]); - this.$setInternalColumnDataProperty(column); - - } else { - const df = new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns, column], - dtypes: [...this.dtypes, utils.inferDtype(colunmValuesToAdd)[0]], - config: { ...this.$config } - }); - return df; - } - } else { - this.$setColumnData(column, values); - } - - } - - /** - * Makes a new copy of a DataFrame - */ - copy() { - let df = new DataFrame([...this.$data], { - columns: [...this.columns], - index: [...this.index], - dtypes: [...this.dtypes], - config: { ...this.$config } - }); - return df; - } - - /** - * Return a boolean same-sized object indicating where elements are empty (NaN, undefined, null). - * NaN, undefined and null values gets mapped to true, and everything else gets mapped to false. - */ - isna() { - const newData = []; - for (let i = 0; i < this.values.length; i++) { - const valueArr = this.values[i]; - const tempData = valueArr.map((value) => { - if (utils.isEmpty(value)) { - return true; - } else { - return false; - } - }); - newData.push(tempData); - } - - const df = new DataFrame(newData, - { - index: [...this.index], - columns: [...this.columns], - config: { ...this.config } - }); - return df; - } - - /** - * Replace all empty elements with a specified value. Replace params expect columns array to map to values array. - * @param columns The list of column names to be replaced - * @param options.values The list of values to use for replacement. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(values, options) { - let { columns, inplace } = { inplace: false, ...options }; - - if (!values && typeof values !== "boolean") { - throw Error('ParamError: value must be specified'); - } - - if (Array.isArray(values)) { - if (!Array.isArray(columns)) { - throw Error('ParamError: value is an array, hence columns must also be an array of same length'); - } - - if (values.length !== columns.length) { - throw Error('ParamError: specified column and values must have the same length'); - } - - columns.forEach((col) => { - if (!this.columns.includes(col)) { - throw Error( - `ValueError: Specified column "${col}" must be one of ${this.columns}` - ); - } - }); - } - - const newData = []; - const oldValues = [...this.values]; - - if (!columns) { - //Fill all columns - for (let i = 0; i < oldValues.length; i++) { - const valueArr = [...oldValues[i]]; - - const tempArr = valueArr.map((innerVal) => { - if (utils.isEmpty(innerVal)) { - const replaceWith = Array.isArray(values) ? values[i] : values; - return replaceWith; - } else { - return innerVal; - } - }); - newData.push(tempArr); - } - - } else { - //Fill specific columns - const tempData = [...this.values]; - - for (let i = 0; i < tempData.length; i++) { - const valueArr = tempData[i]; - - for (let i = 0; i < columns.length; i++) { //B - const columnIndex = this.columns.indexOf(columns[i]); - const replaceWith = Array.isArray(values) ? values[i] : values; - valueArr[columnIndex] = utils.isEmpty(valueArr[columnIndex]) ? replaceWith : valueArr[columnIndex]; - } - newData.push(valueArr); - } - } - - if (inplace) { - this.$setValues(newData); - } else { - const df = new DataFrame(newData, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - } - - /** - * Drop columns or rows with missing values. Missing values are NaN, undefined or null. - * @param options.columns Array of column names to drop - * @param options.index Array of index to drop - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop(options) { - let { columns, index, inplace } = { inplace: false, ...options }; - - if (!columns && !index) { - throw Error('ParamError: Must specify one of columns or index'); - } - - if (columns && index) { - throw Error('ParamError: Can only specify one of columns or index'); - } - - if (columns) { - const columnIndices = []; - - if (typeof columns === "string") { - columnIndices.push(this.columns.indexOf(columns)); - } else if (Array.isArray(columns)) { - for (let column of columns) { - if (this.columns.indexOf(column) === -1) { - throw Error(`ParamError: specified column "${column}" not found in columns`); - } - columnIndices.push(this.columns.indexOf(column)); - } - - } else { - throw Error('ParamError: columns must be an array of column names or a string of column name'); - } - - let newRowData = []; - let newColumnNames = []; - let newDtypes = []; - - for (let i = 0; i < this.values.length; i++) { - const tempInnerArr = []; - const innerArr = this.values[i]; - for (let j = 0; j < innerArr.length; j++) { - if (!(columnIndices.includes(j))) { - tempInnerArr.push(innerArr[j]); - } - } - newRowData.push(tempInnerArr); - } - - for (let i = 0; i < this.columns.length; i++) { - const element = this.columns[i]; - if (!(columns.includes(element))) { - newColumnNames.push(element); - newDtypes.push(this.dtypes[i]); - } - } - - if (inplace) { - this.$setValues(newRowData, true, false); - this.$setColumnNames(newColumnNames); - } else { - const df = new DataFrame(newRowData, - { - index: [...this.index], - columns: newColumnNames, - dtypes: newDtypes, - config: { ...this.config } - }); - return df; - } - - } - - if (index) { - const rowIndices = []; - - if (typeof index === "string" || typeof index === "number" || typeof index === "boolean") { - rowIndices.push(this.index.indexOf(index)); - } else if (Array.isArray(index)) { - for (let indx of index) { - if (this.index.indexOf(indx) === -1) { - throw Error(`ParamError: specified index "${indx}" not found in indices`); - } - rowIndices.push(this.index.indexOf(indx)); - } - } else { - throw Error('ParamError: index must be an array of indices or a scalar index'); - } - - let newRowData = []; - let newIndex = []; - - for (let i = 0; i < this.values.length; i++) { - const innerArr = this.values[i]; - if (!(rowIndices.includes(i))) { - newRowData.push(innerArr); - } - } - - for (let i = 0; i < this.index.length; i++) { - const indx = this.index[i]; - if (!(index.includes(indx))) { - newIndex.push(indx); - } - } - - if (inplace) { - this.$setValues(newRowData, false); - this.$setIndex(newIndex); - } else { - const df = new DataFrame(newRowData, - { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - } - - } - - /** - * Sorts a Dataframe by a specified column values - * @param options.column Column name to sort by - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options) { - const { by, ascending, inplace } = { by: undefined, ascending: true, inplace: false, ...options }; - - if (!by) { - throw Error(`ParamError: must specify a column to sort by`); - } - - if (this.columns.indexOf(by) === -1) { - throw Error(`ParamError: specified column "${by}" not found in columns`); - } - - const columnValues = this.$getColumnData(by, false); - const index = [...this.index]; - - const objToSort = columnValues.map((value, i) => { - return { index: index[i], value }; - }); - - const sortedObjectArr = utils.sortObj(objToSort, ascending); - const sortedIndex = sortedObjectArr.map((obj) => obj.index); - - const newDf = _loc({ ndFrame: this, rows: sortedIndex }); - - if (inplace) { - this.$setValues(newDf.values); - this.$setIndex(newDf.index); - } else { - return newDf; - } - - } - - /** - * Sets the index of the DataFrame to the specified index. - * @param options.index An array of index values to set - * @param options.column A column name to set the index to - * @param options.drop Whether to drop the column whose index was set. Defaults to false - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options) { - const { index, column, drop, inplace } = { drop: false, inplace: false, ...options }; - - if (!index && !column) { - throw new Error("ParamError: must specify either index or column"); - } - - let newIndex = []; - - if (index) { - if (!Array.isArray(index)) { - throw Error(`ParamError: index must be an array`); - } - - if (index.length !== this.values.length) { - throw Error(`ParamError: index must be the same length as the number of rows`); - } - newIndex = index; - } - - if (column) { - if (this.columns.indexOf(column) === -1) { - throw Error(`ParamError: column not found in column names`); - } - - newIndex = this.$getColumnData(column, false); - } - - if (drop) { - const dfDropped = this.drop({ columns: [column] }); - - const newData = dfDropped.values; - const newColumns = dfDropped.columns; - const newDtypes = dfDropped.dtypes; - - if (inplace) { - this.$setValues(newData, true, false); - this.$setIndex(newIndex); - this.$setColumnNames(newColumns); - } else { - const df = new DataFrame(newData, - { - index: newIndex, - columns: newColumns, - dtypes: newDtypes, - config: { ...this.config } - }); - return df; - } - } else { - if (inplace) { - this.$setIndex(newIndex); - } else { - const df = new DataFrame(this.values, - { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - } - - } - - /** - * Resets the index of the DataFrame to the default index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - reset_index(options) { - const { inplace } = { inplace: false, ...options }; - - if (inplace) { - this.$resetIndex(); - } else { - const df = new DataFrame(this.values, - { - index: this.index.map((_, i) => i), - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return df; - } - - } - - /** - * Apply a function along an axis of the DataFrame. To apply a function element-wise, use `applyMap`. - * Objects passed to the function are Series values whose - * index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1) - * @param callable Function to apply to each column or row - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - */ - apply(callable, options) { - const { axis } = { axis: 1, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error(`ParamError: axis must be 0 or 1`); - } - - const valuesForFunc = this.$getDataByAxisWithMissingValuesRemoved(axis); - - const result = valuesForFunc.map((row) => { - return callable(row); - }); - - if (axis === 1) { - if (utils.is1DArray(result)) { - return new Series(result, { - index: [...this.columns] - }); - } else { - return new DataFrame(result, { - index: [...this.columns], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } else { - if (utils.is1DArray(result)) { - return new Series(result, { - index: [...this.index] - }); - } else { - return new DataFrame(result, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - } - - /** - * Apply a function to a Dataframe values element-wise. - * @param callable Function to apply to each column or row - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply_map(callable, options) { - const { inplace } = { inplace: false, ...options }; - - const newData = this.values.map((row) => { - const tempData = row.map((val) => { - return callable(val); - }); - return tempData; - }); - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, - { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - /** - * Returns the specified column data as a Series object. - * @param column The name of the column to return - */ - column(column) { - return this.$getColumnData(column); - } - - /** - * Return a subset of the DataFrame’s columns based on the column dtypes. - * @param include An array of dtypes or strings to be included. - */ - select_dtypes(include) { - const supportedDtypes = ["float32", "int32", "string", "boolean", 'undefined']; - - if (Array.isArray(include) === false) { - throw Error(`ParamError: include must be an array`); - } - - include.forEach((dtype) => { - if (supportedDtypes.indexOf(dtype) === -1) { - throw Error(`ParamError: include must be an array of valid dtypes`); - } - }); - const newColumnNames = []; - - for (let i = 0; i < this.dtypes.length; i++) { - if (include.includes(this.dtypes[i])) { - newColumnNames.push(this.columns[i]); - } - } - return this.loc({ columns: newColumnNames }); - - } - - /** - * Returns the transposes the DataFrame. - **/ - transpose(options) { - const { inplace } = { inplace: false, ...options }; - const newData = utils.transposeArray(this.values); - const newColNames = [...this.index.map((i) => i.toString())]; - - if (inplace) { - this.$setValues(newData, false, false); - this.$setIndex([...this.columns]); - this.$setColumnNames(newColNames); - } else { - return new DataFrame(newData, { - index: [...this.columns], - columns: newColNames, - config: { ...this.config } - }); - } - } - - /** - * Returns the Transpose of the DataFrame. Similar to `transpose`, but does not change the original DataFrame. - **/ - get T() { - const newData = utils.transposeArray(this.values); - return new DataFrame(newData, { - index: [...this.columns], - columns: [...this.index.map((i) => i.toString())], - config: { ...this.config } - }); - } - - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.columns An array of column names you want to replace. If not provided replace accross all columns. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace( - oldValue, - newValue, - options - ) { - const { columns, inplace } = { inplace: false, ...options }; - - if (!oldValue && typeof oldValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'oldValue' to replace`); - } - - if (!newValue && typeof newValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'newValue' to replace with`); - } - - let newData = []; - - if (columns) { - if (!Array.isArray(columns)) { - throw Error(`Params Error: column must be an array of column(s)`); - } - const columnIndex = []; - - columns.forEach((column) => { - const _indx = this.columns.indexOf(column); - if (_indx === -1) { - throw Error(`Params Error: column not found in columns`); - } - columnIndex.push(_indx); - }); - - newData = (this.values).map(([...row]) => { - for (const colIndx of columnIndex) { - if (row[colIndx] === oldValue) { - row[colIndx] = newValue; - } - } - return row; - }); - } else { - newData = (this.values).map(([...row]) => { - return row.map(((cell) => { - if (cell === oldValue) { - return newValue; - } else { - return cell; - } - })); - }); - } - - if (inplace) { - this.$setValues(newData); - } else { - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - - /** - * Cast the values of a column to specified data type - * @param column The name of the column to cast - * @param dtype Data type to cast to. One of [float32, int32, string, boolean] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(options) { - const { inplace, column, dtype } = { inplace: false, ...options }; - const columnIndex = this.columns.indexOf(column); - - if (columnIndex === -1) { - throw Error(`Params Error: column not found in columns`); - } - - if (!(DATA_TYPES.includes(dtype))) { - throw Error(`dtype ${dtype} not supported. dtype must be one of ${DATA_TYPES}`); - } - - const data = this.values; - - const newData = data.map((row) => { - if (dtype === "float32") { - row[columnIndex] = Number(row[columnIndex]); - return row; - } else if (dtype === "int32") { - row[columnIndex] = parseInt(row[columnIndex]); - return row; - } else if (dtype === "string") { - row[columnIndex] = row[columnIndex].toString(); - return row; - } else if (dtype === "boolean") { - row[columnIndex] = Boolean(row[columnIndex]); - return row; - } - }); - - if (inplace) { - this.$setValues(newData); - } else { - const newDtypes = [...this.dtypes]; - newDtypes[columnIndex] = dtype; - - return new DataFrame(newData, { - index: [...this.index], - columns: [...this.columns], - dtypes: newDtypes, - config: { ...this.config } - }); - } - } - - /** - * Return the number of unique elements in a across the specified axis. - * To get the values use `.unique()` instead. - * @param axis The axis to count unique elements across. Defaults to 1 - */ - nunique(axis = 1) { - if ([0, 1].indexOf(axis) === -1) { - throw Error(`ParamError: axis must be 0 or 1`); - } - const data = this.$getDataArraysByAxis(axis); - const newData = data.map((row) => new Set(row).size); - - if (axis === 0) { - return new Series(newData, { - index: [...this.columns], - dtypes: ["int32"] - }); - } else { - return new Series(newData, { - index: [...this.index], - dtypes: ["int32"] - }); - } - } - - /** - * Renames a column or index. - * @param mapper An object that maps each column or index in the DataFrame to a new value - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.axis The axis to perform the operation on. Defaults to 1 - */ - rename(options) { - const { mapper, axis, inplace } = { axis: 1, inplace: false, ...options }; - - if ([0, 1].indexOf(axis) === -1) { - throw Error(`ParamError: axis must be 0 or 1`); - } - - if (axis === 1) { - const colsAdded = []; - const newColumns = this.columns.map((col) => { - if (mapper[col] !== undefined) { - colsAdded.push(mapper[col]); - return mapper[col]; - } else { - return col; - } - }); - - if (inplace) { - this.$setColumnNames(newColumns); - for (const col of colsAdded) { - this.$setInternalColumnDataProperty(col); - } - } else { - return new DataFrame([...this.values], { - index: [...this.index], - columns: newColumns, - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } else { - const newIndex = this.index.map((col) => { - if (mapper[col] !== undefined) { - return mapper[col]; - } else { - return col; - } - }); - - if (inplace) { - this.$setIndex(newIndex); - } else { - return new DataFrame([...this.values], { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - } - - } - - /** - * Sorts the Dataframe by the index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - */ - sort_index(options) { - const { ascending, inplace } = { ascending: true, inplace: false, ...options }; - - const indexPosition = utils.range(0, this.index.length - 1); - const index = [...this.index]; - - const objToSort = index.map((idx, i) => { - return { index: indexPosition[i], value: idx }; - }); - - const sortedObjectArr = utils.sortObj(objToSort, ascending); - let sortedIndex = sortedObjectArr.map((obj) => obj.index); - const newData = sortedIndex.map((i) => (this.values)[i]); - sortedIndex = sortedIndex.map((i) => index[i]); - - if (inplace) { - this.$setValues(newData); - this.$setIndex(sortedIndex); - } else { - return new DataFrame(newData, { - index: sortedIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - } - - /** - * Add new rows to the end of the DataFrame. - * @param newValues Array, Series or DataFrame to append to the DataFrame - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append( - newValues, - index, - options - ) { - const { inplace } = { inplace: false, ...options }; - - if (!newValues) { - throw Error(`ParamError: newValues must be a Series, DataFrame or Array`); - } - - if (!index) { - throw Error(`ParamError: index must be specified`); - } - - let rowsToAdd = []; - if (newValues instanceof Series) { - - if (newValues.values.length !== this.shape[1]) { - throw Error(`ValueError: length of newValues must be the same as the number of columns.`); - } - rowsToAdd = [newValues.values]; - - } else if (newValues instanceof DataFrame) { - - if (newValues.shape[1] !== this.shape[1]) { - throw Error(`ValueError: length of newValues must be the same as the number of columns.`); - } - rowsToAdd = newValues.values; - - } else if (Array.isArray(newValues)) { - - if (utils.is1DArray(newValues)) { - rowsToAdd = [newValues]; - } else { - rowsToAdd = newValues; - } - - if ((rowsToAdd[0]).length !== this.shape[1]) { - throw Error(`ValueError: length of newValues must be the same as the number of columns.`); - } - - } else { - throw Error(`ValueError: newValues must be a Series, DataFrame or Array`); - } - - - let indexInArrFormat = []; - if (!Array.isArray(index)) { - indexInArrFormat = [index]; - } else { - indexInArrFormat = index; - } - - if (rowsToAdd.length !== indexInArrFormat.length) { - throw Error(`ParamError: index must contain the same number of values as newValues`); - } - - const newData = [...this.values]; - const newIndex = [...this.index]; - - rowsToAdd.forEach((row, i) => { - newData.push(row); - newIndex.push(indexInArrFormat[i]); - }); - - if (inplace) { - this.$setValues(newData); - this.$setIndex(newIndex); - } else { - return new DataFrame(newData, { - index: newIndex, - columns: [...this.columns], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - } - - } - - /** - * Queries the DataFrame for rows that meet the boolean criteria. - * @param options - * - `column` A column name to query with. - * - `is` A logical operator. Can be one of the following: [">", "<", "<=", ">=", "==", "!="] - * - `to` A value to query with. - * - `condition` An array of boolean mask, one for each row in the DataFrame. Rows where the value are true will be returned. - * If specified, then other parameters are ignored. - * - `inplace` Boolean indicating whether to perform the operation inplace or not. Defaults to false - **/ - query(options) { - const { inplace, condition, column, is, to } = { inplace: false, ...options }; - - if (condition) { - const result = _iloc({ - ndFrame: this, - rows: condition - }); - - if (inplace) { - this.$setValues(result.values, false, false); - this.$setIndex(result.index); - return; - } else { - return result; - } - - } - - const operators = [">", "<", "<=", ">=", "==", "!="]; - - let columnIndex, operator, value; - - if (column) { - if (this.columns.includes(column)) { - columnIndex = this.columns.indexOf(column); - } else { - throw new Error(`ParamError: column ${column} not found in column names`); - } - } else { - throw new Error(`ParamError: specify a column name to query`); - } - - if (is) { - if (operators.includes(is)) { - operator = is; - } else { - throw new Error(`ParamError: specified operato ${is} is not a supported. operator must be one of ${operators}`); - } - } else { - throw new Error(`ParamError: specify an operator to apply. operator must be one of ${operators}`); - } - - if (to) { - value = to; - } else { - throw new Error("ParamError: specify a value to query by"); - } - - let data = this.values; - let index = this.index; - let newData = []; - let newIndex = []; - - for (var i = 0; i < data.length; i++) { - let dataValue = data[i]; - let elem = dataValue[columnIndex]; - //use eval function for easy operation - //eval() takes in a string expression e.g eval('2>5') - if (eval(`elem${operator}value`)) { - newData.push(dataValue); - newIndex.push(index[i]); - } - } - - if (inplace) { - this.$setValues(newData, false, false); - this.$setIndex(newIndex); - return; - } else { - return new DataFrame(newData, { - index: newIndex, - columns: this.columns, - config: { ...this.config } - }); - } - } - - /** - * Returns the data types for each column as a Series. - */ - get ctypes() { - return new Series(this.dtypes, { index: this.columns }); - } - - /** - * One-hot encode specified columns in the DataFrame. If columns are not specified, all columns of dtype string will be encoded. - * @param options Options for the operation. The following options are available: - * - `columns`: A single column name or an array of column names to encode. Defaults to all columns of dtype string. - * - `prefix`: Prefix to add to the column names. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * - `inplace` indicating whether to perform the operation inplace or not. Defaults to false - * @returns A DataFrame with the one-hot encoded columns. - * @example - * df.getDummies({ columns: ['a', 'b'] }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-', inplace: true }) - * df.getDummies({ columns: ['a', 'b'], prefix: ['col1', 'col2'], prefixSeparator: '-', inplace: true }) - */ - get_dummies(options) { - const { inplace } = { inplace: false, ...options }; - - const encodedDF = dummyEncode(this, options); - if (inplace) { - this.$setValues(encodedDF.values, false, false); - this.$setColumnNames(encodedDF.columns); - } else { - return encodedDF; - } - - } - - /** - * - * @param {col} col is a list of columns - */ - groupby(col) { - const len = this.shape[0]; - const columns = this.columns; - const col_index = col.map((val) => columns.indexOf(val)); - const col_dtype = this.dtypes.filter((val, index) => { - return col_index.includes(index); - }); - - const self = this; - const data = col.map( - (column_name) => { - if (!(columns.includes(column_name))) - throw new Error(`column ${column_name} does not exist`); - const column_data = self.column(column_name).values; - return column_data; - } - ); - - const unique_columns = data.map((column_data) => utils.unique(column_data)); - - function getRecursiveDict(uniq_columns) { - const first_uniq_columns = uniq_columns[0]; - const remaining_columns = uniq_columns.slice(1); - const c_dict = {}; - if (!remaining_columns.length) - first_uniq_columns.forEach((col_value) => c_dict[col_value] = []); - else - first_uniq_columns.forEach((col_value) => c_dict[col_value] = getRecursiveDict(remaining_columns)); - return c_dict; - } - const col_dict = getRecursiveDict(unique_columns); - - return new GroupBy( - col_dict, - col, - this.values, - columns, - col_dtype - ).group(); - } - -} diff --git a/danfojs-node/src/core/generic.js b/danfojs-node/src/core/generic.js deleted file mode 100644 index d90952cb..00000000 --- a/danfojs-node/src/core/generic.js +++ /dev/null @@ -1,451 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -import { utils } from "../shared/utils"; -import Configs from "../shared/config"; -import ErrorThrower from '../shared/errors'; -import { BASE_CONFIG, DATA_TYPES } from '../shared/defaults'; -import { toCSV, toJSON, toExcel } from "../io"; -import { Tensor, tensor1d, tensor2d } from "@tensorflow/tfjs-node"; - -// const utils = new Utils(); - -/** - * N-Dimension data structure. Stores multi-dimensional - * data in a size-mutable, labeled data structure. Analogous to the Python Pandas DataFrame. - * - * @param Object - * - * data: 1D or 2D Array, JSON, Tensor, Block of data. - * - * index: Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * - * columns: Array of column names. If not specified, column names are auto generated. - * - * dtypes: Array of data types for each the column. If not specified, dtypes inferred. - * - * config: General configuration object for NDframe - * - * @returns NDframe - */ -export default class NDframe { - - constructor({ data, index, columns, dtypes, config, isSeries }) { - this.$isSeries = isSeries; - if (config) { - this.$config = new Configs({ ...BASE_CONFIG, ...config }); - } else { - this.$config = new Configs(BASE_CONFIG); - } - - if (data instanceof Tensor) { - data = data.arraySync(); - } - - if (data === undefined || (Array.isArray(data) && data.length === 0)) { - this.loadArrayIntoNdframe({ data: [], index: [], columns: [], dtypes: [] }); - } else if (utils.is1DArray(data)) { - this.loadArrayIntoNdframe({ data, index, columns, dtypes }); - } else { - - if (Array.isArray(data) && utils.isObject(data[0])) { - this.loadObjectIntoNdframe({ data, type: 1, index, columns, dtypes }); - - } else if (utils.isObject(data)) { - this.loadObjectIntoNdframe({ data, type: 2, index, columns, dtypes }); - - } else if ( - Array.isArray((data)[0]) || - utils.isNumber((data)[0]) || - utils.isString((data)[0]) - ) { - this.loadArrayIntoNdframe({ data, index, columns, dtypes }); - } else { - throw new Error("File format not supported!"); - } - } - } - - /** - * Internal function to load array of data into NDFrame - * @param data The array of data to load into NDFrame - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - loadArrayIntoNdframe({ data, index, columns, dtypes }){ - // this.$data = utils.replaceUndefinedWithNaN(data, this.$isSeries); - this.$data = data; - if (!this.$config.isLowMemoryMode) { - //In NOT low memory mode, we transpose the array and save in column format. - //This makes column data retrieval run in constant time - this.$dataIncolumnFormat = utils.transposeArray(data); - } - this.$setIndex(index); - this.$setDtypes(dtypes); - this.$setColumnNames(columns); - } - - /** - * Internal function to format and load a Javascript object or object of arrays into NDFrame. - * @param data Object or object of arrays. - * @param type The type of the object. There are two recognized types: - * - * - type 1 object are in JSON format `[{a: 1, b: 2}, {a: 30, b: 20}]`. - * - * - type 2 object are of the form `{a: [1,2,3,4], b: [30,20, 30, 20}]}` - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - loadObjectIntoNdframe({ data, type, index, columns, dtypes }){ - if (type === 1 && Array.isArray(data)) { - const _data = (data).map((item) => { - return Object.values(item); - }); - - let _columnNames; - - if (columns) { - _columnNames = columns; - } else { - _columnNames = Object.keys((data)[0]); - } - - this.loadArrayIntoNdframe({ data: _data, index, columns: _columnNames, dtypes }); - - } else { - const [_data, _colNames] = utils.getRowAndColValues(data); - let _columnNames; - - if (columns) { - _columnNames = columns; - } else { - _columnNames = _colNames; - } - this.loadArrayIntoNdframe({ data: _data, index, columns: _columnNames, dtypes }); - } - } - - /** - * Converts and returns the data in the NDframe as a Tensorflow.js Tensor. - */ - get tensor() { - if (this.$isSeries) { - return tensor1d(this.$data); - } else { - return tensor2d(this.$data); - } - } - - /** - * Returns the dtypes of the columns - */ - get dtypes() { - return this.$dtypes; - } - - /** - * Internal function to set the Dtypes of the NDFrame from an array. This function - * performs the necessary checks. - */ - $setDtypes(dtypes){ - if (this.$isSeries) { - if (dtypes) { - if (this.$data.length != 0 && dtypes.length != 1) { - ErrorThrower.throwDtypesLengthError(this, dtypes); - } - - if (!(DATA_TYPES.includes(`${dtypes[0]}`))) { - ErrorThrower.throwDtypeNotSupportedError(dtypes[0]); - } - - this.$dtypes = dtypes; - } else { - this.$dtypes = utils.inferDtype(this.$data); - } - - } else { - if (dtypes) { - if (this.$data.length != 0 && dtypes.length != this.shape[1]) { - ErrorThrower.throwDtypesLengthError(this, dtypes); - } - - if (this.$data.length == 0 && dtypes.length == 0) { - this.$dtypes = dtypes; - } else { - dtypes.forEach((dtype) => { - if (!(DATA_TYPES.includes(dtype))) { - ErrorThrower.throwDtypeNotSupportedError(dtype); - } - }); - - this.$dtypes = dtypes; - - } - - } else { - this.$dtypes = utils.inferDtype(this.$data); - } - } - } - - /** - * Returns the dimension of the data. Series have a dimension of 1, - * while DataFrames have a dimension of 2. - */ - get ndim() { - if (this.$isSeries) { - return 1; - } else { - return 2; - } - } - - /** - * Returns the axis labels of the NDFrame. - */ - get axis() { - return { - index: this.$index, - columns: this.$columns - }; - } - - /** - * Returns the configuration object of the NDFrame. - */ - get config() { - return this.$config; - - } - - /** - * Internal function to set the configuration of the ndframe - */ - $setConfig(config){ - this.$config = config; - } - - /** - * Returns the indices of the NDFrame - */ - get index() { - return this.$index; - - } - - /** - * Internal function to set the index of the NDFrame with the specified - * array of indices. Performs all necessary checks to ensure that the - * index is valid. - */ - $setIndex(index){ - if (index) { - - if (this.$data.length != 0 && index.length != this.shape[0]) { - ErrorThrower.throwIndexLengthError(this, index); - } - if (Array.from(new Set(index)).length !== this.shape[0]) { - ErrorThrower.throwIndexDuplicateError(); - } - - this.$index = index; - } else { - this.$index = utils.range(0, this.shape[0] - 1); //generate index - } - } - - /** - * Internal function to reset the index of the NDFrame using a range of indices. - */ - $resetIndex(){ - this.$index = utils.range(0, this.shape[0] - 1); - } - - /** - * Returns the column names of the NDFrame - */ - get columns() { - return this.$columns; - } - - /** - * Internal function to set the column names for the NDFrame. This function - * performs a check to ensure that the column names are unique, and same length as the - * number of columns in the data. - */ - $setColumnNames(columns) { - - if (this.$isSeries) { - if (columns) { - if (this.$data.length != 0 && columns.length != 1 && typeof columns != 'string') { - ErrorThrower.throwColumnNamesLengthError(this, columns); - } - this.$columns = columns; - } else { - this.$columns = ["0"]; - } - } else { - if (columns) { - - if (this.$data.length != 0 && columns.length != this.shape[1]) { - - ErrorThrower.throwColumnNamesLengthError(this, columns); - } - if (Array.from(new Set(columns)).length !== this.shape[1]) { - ErrorThrower.throwColumnDuplicateError(); - } - - this.$columns = columns; - } else { - this.$columns = (utils.range(0, this.shape[1] - 1)).map((val) => `${val}`); //generate columns - } - } - } - - /** - * Returns the shape of the NDFrame. Shape is determined by [row lenght, column length] - */ - get shape() { - if (this.$data.length === 0) return [0, 0]; - if (this.$isSeries) { - return [this.$data.length, 1]; - } else { - const rowLen = (this.$data).length; - const colLen = (this.$data[0]).length; - return [rowLen, colLen]; - } - - } - - /** - * Returns the underlying data in Array format. - */ - get values() { - return this.$data; - } - - /** - * Updates the internal $data property to the specified value - * @param values An array of values to set - * @param checkLength Whether to check the length of the new values and the existing row length - * @param checkColumnLength Whether to check the length of the new values and the existing column length - * */ - $setValues(values, checkLength = true, checkColumnLength = true){ - if (this.$isSeries) { - if (checkLength && values.length != this.shape[0]) { - ErrorThrower.throwRowLengthError(this, values.length); - } - - this.$data = values; - this.$dtypes = utils.inferDtype(values); //Dtype may change depeneding on the value set - - if (!this.$config.isLowMemoryMode) { - this.$dataIncolumnFormat = values; - } - - } else { - if (checkLength && values.length != this.shape[0]) { - ErrorThrower.throwRowLengthError(this, values.length); - } - - if (checkColumnLength) { - values.forEach((value) => { - if ((value).length != this.shape[1]) { - ErrorThrower.throwColumnLengthError(this, values.length); - } - }); - } - - this.$data = values; - this.$dtypes = utils.inferDtype(values); - - if (!this.$config.isLowMemoryMode) { - this.$dataIncolumnFormat = utils.transposeArray(values); - } - - } - - } - - /** - * Returns the underlying data in Array column format. - */ - get getColumnData() { - if (this.config.isLowMemoryMode) { - return utils.transposeArray(this.values); - } else { - return this.$dataIncolumnFormat; - } - } - - /** - * Returns the size of the NDFrame object - * - */ - get size() { - return this.shape[0] * this.shape[1]; - } - - /** - * Converts a DataFrame or Series to CSV. - * @param options Configuration object. Supports the following options: - * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - */ - to_csv(options) { - return toCSV(this, options); - } - - /** - * Converts a DataFrame or Series to JSON. - * @param options Configuration object. Supported options: - * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - */ - to_json(options) { - return toJSON(this, options); - } - - - /** - * Converts a DataFrame or Series to Excel Sheet. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. - */ - to_excel(options){ - return toExcel(this, options); - } - - /** - * Pretty prints a DataFrame or Series to the console - */ - print() { - console.log(this + ""); - } -} diff --git a/danfojs-node/src/core/get_dummies.js b/danfojs-node/src/core/get_dummies.js deleted file mode 100644 index 6e119924..00000000 --- a/danfojs-node/src/core/get_dummies.js +++ /dev/null @@ -1,149 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import DataFrame from "./frame"; -import Series from "./series"; -import { utils } from "../shared/utils"; - - -/** - * Generate one-hot encoding for categorical columns in an Array, Series or Dataframe. - * @param data Series or Dataframe - * @param columns Columns to encode - * @param prefix Prefix for the new columns - * @param prefixSeparator Separator for the prefix and the column name - * @returns Encoded Dataframe - * @example - * import { DataFrame, DummyEncoder }from 'danfojs'; - * const df = new DataFrame([[1,2,3], [4,5,6]], { columns: ['a', 'b', 'c'] }); - * const df2 = new DummyEncoder({data: df, columns: ['a', 'b'], prefix: 'enc', prefixSeparator: '#'}).encode(); - * df2.print(); - */ -function dummyEncode(data, options) { - let { columns, prefix, prefixSeparator } = { prefixSeparator: "_", ...options }; - - if (!data) { - throw new Error('ParamError: data must be one of Array, Series or DataFrame'); - } - - if (data instanceof Series || data instanceof DataFrame) { - if (!columns) { - const colsWithStringDtype = []; - data.dtypes.forEach((dtype, index) => { - if (dtype === "string") { - colsWithStringDtype.push(data.columns[index]); - } - }); - columns = colsWithStringDtype; - } - } else { - throw new Error('ParamError: data must be one of Array, Series or DataFrame'); - } - - - if (typeof columns === "string") { - columns = [columns]; - if (Array.isArray(prefix) && prefix.length === 1) { - prefix = prefix; - } else if (typeof prefix === "string") { - prefix = [prefix]; - } else { - throw new Error('ParamError: prefix must be a string, or an array of same length as columns'); - } - - if (Array.isArray(prefixSeparator) && prefixSeparator.length === 1) { - prefixSeparator = prefixSeparator; - } else if (typeof prefixSeparator === "string") { - prefixSeparator = [prefixSeparator]; - } else { - throw new Error('ParamError: prefix must be a string, or an array of same length as columns'); - } - } else if (Array.isArray(columns)) { - if (prefix) { - if (Array.isArray(prefix) && prefix.length !== columns.length) { - throw new Error(`ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "${prefix}"}`); - } - - if (typeof prefix === "string") { - prefix = columns.map((_) => prefix); - } - } - - if (prefixSeparator) { - if (Array.isArray(prefixSeparator) && prefixSeparator.length !== columns.length) { - throw new Error(`ParamError: prefixSeparator and data array must be of the same length. If you need to use the same prefix separator, then pass a string param instead. e.g {prefixSeparator: "${prefixSeparator}"}`); - } - - if (typeof prefixSeparator === "string") { - prefixSeparator = columns.map((_) => prefixSeparator); - } - } - - } else { - throw new Error('ParamError: columns must be a string or an array of strings'); - } - - if (data instanceof Series) { - const colData = data.values; - const newColumnNames = []; - const uniqueValues = Array.from(new Set(colData)); - const oneHotArr = utils.zeros(colData.length, uniqueValues.length); - - for (let i = 0; i < colData.length; i++) { - const index = uniqueValues.indexOf(colData[i]); - oneHotArr[i][index] = 1; - } - - for (let i = 0; i < uniqueValues.length; i++) { - const prefixToAdd = prefix ? prefix[0] : i; - newColumnNames.push(`${prefixToAdd}${prefixSeparator[0]}${uniqueValues[i]}`); - - } - - return new DataFrame(oneHotArr, { columns: newColumnNames }); - - } else { - const dfWithSelectedColumnsDropped = data.drop({ columns }); - let newData = dfWithSelectedColumnsDropped.values; - const newColumnNames = dfWithSelectedColumnsDropped.columns; - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - const colData = data.column(column).values; - - const uniqueValues = Array.from(new Set(colData)); - const oneHotArr = utils.zeros(colData.length, uniqueValues.length); - - for (let j = 0; j < colData.length; j++) { - const index = uniqueValues.indexOf(colData[j]); - oneHotArr[j][index] = 1; - const prefixToAdd = prefix ? prefix[i] : column; - const newColName = `${prefixToAdd}${prefixSeparator[i]}${colData[j]}`; - if (!newColumnNames.includes(newColName)) { - newColumnNames.push(newColName); - } - } - - for (let k = 0; k < newData.length; k++) { - newData[k] = [...newData[k], ...oneHotArr[k]]; - - } - - } - - return new DataFrame(newData, { columns: newColumnNames }); - } - -} - -export default dummyEncode; diff --git a/danfojs-node/src/core/groupby.js b/danfojs-node/src/core/groupby.js deleted file mode 100644 index 2718319c..00000000 --- a/danfojs-node/src/core/groupby.js +++ /dev/null @@ -1,349 +0,0 @@ -import DataFrame from "./frame"; -import { utils } from "../shared/utils"; -import Series from "./series"; -import { concat } from "./concat"; - -/** - * The class performs all groupby operation on a dataframe - * involveing all aggregate funciton - * @param {col_dict} col_dict Object of unique keys in the group by column - * @param {key_col} key_col Array contains the column names - * @param {data} Array the dataframe data - * @param {column_name} Array of all column name in the dataframe. - */ -export class GroupBy { - constructor(col_dict, key_col, data, column_name, col_dtype) { - - this.key_col = key_col; - this.col_dict = col_dict; - this.data = data; - this.column_name = column_name; - this.data_tensors = {}; //store the tensor version of the groupby data - this.col_dtype = col_dtype; - - } - - /** - * Group the dataframe by the column by - * creating an object to store the grouping - * @returns Groupby data structure - */ - group(){ - for (const value of this.data){ - const col_indexes = this.key_col.map((key) => this.column_name.indexOf(key)); - const col_values = col_indexes.map((idx) => value[idx]); - - let sub_col_dict = this.col_dict; - for (const col_value of col_values){ - if (!(col_value in sub_col_dict)) - break; - if (col_value === col_values[col_values.length - 1]) - sub_col_dict[col_value].push(value); - else - sub_col_dict = sub_col_dict[col_value]; - } - } - - const self = this; - function dfs(sub_col_dict, sub_data_tensors){ - for (const [ key, value ] of Object.entries(sub_col_dict)){ - if (Array.isArray(value)) { - if (value.length === 0) - delete sub_col_dict[key]; - else - sub_data_tensors[key] = new DataFrame(value, { columns:self.column_name }); - } else { - if (!(key in sub_data_tensors)) - sub_data_tensors[key] = {}; - dfs(value, sub_data_tensors[key]); - } - } - } - dfs(this.col_dict, this.data_tensors); - - return this; - } - - /** - * obtain the column for each group - * @param {col_name} col_name [Array]--> array of column names - * @return Groupby data structure - */ - col(col_names){ - this.selected_column = col_names; // store col_names for use later in .apply - if (Array.isArray(col_names)){ - - for (let i = 0; i < col_names.length; i++){ - - let col_name = col_names[i]; - if (!this.column_name.includes(col_name)){ - throw new Error(`Column ${col_name} does not exist in groups`); - } - } - } else { - throw new Error(`Col_name must be an array of column`); - } - - const group_col = {}; - function dfs(sub_data_tensors, sub_group_col) { - for (const [ key, value ] of Object.entries(sub_data_tensors)){ - if (value instanceof DataFrame) { - sub_group_col[key] = col_names.map((col_name) => value.column(col_name)); - } else { - sub_group_col[key] = {}; - dfs(value, sub_group_col[key]); - } - } - } - dfs(this.data_tensors, group_col); - - const gp = new GroupBy( - null, - this.key_col, - null, - col_names, - this.col_dtype - ); - gp.group_col = group_col; - gp.group_col_name = col_names; - return gp; - } - - - /** - * Basic root of all column arithemetic in groups - * @param {operation} operation String - */ - arithemetic(operation){ - const ops_name = [ "mean", "sum", "count", "mode", "std", "var", "cumsum", "cumprod", - "cummax", "cummin" ]; - const ops_map = { - "mean": "mean()", - "sum": "sum()", - "mode": "mode()", - "count": "count()", - "std" : "std()", - "var" : "var()", - "cumsum" : "cumsum().values", - "cumprod": "cumprod().values", - "cummax" : "cummax().values", - "cummin" : "cummin().values" - }; - const is_array_operation = Array.isArray(operation); - const count_group = {}; - - //the local variable to store variables to be used in eval - // this seems not to be needed in Node version, since local - //variable are easily accessed in the eval function - let local = null; - function dfs(sub_count_group, sub_group_col) { - for (const [ key, value ] of Object.entries(sub_group_col)){ - if (Array.isArray(value)) { - sub_count_group[key] = []; - let data; - if (is_array_operation) { - for (let i = 0; i < value.length; i++){ - const op = operation[i]; - if (!ops_name.includes(op)){ - throw new Error("operation does not exist"); - } - local = value[i]; - data = eval(`local.${ops_map[op]}`); - sub_count_group[key].push(data); - } - } else { - value.forEach((v) => { - local = v; - data = eval(`local.${operation}`); - sub_count_group[key].push(data); - }); - } - } else { - sub_count_group[key] = {}; - dfs(sub_count_group[key], value); - } - } - } - - dfs(count_group, this.group_col); - return count_group; - } - - operations(ops, name) { - if (!this.group_col) { - let column = this.column_name.filter((val) => !this.key_col.includes(val)); - let col_gp = this.col(column); - let value = col_gp.arithemetic(ops); - let df = col_gp.to_DataFrame(col_gp.key_col, col_gp.group_col_name, value, name); - return df; - } else { - let value = this.arithemetic(ops); - let df = this.to_DataFrame(this.key_col, this.group_col_name, value, name); - return df; - } - } - count(){ - return this.operations("count()", "count"); - } - - sum(){ - return this.operations("sum()", "sum"); - } - - std(){ - return this.operations("std()", "std"); - } - - var(){ - return this.operations("var()", "var"); - } - - mean(){ - return this.operations("mean()", "mean"); - } - - cumsum(){ - return this.operations("cumsum().values", "cumsum"); - } - cummax(){ - return this.operations("cummax().values", "cummax"); - } - - cumprod(){ - return this.operations("cumprod().values", "cumprod"); - } - - cummin(){ - return this.operations("cummin().values", "cummin"); - } - - max(){ - return this.operations("max()", "max"); - } - - min(){ - return this.operations("min()", "min"); - } - - /** - * returns dataframe of a group - * @param {*} key [Array] - */ - get_groups(key){ - if (this.key_col.length < 2) - return this.data_tensors[key]; - - if (key.length !== this.key_col.length) - throw new Error("specify the group by column"); - - utils.isObject(this.data_tensors, key[0], `Key Error: ${key[0]} not in object`); - const last_key = key[key.length - 1]; - let sub_data_tensors = this.data_tensors; - for (const k of key) { - if (k === last_key) - return sub_data_tensors[k]; - else - sub_data_tensors = sub_data_tensors[k]; - } - } - - /** - * Map every column to an operation - * @param {kwargs} kwargs {column name: math operation} - * @example .agg({"A": "mean","B": "sum","C":"count"}) - */ - agg(kwargs = {}){ - - let columns = Object.keys(kwargs); - let operations = columns.map((x) => { return kwargs[x].toLocaleLowerCase(); }); - - let col_gp = this.col(columns); - - let data = col_gp.arithemetic(operations); - let df = this.to_DataFrame(col_gp.key_col, col_gp.group_col_name, data, operations); - - return df; - } - - to_DataFrame(key_col, col, data, ops){ - const df_data = []; - - function concatPathAndNode(path, node, col_dtype) { - if (Array.isArray(node)) { - if (Array.isArray(node[0])) { - if (ops != "apply" ) { - const transposed_node = node[0].map((_, colIndex) => node.map((row) => row[colIndex])); - for (const n_array of transposed_node) - df_data.push(path.concat(n_array)); - } else { - for (const n_array of node) - df_data.push(path.concat(n_array)); - } - - } else - df_data.push(path.concat(node)); - } else { - for (const [ k, child ] of Object.entries(node)) { - const sanitized_k = col_dtype[0] === "string" ? k : parseInt(k); - concatPathAndNode(path.concat([ sanitized_k ]), child, col_dtype.slice(1)); - } - } - } - - concatPathAndNode([], data, this.col_dtype); - - const column = [ ...key_col ]; - const group_col = col.slice().map((x, i) => { - if (Array.isArray(ops)){ - return `${x}_${ops[i]}`; - } - return `${x}_${ops}`; - }); - column.push(...group_col); - - return new DataFrame(df_data, { columns: column }); - } - - apply(callable){ - let df_data; - let column; - if (!this.group_col) { - column = this.column_name.filter((val) => !this.key_col.includes(val)); - const col_gp = this.col(column); - df_data = col_gp.group_col; - } else { - column = this.group_col_name; - df_data = this.group_col; - } - const count_group = {}; - - function recursiveCount(sub_df_data, sub_count_group) { - for (const [ key, value ] of Object.entries(sub_df_data)) { - if (Array.isArray(value)) { - let callable_value; - if (value.length > 1) { - callable_value = concat({ df_list: value, axis: 1 }); - } else { - callable_value = value[0]; - } - const callable_rslt = callable(callable_value); - if (callable_rslt instanceof DataFrame) { - column = callable_rslt.columns; - sub_count_group[key] = callable_rslt.values; - } else if (callable_rslt instanceof Series) { - sub_count_group[key] = callable_rslt.values; - } else - sub_count_group = callable_rslt; - } else { - sub_count_group[key] = {}; - recursiveCount(value, sub_count_group[key]); - } - } - } - - recursiveCount(df_data, count_group); - - return this.to_DataFrame(this.key_col, column, count_group, "apply"); - } - -} diff --git a/danfojs-node/src/core/indexing.js b/danfojs-node/src/core/indexing.js deleted file mode 100644 index e2b5e04d..00000000 --- a/danfojs-node/src/core/indexing.js +++ /dev/null @@ -1,411 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { utils } from "../shared/utils"; -import Series from "./series"; -import DataFrame from "./frame"; - -// const utils = new Utils(); - -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export function _iloc({ ndFrame, rows, columns }) { - - let _rowIndexes; - let _columnIndexes; - - const _data = ndFrame.values; - const _index = ndFrame.index; - - if (rows instanceof Series) { - rows = rows.values; - } - - if (rows !== undefined && !Array.isArray(rows)) { - throw new Error(`rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); - } - - if (columns !== undefined && !Array.isArray(columns)) { - throw new Error(`columns parameter must be an Array. For example: columns: [1,2] or columns: ["0:10"]`); - } - - if (!rows) { - _rowIndexes = utils.range(0, ndFrame.shape[0] - 1); - - } else if (rows.length == 1 && typeof rows[0] == "string") { - const rowSplit = rows[0].split(":"); - - if (rowSplit.length != 2) { - throw new Error(`Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); - } - if (isNaN(parseInt(rowSplit[0])) && rowSplit[0] != "") { - throw new Error(`Invalid row split parameter. Split parameter must be a number`); - } - - if (isNaN(parseInt(rowSplit[1])) && rowSplit[1] != "") { - throw new Error(`Invalid row split parameter. Split parameter must be a number`); - } - - const start = rowSplit[0] == "" ? 0 : parseInt(rowSplit[0]); - const end = rowSplit[1] == "" ? ndFrame.shape[0] : parseInt(rowSplit[1]); - - if (start < 0) { - throw new Error(`row slice [start] index cannot be less than 0`); - } - - if (end > ndFrame.shape[0]) { - throw new Error(`row slice [end] index cannot be bigger than ${ndFrame.shape[0]}`); - } - _rowIndexes = utils.range(start, end - 1); - } else { - const _formatedRows = []; - for (let i = 0; i < rows.length; i++) { - let _indexToUse = rows[i]; - if (_indexToUse > ndFrame.shape[0]) { - throw new Error(`Invalid row parameter: Specified index ${_indexToUse} cannot be bigger than index length ${ndFrame.shape[0]}`); - } - - if (typeof _indexToUse !== "number" && typeof _indexToUse !== "boolean") { - throw new Error(`Invalid row parameter: row index ${_indexToUse} must be a number or boolean`); - } - - if (typeof _indexToUse === "boolean" && _indexToUse === true) { - _formatedRows.push(_index[i]); - } - - if (typeof _indexToUse === "number") { - _formatedRows.push(_indexToUse); - } - } - - _rowIndexes = _formatedRows; - } - - if (!columns) { - _columnIndexes = utils.range(0, ndFrame.shape[1] - 1); - - } else if (columns.length == 1 && typeof columns[0] == "string") { - const columnSplit = columns[0].split(":"); - - if (columnSplit.length != 2) { - throw new Error(`Invalid column split parameter: If using column split string, it must be of the form; columns: ["start:end"]`); - } - if (isNaN(parseInt(columnSplit[0])) && columnSplit[0] != "") { - throw new Error(`Invalid column split parameter. Split parameter must be a number`); - } - - if (isNaN(parseInt(columnSplit[1])) && columnSplit[1] != "") { - throw new Error(`Invalid column split parameter. Split parameter must be a number`); - } - - const start = columnSplit[0] == "" ? 0 : parseInt(columnSplit[0]); - const end = columnSplit[1] == "" ? ndFrame.shape[1] : parseInt(columnSplit[1]); - - if (start < 0) { - throw new Error(`column slice [start] index cannot be less than 0`); - } - - if (end > ndFrame.shape[1]) { - throw new Error(`column slice [end] index cannot be bigger than ${ndFrame.shape[1]}`); - } - _columnIndexes = utils.range(start, end - 1); - } else { - - for (let i = 0; i < columns.length; i++) { - const _indexToUse = columns[i]; - if (_indexToUse > ndFrame.shape[1]) { - throw new Error(`Invalid column parameter: Specified index ${_indexToUse} cannot be bigger than index length ${ndFrame.shape[1]}`); - } - - if (typeof _indexToUse != "number") { - throw new Error(`Invalid column parameter: column index ${_indexToUse} must be a number`); - } - - } - - _columnIndexes = columns; - } - - if (ndFrame instanceof Series) { - const newData = []; - const newIndex = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - newData.push(_data[rowIndx]); - newIndex.push(_index[rowIndx]); - } - const sf = new Series( - newData, - { - index: newIndex, - columns: ndFrame.columns, - dtypes: ndFrame.dtypes, - config: ndFrame.config - }); - - return sf; - } else { - const newData = []; - const newIndex = []; - const newColumnNames = []; - const newDtypes = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - const rowData = _data[rowIndx]; - const newRowDataWithRequiredCols = []; - - for (let j = 0; j < _columnIndexes.length; j++) { - const colIndx = _columnIndexes[j]; - newRowDataWithRequiredCols.push(rowData[colIndx]); - } - newData.push(newRowDataWithRequiredCols); - newIndex.push(_index[rowIndx]); - } - - for (let i = 0; i < _columnIndexes.length; i++) { - const colIndx = _columnIndexes[i]; - newColumnNames.push(ndFrame.columns[colIndx]); - newDtypes.push(ndFrame.dtypes[colIndx]); - - } - - const df = new DataFrame( - newData, - { - index: newIndex, - columns: newColumnNames, - dtypes: newDtypes, - config: ndFrame.config - }); - - return df; - - } - -} - -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export function _loc({ ndFrame, rows, columns }) { - - let _rowIndexes; - let _columnIndexes; - - const _data = ndFrame.values; - const _index = ndFrame.index; - - if (rows instanceof Series) { - rows = rows.values; - } - - if (rows !== undefined && !Array.isArray(rows)) { - throw new Error(`rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); - } - - if (columns !== undefined && !Array.isArray(columns)) { - throw new Error(`columns parameter must be an Array. For example: columns: ["a","b"] or columns: ["a:c"]`); - } - - if (!rows) { - _rowIndexes = _index.map((indexValue) => _index.indexOf(indexValue)); // Return all row index - - } else if (rows.length === 1 && typeof rows[0] === "string") { - - if (rows[0].indexOf(":") === -1) { // Input type ==> ["1"] or [`"1"`] - let temp; - if (rows[0].startsWith(`"`) || rows[0].startsWith(`'`) || rows[0].startsWith("`")) { - temp = _index.indexOf(rows[0].replace(/['"`]/g, '')); - } else if (typeof rows[0] === "string") { - temp = _index.indexOf(rows[0]); - } else { - temp = _index.indexOf(Number(rows[0])); - } - - if (temp === -1) { - throw new Error(`IndexError: Specified index (${rows[0]}) not found`); - } - - _rowIndexes = [temp]; - - } else { - // Input type ==> ["1:2"] or [`"1":"4"`] - const rowSplit = rows[0].split(":"); - - if (rowSplit.length != 2) { - throw new Error(`Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); - } - - let start; - let end; - - if (rowSplit[0] === "") { - start = _index.indexOf(_index[0]); - } else { - if (rowSplit[0].startsWith(`"`) || rowSplit[0].startsWith(`'`) || rowSplit[0].startsWith("`")) { - start = _index.indexOf(rowSplit[0].replace(/['"`]/g, '')); - } else { - start = _index.indexOf(Number(rowSplit[0])); - } - } - - if (rowSplit[1] === "") { - end = _index.indexOf(_index[_index.length - 1]) + 1; - } else { - if (rowSplit[1].startsWith(`"`) || rowSplit[1].startsWith(`'`) || rowSplit[1].startsWith("`")) { - end = _index.indexOf(rowSplit[1].replace(/['"`]/g, '')); - } else { - end = _index.indexOf(Number(rowSplit[1])); - } - - } - - if (start === -1) { - throw new Error(`IndexError: Specified start index not found`); - } - - if (end === -1) { - throw new Error(`IndexError: Specified end index not found`); - } - - _rowIndexes = _index.slice(start, end).map((indexValue) => _index.indexOf(indexValue)); - } - - } else { - // Input type ==> ["1", "2"] or [1, 5] or [true, false] - const rowsIndexToUse = []; - for (let i = 0; i < rows.length; i++) { - const isBoolean = typeof rows[i] === "boolean"; - if (isBoolean && rows[i]) { - rowsIndexToUse.push(_index.indexOf(_index[i])); - } - - if (!isBoolean) { - const rowIndex = _index.indexOf(rows[i]); - if (rowIndex === -1) { - throw new Error(`IndexError: Specified index (${rows[i]}) not found`); - } - rowsIndexToUse.push(rowIndex); - } - } - - _rowIndexes = rowsIndexToUse; - } - - const _columnNames = ndFrame.columns; - - if (!columns) { - _columnIndexes = _columnNames.map((columnName) => _columnNames.indexOf(columnName));// Return all column index - - } else if (columns.length == 1) { - if (typeof columns[0] !== "string") { - throw new Error(`ColumnIndexError: columns parameter must be an array of a string name. For example: columns: ["b"]`); - } - - if (columns[0].indexOf(":") == -1) { // Input type ==> ["A"] - _columnIndexes = [_columnNames.indexOf(columns[0])]; - - } else { // Input type ==> ["a:b"] or [`"col1":"col5"`] - const columnSplit = columns[0].split(":"); - - if (columnSplit.length != 2) { - throw new Error(`ColumnIndexError: Invalid row split parameter. If using row split string, it must be of the form; rows: ["start:end"]`); - } - - const start = columnSplit[0] == "" ? _columnNames.indexOf(_columnNames[0]) : _columnNames.indexOf(columnSplit[0]); - const end = columnSplit[1] == "" ? _columnNames.indexOf(_columnNames[_columnNames.length - 1]) : _columnNames.indexOf(columnSplit[1]); - - if (start === -1) { - throw new Error(`ColumnIndexError: Specified start index not found`); - } - - if (end === -1) { - throw new Error(`ColumnIndexError: Specified end index not found`); - } - _columnIndexes = _columnNames.slice(start, end + 1).map((columnName) => _columnNames.indexOf(columnName)); - _columnIndexes.pop(); //Remove the last element - - } - } else { // Input type ==> ["A", "B"] or ["col1", "col2"] - for (let i = 0; i < columns.length; i++) { - if (_columnNames.indexOf(columns[i]) === -1) { - throw new Error(`ColumnIndexError: Specified column (${columns[i]}) not found`); - } - } - _columnIndexes = columns.map((columnName) => _columnNames.indexOf(columnName)); - } - - if (ndFrame instanceof Series) { - const newData = []; - const newIndex = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - newData.push(_data[rowIndx]); - newIndex.push(_index[rowIndx]); - } - const sf = new Series( - newData, - { - index: newIndex, - columns: ndFrame.columns, - dtypes: ndFrame.dtypes, - config: ndFrame.config - }); - - return sf; - } else { - const newData = []; - const newIndex = []; - const newColumnNames = []; - const newDtypes = []; - - for (let i = 0; i < _rowIndexes.length; i++) { - const rowIndx = _rowIndexes[i]; - const rowData = _data[rowIndx]; - const newRowDataWithRequiredCols = []; - - for (let j = 0; j < _columnIndexes.length; j++) { - const colIndx = _columnIndexes[j]; - newRowDataWithRequiredCols.push(rowData[colIndx]); - } - newData.push(newRowDataWithRequiredCols); - newIndex.push(_index[rowIndx]); - } - - for (let i = 0; i < _columnIndexes.length; i++) { - const colIndx = _columnIndexes[i]; - newColumnNames.push(ndFrame.columns[colIndx]); - newDtypes.push(ndFrame.dtypes[colIndx]); - - } - - const df = new DataFrame( - newData, - { - index: newIndex, - columns: newColumnNames, - dtypes: newDtypes, - config: ndFrame.config - }); - return df; - - } - -} diff --git a/danfojs-node/src/core/math.ops.js b/danfojs-node/src/core/math.ops.js deleted file mode 100644 index b6b3f26f..00000000 --- a/danfojs-node/src/core/math.ops.js +++ /dev/null @@ -1,163 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -import { utils } from "../shared/utils"; - -// const utils = new Utils(); - -/** - * Generic function for performing add, sub, pow, mul and mod operation on a series - * @param object - * - * ndframe ==> The current Series - * - * other ==> The Series or number to perform math operation with - * - * operation ==> The type of operation to perform -*/ -export function _genericMathOp({ ndFrame, other, operation }) { - if (typeof other === 'number') { - //broadcast operation - let newData; - switch (operation) { - case 'add': - newData = (ndFrame.values).map(((ele) => ele + other)); - return newData; - - case 'sub': - newData = (ndFrame.values).map(((ele) => ele - other)); - return newData; - - case 'mul': - newData = (ndFrame.values).map(((ele) => ele * other)); - return newData; - - case 'div': - newData = (ndFrame.values).map(((ele) => ele / other)); - return newData; - - case 'mod': - newData = (ndFrame.values).map(((ele) => ele % other)); - return newData; - - case 'pow': - newData = (ndFrame.values).map(((ele) => ele ** other)); - return newData; - - case 'minimum': - newData = (ndFrame.values).map(((ele) => Math.min(ele, other))); - return newData; - - case 'maximum': - newData = (ndFrame.values).map(((ele) => Math.max(ele, other))); - return newData; - - default: - throw new Error(`${operation} is not implemented`); - - } - } else if (other instanceof Series) { - utils.checkSeriesOpCompactibility({ firstSeries: ndFrame, secondSeries: other, operation }); - - let newData; - switch (operation) { - case 'add': - - newData = (ndFrame.values).map((ele, index) => { return ele + (other.values)[index]; }); - return newData; - - case 'sub': - - newData = (ndFrame.values).map((ele, index) => { return ele - (other.values)[index]; }); - return newData; - - case 'mul': - - newData = (ndFrame.values).map((ele, index) => { return ele * (other.values)[index]; }); - return newData; - - case 'div': - - newData = (ndFrame.values).map((ele, index) => { return ele / (other.values)[index]; }); - return newData; - - case 'mod': - - newData = (ndFrame.values).map((ele, index) => { return ele % (other.values)[index]; }); - return newData; - - case 'pow': - newData = (ndFrame.values).map((ele, index) => { return ele ** (other.values)[index]; }); - return newData; - - case 'minimum': - newData = (ndFrame.values).map((ele, index) => { return Math.min(ele, (other.values)[index]); }); - return newData; - - case 'maximum': - newData = (ndFrame.values).map((ele, index) => { return Math.max(ele, (other.values)[index]); }); - return newData; - - default: - throw new Error(`${operation} is not implemented`); - } - } else if (Array.isArray(other)) { - if (other.length !== ndFrame.values.length){ - throw new Error(`ParamError: Length of array must be equal to length of Series`); - } - let newData; - switch (operation) { - case 'add': - - newData = (ndFrame.values).map((ele, index) => { return ele + (other)[index]; }); - return newData; - - case 'sub': - - newData = (ndFrame.values).map((ele, index) => { return ele - (other)[index]; }); - return newData; - - case 'mul': - - newData = (ndFrame.values).map((ele, index) => { return ele * (other)[index]; }); - return newData; - - case 'div': - - newData = (ndFrame.values).map((ele, index) => { return ele / (other)[index]; }); - return newData; - - case 'mod': - - newData = (ndFrame.values).map((ele, index) => { return ele % (other)[index]; }); - return newData; - - case 'pow': - newData = (ndFrame.values).map((ele, index) => { return ele ** (other)[index]; }); - return newData; - - case 'minimum': - newData = (ndFrame.values).map((ele, index) => { return Math.min(ele, (other)[index]); }); - return newData; - - case 'maximum': - newData = (ndFrame.values).map((ele, index) => { return Math.max(ele, (other)[index]); }); - return newData; - - } - } else { - throw new Error("ParamError: value for other not supported. It must be either a scalar, Array or Series"); - } -} diff --git a/danfojs-node/src/core/merge.js b/danfojs-node/src/core/merge.js deleted file mode 100644 index 61e8c503..00000000 --- a/danfojs-node/src/core/merge.js +++ /dev/null @@ -1,328 +0,0 @@ -import DataFrame from './frame'; -import { utils } from "../shared/utils"; - -export class Merge { - - constructor(kwargs) { - - //check if keys exist in kwargs - utils.keyInObject(kwargs, "left"); - utils.keyInObject(kwargs, "right"); - utils.keyInObject(kwargs, "on"); - // utils.keyInObject(kwargs, "how") - if (!utils.keyInObject(kwargs, "how")){ - this.how = 'inner'; - kwargs['how'] = 'inner'; - } else { - this.how = kwargs['how']; - } - - this.left = null; - this.right = null; - this.on = null; - // this.how = null; - - let how_keys = [ "outer", "inner", "left", "right" ]; - - if ((kwargs["left"] instanceof DataFrame) && (kwargs["right"] instanceof DataFrame)) { - this.left = kwargs["left"]; - this.right = kwargs["right"]; - } else { - throw new Error("The left and right key value must be a dataFrame"); - } - - if (Array.isArray(kwargs["on"])) { - this.on = kwargs["on"]; - } else { - throw new Error("key 'on' must be a list"); - } - - if (how_keys.includes(kwargs["how"])) { - - this.how = kwargs["how"]; - } else { - throw new Error(`${kwargs["how"]} specify in keyword how is not recognise`); - } - - this.left_col_index = []; - this.right_col_index = []; - - //find the index of the columns - for (let i = 0; i < this.on.length; i++) { - - if (this.left.columns.includes(this.on[i]) && this.right.columns.includes(this.on[i])) { - - let left_index = this.left.columns.indexOf(this.on[i]); - let right_index = this.right.columns.indexOf(this.on[i]); - - this.left_col_index.push(left_index); - this.right_col_index.push(right_index); - } - } - - this.left_key_dict = {}; - this.right_key_dict = {}; - - let left_values = this.left.values; - let right_values = this.right.values; - - - /** - * Create a dictionary for both left and right dataframe - containing the key combination of columns used as keys, and - the value of such keys combination are the rows having this - keys combination. - */ - for (let i = 0; i < left_values.length; i++) { - let left_value = left_values[i]; - let left_key_comb_values = []; - - //get the value in the column index - for (let j = 0; j < this.left_col_index.length; j++) { - let index = this.left_col_index[j]; - - left_key_comb_values.push(left_value[index]); - } - //combine into single hashable string - let left_key_comb = left_key_comb_values.join('_'); - - let self = this; // assign the this scope to self - //filter out the value that are not the column key - let left_value_filter = left_value.filter(function (val, index) { - return !self.left_col_index.includes(index); - }); - - //check if the key combination already exist or not - //before storing the key combination and the value - //associated with it - if (utils.keyInObject(this.left_key_dict, left_key_comb)) { - this.left_key_dict[left_key_comb].filters.push(left_value_filter); - } else { - this.left_key_dict[left_key_comb] = { - filters: [left_value_filter], - comb_values: left_key_comb_values - }; - } - - } - for (let i = 0; i < right_values.length; i++) { - let right_value = right_values[i]; - let right_key_comb_values = []; - - for (let j = 0; j < this.right_col_index.length; j++) { - let index = this.right_col_index[j]; - - right_key_comb_values.push(right_value[index]); - } - let right_key_comb = right_key_comb_values.join('_'); - - let self = this; - let right_value_filter = right_value.filter(function (val, index) { - return !self.right_col_index.includes(index); - }); - - if (utils.keyInObject(this.right_key_dict, right_key_comb)) { - this.right_key_dict[right_key_comb].filters.push(right_value_filter); - } else { - this.right_key_dict[right_key_comb] = { - filters: [right_value_filter], - comb_values: right_key_comb_values - }; - } - } - - - //create column - this.__create_columns(); - - let data = null; - switch (this.how) { - - case "outer": - data = this.outer(); - break; - case "inner": - data = this.inner(); - break; - case "left": - data = this.left_merge(); - break; - case "right": - data = this.right_merge(); - break; - } - - // eslint-disable-next-line no-self-assign - let df = new DataFrame(data = data, { columns: this.columns }); - - return df; - } - - __create_columns() { - - let self = this; - self.left_col = self.left.columns.filter((val, index) => { - return !self.left_col_index.includes(index); - }); - - self.right_col = self.right.columns.filter((val, index) => { - return !self.right_col_index.includes(index); - }); - - self.columns = [ ...self.on ]; - let column_duplicate = {}; - - let temp_column = [ ...self.left_col ]; - temp_column.push(...self.right_col); - - for (let i = 0; i < temp_column.length; i++) { - - let col = temp_column[i]; - if (utils.keyInObject(column_duplicate, col)) { - - let col_name = `${col}_${column_duplicate[col]}`; - self.columns.push(col_name); - - column_duplicate[col] += 1; - } else { - self.columns.push(col); - column_duplicate[col] = 1; - } - } - } - - outer() { - - let keys = Object.keys(this.left_key_dict); // obtain the keys of the left dataframe - - keys.push(...Object.keys(this.right_key_dict)); - - keys = Array.from(new Set(keys)); // obtain the unique keys - - let data = this.basic(keys); - - return data; - - } - - inner() { - - let left_keys = Object.keys(this.left_key_dict); - let right_keys = Object.keys(this.right_key_dict); - - let keys = left_keys.filter((val) => { - return right_keys.includes(val); - }); - - let data = this.basic(keys); - - return data; - } - - left_merge() { - - let keys = Object.keys(this.left_key_dict); - let data = this.basic(keys); - - return data; - - } - - right_merge() { - let keys = Object.keys(this.right_key_dict); - let data = this.basic(keys); - - return data; - } - - basic(keys) { - - let data = []; - - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - - let key_array = key.split("_").filter((val) => { - return val != ""; - }); - - if (utils.keyInObject(this.left_key_dict, key)) { - let left_row = this.left_key_dict[key].filters; - let key_array = this.left_key_dict[key].comb_values; - - - for (let left_i = 0; left_i < left_row.length; left_i++) { - - let left_row_row = left_row[left_i]; - - if (utils.keyInObject(this.right_key_dict, key)) { - - let right_row = this.right_key_dict[key].filters; - - for (let r_i = 0; r_i < right_row.length; r_i++) { - - let right_row_row = right_row[r_i]; - - - let inner_data = key_array.slice(0); - inner_data.push(...left_row_row); - inner_data.push(...right_row_row); - - - data.push(inner_data); - } - } else { - let nan_array = Array(this.right_col.length); - - for (let i = 0; i < this.right_col.length; i++) { - nan_array[i] = NaN; - } - - let inner_data = key_array.slice(0); - inner_data.push(...left_row_row); - inner_data.push(...nan_array); - data.push(inner_data); - } - } - } else { - - let right_row = this.right_key_dict[key].filters; - let key_array = this.right_key_dict[key].comb_values; - - for (let i = 0; i < right_row.length; i++) { - - let right_row_row = right_row[i]; - - let nan_array = Array(this.left_col.length); - - for (let j = 0; j < nan_array.length; j++) { - nan_array[j] = NaN; - } - - let inner_data = key_array.slice(0); - inner_data.push(...nan_array); - inner_data.push(...right_row_row); - data.push(inner_data); - } - } - } - return data; - - } -} - - -/** -* Merge DataFrame or named Series objects with a database-style join. -* The join is done on columns or indexes. If joining columns on columns, the DataFrame indexes will be ignored. Otherwise -* if joining indexes on indexes or indexes on a column or columns, the index will be passed on. -* @param {kwargs}{left: DataFrame; -* right: DataFrame | Named Series, Object to merge with; -* on: label, Column or index level names to join on. These must be found in both DataFrames; -* how: {‘left’, ‘right’, ‘outer’, ‘inner’}. Type of merge to be performed. -* @returns {DataFrame} -*/ -export const merge = (kwargs) => { - let merge = new Merge(kwargs); - return merge; -}; diff --git a/danfojs-node/src/core/series.js b/danfojs-node/src/core/series.js deleted file mode 100644 index 42555905..00000000 --- a/danfojs-node/src/core/series.js +++ /dev/null @@ -1,1347 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { variance, std, median, mode } from 'mathjs'; -import { _genericMathOp } from "./math.ops"; -import { DATA_TYPES } from '../shared/defaults'; -import ErrorThrower from "../shared/errors"; -import { _iloc, _loc } from "./indexing"; -import { utils } from "../shared/utils"; -import NDframe from "./generic"; -import { table } from "table"; -import Str from './strings'; -import Dt from './datetime'; -import dummyEncode from "./get_dummies"; -import { data as tfData } from "@tensorflow/tfjs-node"; - - -/** - * One-dimensional ndarray with axis labels. - * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. - * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. - * @param data 2D Array, JSON, Tensor, Block of data. - * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * @param options.columns Array of column names. If not specified, column names are auto generated. - * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. - * @param options.config General configuration object for extending or setting NDframe behavior. - */ -export default class Series extends NDframe { - - constructor(data = [], options) { - const { index, columns, dtypes, config } = { index: undefined, columns: undefined, dtypes: undefined, config: undefined, ...options }; - if (Array.isArray(data[0]) || utils.isObject(data[0])) { - data = utils.convert2DArrayToSeriesArray(data); - super({ - data, - index, - columns, - dtypes, - config, - isSeries: true - }); - } else { - super({ - data, - index, - columns, - dtypes, - config, - isSeries: true - }); - } - } - - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc(rows) { - return _iloc({ ndFrame: this, rows }); - } - - /** - * Access a group of rows by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc(rows) { - return _loc({ ndFrame: this, rows }); - } - - /** - * Returns the first n values in a Series - * @param rows The number of rows to return - */ - head(rows = 5) { - return this.iloc([`0:${rows}`]); - } - - /** - * Returns the last n values in a Series - * @param rows The number of rows to return - */ - tail(rows = 5) { - const startIdx = this.shape[0] - rows; - return this.iloc([`${startIdx}:`]); - } - - /** - * Returns specified number of random rows in a Series - * @param num The number of rows to return - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - async sample(num = 5, options) { - const { seed } = { seed: 1, ...options }; - - if (num > this.shape[0]) { - throw new Error("Sample size n cannot be bigger than size of dataset"); - } - if (num < -1 || num == 0) { - throw new Error("Sample size cannot be less than -1 or be equal to 0"); - } - num = num === -1 ? this.shape[0] : num; - - const shuffledIndex = await tfData.array(this.index).shuffle(num, `${seed}`).take(num).toArray(); - const sf = this.iloc(shuffledIndex); - return sf; - } - - /** - * Return Addition of series and other, element-wise (binary operator add). - * Equivalent to series + other - * @param other Series, Array of same length or scalar number to add - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("add"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "add" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Returns the subtraction between a series and other, element-wise (binary operator subtraction). - * Equivalent to series - other - * @param other Number to subtract - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("sub"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "sub" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - - } - - /** - * Return Multiplication of series and other, element-wise (binary operator mul). - * Equivalent to series * other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("mul"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "mul" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Return division of series and other, element-wise (binary operator div). - * Equivalent to series / other - * @param other Series or number to divide with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("div"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "div" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Return Exponential power of series and other, element-wise (binary operator pow). - * Equivalent to series ** other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("pow"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "pow" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Return Modulo of series and other, element-wise (binary operator mod). - * Equivalent to series % other - * @param other Number to modulo with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other, options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("mod"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "mod" }); - - if (inplace) { - this.$setValues(newData); - } else { - return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }); - } - } - - /** - * Checks if the array value passed has a compatible dtype, removes NaN values, and if - * boolean values are present, converts them to integer values. - * */ - $checkAndCleanValues(values, operation) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError(operation); - values = utils.removeMissingValuesFromArray(values); - - if (this.dtypes[0] == "boolean") { - values = (utils.mapBooleansToIntegers(values, 1)); - } - return values; - } - - /** - * Returns the mean of elements in Series - */ - mean() { - const values = this.$checkAndCleanValues(this.values, "mean"); - return (values.reduce((a, b) => a + b) / values.length); - } - - - /** - * Returns the median of elements in Series - */ - median() { - const values = this.$checkAndCleanValues(this.values, "median"); - return median(values); - } - - /** - * Returns the modal value of elements in Series - */ - mode() { - const values = this.$checkAndCleanValues(this.values, "mode"); - return mode(values); - } - - /** - * Returns the minimum value in a Series - */ - min() { - const values = this.$checkAndCleanValues(this.values, "min"); - let smallestValue = values[0]; - for (let i = 0; i < values.length; i++) { - smallestValue = smallestValue < values[i] ? smallestValue : values[i]; - } - return smallestValue; - } - - /** - * Returns the maximum value in a Series - * @returns {Number} - */ - max() { - const values = this.$checkAndCleanValues(this.values, "max"); - let biggestValue = values[0]; - for (let i = 0; i < values.length; i++) { - biggestValue = biggestValue > values[i] ? biggestValue : values[i]; - } - return biggestValue; - } - - /** - * Return the sum of the values in a series. - */ - sum() { - const values = this.$checkAndCleanValues(this.values, "sum"); - return values.reduce((sum, value) => sum + value, 0); - } - - /** - * Return number of non-null elements in a Series - */ - count() { - const values = utils.removeMissingValuesFromArray(this.values); - return values.length; - } - - /** - * Return maximum of series and other. - * @param other Series or number to check against - */ - maximum(other) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("maximum"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "maximum" }); - return new Series(newData, { - columns: this.columns, - index: this.index - }); - } - - /** - * Return minimum of series and other. - * @param other Series, Numbers to check against - */ - minimum(other) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("maximum"); - - const newData = _genericMathOp({ ndFrame: this, other, operation: "minimum" }); - return new Series(newData, { - columns: this.columns, - index: this.index - }); - } - - /** - * Round each value in a Series to the specified number of decimals. - * @param dp Number of Decimal places to round to - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newValues = utils.round(this.values, dp, true); - if (inplace) { - this.$setValues(newValues); - } else { - return utils.createNdframeFromNewDataWithOldProps({ - ndFrame: this, - newData: newValues, - isSeries: true - }); - } - - } - - /** - * Return sample standard deviation of elements in Series - */ - std() { - const values = this.$checkAndCleanValues(this.values, "max"); - return std(values); - } - - /** - * Return unbiased variance of elements in a Series. - */ - var() { - const values = this.$checkAndCleanValues(this.values, "max"); - return variance(values); - } - - /** - * Return a boolean same-sized object indicating where elements are NaN. - * NaN and undefined values gets mapped to true, and everything else gets mapped to false. - */ - isna() { - const newData = this.values.map((value) => { - if (isNaN(value) && typeof value != "string") { - return true; - } else { - return false; - } - }); - const sf = new Series(newData, - { - index: this.index, - dtypes: ["boolean"], - config: this.config - }); - return sf; - } - - /** - * Replace all NaN with a specified value - * @param value The value to replace NaN with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(options) { - const { value, inplace } = { value: undefined, inplace: false, ...options }; - - if (!value && typeof value !== 'boolean') { - throw Error('Value Error: Must specify value to replace with'); - } - - const newValues = []; - (this.values).forEach((val) => { - if (isNaN(val) && typeof val != "string") { - newValues.push(value); - } else { - newValues.push(val); - } - }); - - if (inplace) { - this.$setValues(newValues); - } else { - return utils.createNdframeFromNewDataWithOldProps({ - ndFrame: this, - newData: newValues, - isSeries: true - }); - } - } - - - /** - * Sort a Series in ascending or descending order by some criterion. - * @param options Method options - * @param ascending Whether to return sorted values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options) { - const { ascending, inplace } = { inplace: false, ascending: true, ...options }; - - let sortedValues = []; - const rangeIdx = utils.range(0, this.index.length - 1); - let sortedIdx = utils.sortArrayByIndex(rangeIdx, this.values, this.dtypes[0]); - - for (let indx of sortedIdx) { - sortedValues.push(this.values[indx]); - } - - if (ascending) { - sortedValues = sortedValues.reverse(); - sortedIdx = sortedIdx.reverse(); - } - - if (inplace) { - this.$setValues(sortedValues); - this.$setIndex(sortedIdx); - } else { - const sf = new Series(sortedValues, { - index: sortedIdx, - dtypes: this.dtypes, - config: this.config - }); - return sf; - - } - } - - - /** - * Makes a deep copy of a Series - */ - copy() { - const sf = new Series([...this.values], { - columns: [...this.columns], - index: [...this.index], - dtypes: [...this.dtypes], - config: { ...this.config } - }); - return sf; - } - - - /** - * Generate descriptive statistics. - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - */ - describe() { - if (this.dtypes[0] == "string") { - throw new Error("DType Error: Cannot generate descriptive statistics for Series with string dtype"); - } else { - - const index = ['count', 'mean', 'std', 'min', 'median', 'max', 'variance']; - const count = this.count(); - const mean = this.mean(); - const std = this.std(); - const min = this.min(); - const median = this.median(); - const max = this.max(); - const variance = this.var(); - - const data = [count, mean, std, min, median, max, variance]; - const sf = new Series(data, { index: index }); - return sf; - - } - } - - - /** - * Returns Series with the index reset. - * This is useful when index is meaningless and needs to be reset to the default before another operation. - */ - reset_index(options) { - const { inplace } = { inplace: false, ...options }; - - if (inplace) { - this.$resetIndex(); - } else { - const sf = this.copy(); - sf.$resetIndex(); - return sf; - } - } - - /** - * Set the Series index (row labels) using an array of the same length. - * @param index Array of new index values, - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options) { - const { index, inplace } = { index: undefined, inplace: false, ...options }; - - if (!index) { - throw Error('Param Error: Must specify index array'); - } - - if (inplace) { - this.$setIndex(index); - } else { - const sf = this.copy(); - sf.$setIndex(index); - return sf; - } - } - - - /** - * map all the element in a column to a variable or function - * @param callable callable can either be a funtion or an object - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - map(callable, options) { - const { inplace } = { inplace: false, ...options }; - - const isCallable = utils.isFunction(callable); - - const data = this.values.map((val) => { - if (isCallable) { - return callable(val); - } else if (utils.isObject(callable)) { - if (val in callable) { - return callable[val]; - } else { - return NaN; - } - } else { - throw new Error("Param Error: callable must either be a function or an object"); - } - }); - - if (inplace) { - this.$setValues(data); - } else { - const sf = this.copy(); - sf.$setValues(data); - return sf; - } - } - - /** - * Applies a function to each element of a Series - * @param callable Function to apply to each element of the series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply(callable, options) { - const { inplace } = { inplace: false, ...options }; - - const isCallable = utils.isFunction(callable); - if (!isCallable) { - throw new Error("Param Error: callable must be a function"); - } - - const data = this.values.map((val) => { - return callable(val); - }); - - if (inplace) { - this.$setValues(data); - } else { - const sf = this.copy(); - sf.$setValues(data); - return sf; - } - } - - /** - * Returns a Series with only the unique value(s) in the original Series - */ - unique() { - const newValues = new Set(this.values); - let series = new Series(Array.from(newValues)); - return series; - } - - /** - * Return the number of unique elements in a Series - */ - nunique() { - return (new Set(this.values)).size; - } - - /** - * Returns unique values and their counts in a Series - */ - value_counts() { - const sData = this.values; - const dataDict = {}; - for (let i = 0; i < sData.length; i++) { - const val = sData[i]; - if (`${val}` in dataDict) { - dataDict[`${val}`] = dataDict[`${val}`] + 1; - } else { - dataDict[`${val}`] = 1; - } - } - - const index = Object.keys(dataDict).map((x) => { - return parseInt(x) ? parseInt(x) : x; - }); - const data = Object.values(dataDict); - - const series = new Series(data, { index: index }); - return series; - - } - - /** - * Returns the absolute values in Series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options) { - const { inplace } = { inplace: false, ...options }; - - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("abs"); - let newValues; - - - newValues = this.values.map((val) => Math.abs(val)); - - if (inplace) { - this.$setValues(newValues); - } else { - const sf = this.copy(); - sf.$setValues(newValues); - return sf; - } - } - - /** - * Returns the cumulative sum over a Series - */ - cumsum(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("sum", ops); - } - - /** - * Returns cumulative minimum over a Series - */ - cummin(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("min", ops); - } - - - /** - * Returns cumulative maximum over a Series - */ - cummax(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("max", ops); - } - - /** - * Returns cumulative product over a Series - */ - cumprod(options) { - const ops = { inplace: false, ...options }; - return this.cumOps("prod", ops); - } - - /** - * perform cumulative operation on series data - */ - cumOps(ops, options) { - if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError(ops); - const { inplace } = options; - - const sData = this.values; - let tempval = sData[0]; - const data = [tempval]; - - for (let i = 1; i < sData.length; i++) { - let currVal = sData[i]; - switch (ops) { - case "max": - if (currVal > tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "min": - if (currVal < tempval) { - data.push(currVal); - tempval = currVal; - } else { - data.push(tempval); - } - break; - case "sum": - tempval = (tempval) + (currVal); - data.push(tempval); - break; - case "prod": - tempval = (tempval) * (currVal); - data.push(tempval); - break; - - } - } - - if (inplace) { - this.$setValues(data); - } else { - return new Series(data, { - index: this.index, - config: { ...this.config } - }); - } - } - - - /** - * Returns less than of series and other. Supports element wise operations - * @param other Series or number to compare against - */ - lt(other) { - return this.boolOps(other, "lt"); - } - - /** - * Returns Greater than of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - gt(other) { - return this.boolOps(other, "gt"); - } - - /** - * Returns Less than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - le(other) { - return this.boolOps(other, "le"); - } - - /** - * Returns Greater than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ge(other) { - return this.boolOps(other, "ge"); - } - - /** - * Returns Not Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ne(other) { - return this.boolOps(other, "ne"); - } - - /** - * Returns Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - eq(other) { - return this.boolOps(other, "eq"); - } - - /** - * Perform boolean operations on bool values - * @param other Other Series or number to compare with - * @param bOps Name of operation to perform [ne, ge, le, gt, lt, eq] - */ - boolOps(other, bOps) { - const data = []; - const lSeries = this.values; - let rSeries; - - if (typeof other == "number") { - rSeries = Array(this.values.length).fill(other); //create array of repeated value for broadcasting - } else if (typeof other == "string" && ["eq", "ne"].includes(bOps)) { - rSeries = Array(this.values.length).fill(other); - } else if (other instanceof Series) { - rSeries = other.values; - } else if (Array.isArray(other)) { - rSeries = other; - } else { - throw new Error("ParamError: value for other not supported. It must be either a scalar, Array or Series"); - } - - if (!(lSeries.length === rSeries.length)) { - throw new Error("LengthError: Lenght of other must be equal to length of Series"); - } - - - for (let i = 0; i < lSeries.length; i++) { - let lVal = lSeries[i]; - let rVal = rSeries[i]; - let bool = null; - switch (bOps) { - case "lt": - bool = lVal < rVal ? true : false; - data.push(bool); - break; - case "gt": - bool = lVal > rVal ? true : false; - data.push(bool); - break; - case "le": - bool = lVal <= rVal ? true : false; - data.push(bool); - break; - case "ge": - bool = lVal >= rVal ? true : false; - data.push(bool); - break; - case "ne": - bool = lVal !== rVal ? true : false; - data.push(bool); - break; - case "eq": - bool = lVal === rVal ? true : false; - data.push(bool); - break; - } - } - return new Series(data, { - index: this.index, - config: { ...this.config } - }); - - } - - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace(options) { - const { oldValue, newValue, inplace } = { oldValue: undefined, newValue: undefined, inplace: false, ...options }; - - if (!oldValue && typeof oldValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'oldValue' to replace`); - } - - if (!newValue && typeof newValue !== 'boolean') { - throw Error(`Params Error: Must specify param 'newValue' to replace with`); - } - - const newArr = [...this.values].map((val) => { - if (val === oldValue) { - return newValue; - } else { - return val; - } - }); - - if (inplace) { - this.$setValues(newArr); - } else { - const sf = this.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - /** - * Drops all missing values (NaN) from a Series. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(options) { - const { inplace } = { inplace: false, ...options }; - - const oldValues = this.values; - const oldIndex = this.index; - const newValues = []; - const newIndex = []; - const isNaVals = this.isna().values; - - isNaVals.forEach((val, i) => { - if (!val) { - newValues.push((oldValues)[i]); - newIndex.push(oldIndex[i]); - } - }); - - if (inplace) { - this.$setValues(newValues, false); - this.$setIndex(newIndex); - } else { - const sf = this.copy(); - sf.$setValues(newValues, false); - sf.$setIndex(newIndex); - return sf; - } - - } - - /** - * Return the integer indices that would sort the Series. - * @param ascending boolean true: will sort the Series in ascending order, false: will sort in descending order - */ - argsort(ascending = true) { - const sortedIndex = this.sort_values(ascending); - const sf = new Series(sortedIndex.index); - return sf; - } - - /** - * Return int position of the largest value in the Series. - */ - argmax() { - return this.tensor.argMax().arraySync(); - } - - - /** - * Return int position of the smallest value in the Series. - */ - argmin() { - return this.tensor.argMin().arraySync(); - } - - /** - * Remove duplicate values from a Series - * @param keep "first" | "last", which dupliate value to keep. Defaults to "first". - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop_duplicates(options) { - const { keep, inplace } = { keep: "first", inplace: false, ...options }; - - if (!(["first", "last"].includes(keep))) { - throw Error(`Params Error: Keep must be one of 'first' or 'last'`); - } - - let dataArr; - let newArr = []; - let oldIndex; - let newIndex = []; - - if (keep === "last") { - dataArr = (this.values).reverse(); - oldIndex = this.index.reverse(); - } else { - dataArr = (this.values); - oldIndex = this.index; - } - - dataArr.forEach((val, i) => { - if (!newArr.includes(val)) { - newIndex.push(oldIndex[i]); - newArr.push(val); - } - }); - - if (keep === "last") { - //re-reversed the array and index to its true order - newArr = newArr.reverse(); - newIndex = newIndex.reverse(); - } - - if (inplace) { - this.$setValues(newArr, false); - this.$setIndex(newIndex); - } else { - const sf = this.copy(); - sf.$setValues(newArr, false); - sf.$setIndex(newIndex); - return sf; - } - - } - - /** - * Cast Series to specified data type - * @param dtype Data type to cast to. One of [float32, int32, string, boolean, undefined] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(dtype, options) { - const { inplace } = { inplace: false, ...options }; - - if (!dtype) { - throw Error("Param Error: Please specify dtype to cast to"); - } - - if (!(DATA_TYPES.includes(dtype))) { - throw Error(`dtype ${dtype} not supported. dtype must be one of ${DATA_TYPES}`); - } - - const oldValues = [...this.values]; - const newValues = []; - - switch (dtype) { - case "float32": - oldValues.forEach((val) => { - newValues.push(Number(val)); - }); - break; - case "int32": - oldValues.forEach((val) => { - newValues.push(parseInt(val)); - }); - break; - case "string": - oldValues.forEach((val) => { - newValues.push(String(val)); - }); - break; - case "boolean": - oldValues.forEach((val) => { - newValues.push(Boolean(val)); - }); - break; - case "undefined": - oldValues.forEach((_) => { - newValues.push(NaN); - }); - break; - default: - break; - } - - if (inplace) { - this.$setValues(newValues, false); - this.$setDtypes([dtype]); - } else { - const sf = this.copy(); - sf.$setValues(newValues, false); - sf.$setDtypes([dtype]); - return sf; - } - - } - - /** - * Add a new value or values to the end of a Series - * @param newValues Single value | Array | Series to append to the Series - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append( - newValue, - index, - options - ) { - const { inplace } = { inplace: false, ...options }; - - if (!newValue && typeof newValue !== "boolean") { - throw Error("Param Error: newValues cannot be null or undefined"); - } - - if (!index) { - throw Error("Param Error: index cannot be null or undefined"); - } - - const newData = [...this.values]; - const newIndx = [...this.index]; - - if (Array.isArray(newValue) && Array.isArray(index)) { - - if (newValue.length !== index.length) { - throw Error("Param Error: Length of new values and index must be the same"); - } - - newValue.forEach((el, i) => { - newData.push(el); - newIndx.push(index[i]); - }); - - } else if (newValue instanceof Series) { - const _value = newValue.values; - - if (!Array.isArray(index)) { - throw Error("Param Error: index must be an array"); - } - - if (index.length !== _value.length) { - throw Error("Param Error: Length of new values and index must be the same"); - } - - _value.forEach((el, i) => { - newData.push(el); - newIndx.push(index[i]); - }); - } else { - newData.push(newValue); - newIndx.push(index); - } - - if (inplace) { - this.$setValues(newData, false); - this.$setIndex(newIndx); - } else { - const sf = new Series( - newData, - { - index: newIndx, - columns: this.columns, - dtypes: this.dtypes, - config: this.config - }); - - return sf; - } - } - - /** - * Returns dtype of Series - */ - get dtype() { - return this.dtypes[0]; - } - - /** - * Exposes numerous string methods to manipulate Series of type string - */ - get str() { - if (this.dtypes[0] == "string") { - return new Str(this); - } else { - throw new Error("Cannot call accessor str on non-string type"); - } - } - - /** - * Returns time class that exposes different date time method - */ - get dt() { - if (this.dtypes[0] == "string") { - return new Dt(this); - } else { - throw new Error("Cannot call accessor dt on non-string type"); - } - } - - /** - * Prints Series to console as a grid of row and columns. - */ - toString() { - const maxRow = this.$config.getMaxRow; - let indx; - let values = []; - - if (this.shape[0] > maxRow) { - //slice rows to show [max_rows] rows - const sfSlice = this.iloc([`0:${maxRow}`]); - - indx = sfSlice.index; - values = sfSlice.values; - - } else { - indx = this.index; - values = this.values; - } - - const tabledata = values.map((x, i) => [indx[i], x]); - return table(tabledata); - } - - /** - * Returns the logical AND between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - and(other) { - - if (other === undefined) { - throw new Error("Param Error: other cannot be undefined"); - } - const newValues = []; - - if (other instanceof Series) { - if (this.dtypes[0] !== other.dtypes[0]) { - throw new Error("Param Error must be of same dtype"); - } - - if (this.shape[0] !== other.shape[0]) { - throw new Error("Param Error must be of same shape"); - } - - this.values.forEach((val, i) => { - newValues.push(Boolean(val) && Boolean(other.values[i])); - }); - - } else if (Array.isArray(other)) { - - this.values.forEach((val, i) => { - newValues.push(Boolean(val) && Boolean(other[i])); - }); - - } else { - - this.values.forEach((val) => { - newValues.push(Boolean(val) && Boolean(other)); - }); - - } - - return new Series(newValues, { - index: this.index, - config: { ...this.config } - }); - } - - /** - * Returns the logical OR between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - or(other) { - - if (other === undefined) { - throw new Error("Param Error: other cannot be undefined"); - } - const newValues = []; - - if (other instanceof Series) { - if (this.dtypes[0] !== other.dtypes[0]) { - throw new Error("Param Error must be of same dtype"); - } - - if (this.shape[0] !== other.shape[0]) { - throw new Error("Param Error must be of same shape"); - } - - this.values.forEach((val, i) => { - newValues.push(Boolean(val) || (other.values[i])); - }); - - } else if (typeof other === "boolean") { - - this.values.forEach((val) => { - newValues.push(Boolean(val) || (other)); - }); - - } else if (Array.isArray(other)) { - - this.values.forEach((val, i) => { - newValues.push(Boolean(val) || (other[i])); - }); - - } else { - throw new Error("Param Error: other must be a Series, Scalar, or Array of Scalars"); - } - - return new Series(newValues, { - index: this.index, - config: { ...this.config } - }); - } - - /** - * One-hot encode values in the Series. - * @param options Options for the operation. The following options are available: - * - `prefix`: Prefix to add to the new column. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * @returns A DataFrame with the one-hot encoded columns. - * @example - * sf.get_dummies() - * sf.get_dummies({prefix: 'cat' }) - * sf.get_dummies({ prefix: 'cat', prefixSeparator: '-' }) - */ - get_dummies(options) { - return dummyEncode(this, options); - } -} diff --git a/danfojs-node/src/core/strings.js b/danfojs-node/src/core/strings.js deleted file mode 100644 index ef0f3887..00000000 --- a/danfojs-node/src/core/strings.js +++ /dev/null @@ -1,740 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; - -/** - * Exposes numerous String methods. All methods are applied Element-wise - */ -export default class Str { - constructor(series) { - this.series = series; - this.values = (series.values); - } - - /** - * Converts all characters to lowercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toLowerCase() - * console.log(newSf.values) - * // ["good", "bad", "crazy"] - * ``` - */ - toLowerCase(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.toLowerCase()); - } - - }); - - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - /** - * Converts all characters to uppercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toUpperCase() - * console.log(newSf.values) - * // ["GOOD", "BAD", "CRAZY"] - * ``` - */ - toUpperCase(options){ - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.toUpperCase()); - } - - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - - } - } - - /** - * Capitalize first string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.capitalize() - * console.log(newSf.values) - * // ["Good", "Bad", "Crazy"] - * ``` - */ - capitalize(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - let firstChar = `${val}`.slice(0, 1); - let leftChar = `${val}`.slice(1); - let newStr = `${firstChar.toUpperCase()}${leftChar.toLowerCase()}`; - newArr.push(newStr); - } - - }); - - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - /** - * Returns the character at the specified index (position) - * @param index position of character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.charAt(1) - * console.log(newSf.values) - * // ["o", "a", "r"] - * ``` - */ - charAt(index = 0, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.charAt(index)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Joins specified `other` with values in the Series. - * @param other string|values to concatenate with. - * @param position where to concat the string from. O concats from the start, 1 concats from the end. Defaults to 1. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.concat("_new") - * console.log(newSf.values) - * // ["Good_new", "bad_new", "crazy_new" - * ``` - */ - concat(other, position = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - - if (Array.isArray(other)) { - for (let i = 0; i < other.length; i++) { - let leftStr = `${this.values[i]}`; - let rightStr = `${other[i]}`; - if (position == 1) { - newArr.push(leftStr.concat(rightStr)); - } else { - newArr.push(rightStr.concat(leftStr)); - } - - } - } else { - this.values.map((val) => { - if (position == 1) { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.concat(`${other}`)); - } - - } else { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(other.concat(`${val}`)); - } - } - }); - } - - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - - } - - - /** - * Checks whether a string begins with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.startsWith("G") - * console.log(newSf.values) - * // [true, false, false] - * ``` - */ - startsWith(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.forEach((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.startsWith(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Checks whether a string ends with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.endsWith("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - endsWith(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.endsWith(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Checks whether a string contains the specified string/characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.includes("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - includes(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.includes(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Returns the position of the first occurrence of a specified value in a string. - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.indexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - indexOf(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.indexOf(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Returns the position of the last found occurrence of a specified value in a string - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.lastIndexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - lastIndexOf(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.lastIndexOf(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - - /** - * Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced - * @param searchValue String | Character value to replace - * @param replaceValue String | Character string to replace with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace("d", 7) - * console.log(newSf.values) - * // ["Goo7", "o77", "crazy"] - * ``` - */ - replace(searchValue = "", replaceValue = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.replace(searchValue, replaceValue)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Returns a new string with a specified number of copies of an existing string - * @param num Number of times to repeat - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace(2) - * console.log(newSf.values) - * // ["GoodGood", "oddodd", "crazycrazy"] - * ``` - */ - repeat(num = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.repeat(num)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - - /** - * Searches a string for a specified value, or regular expression, and returns the position of the match - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.search("d") - * console.log(newSf.values) - * ``` - */ - search(str = "", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.search(str)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Extracts a part of a string and returns a new string - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.slice(0,1) - * console.log(newSf.values) - * // ["G", "o", "c"] - * ``` - */ - slice(startIndex = 0, endIndex = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.slice(startIndex, endIndex)); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Splits a string into an values of substrings - * @param splitVal string or character to split at - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.split(d) - * console.log(newSf.values) - * ``` - */ - split(splitVal = " ", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${String(val).split(splitVal)}`); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Extracts the characters from a string, beginning at a specified start position, and through the specified number of character - * @param startIndex index position of start character - * @param num number of characters to return - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substr(d) - * ``` - */ - substr(startIndex = 0, num = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${String(val).substr(startIndex, num)}`); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Extracts the characters from a string, between two specified indices - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substring(d) - * ``` - */ - substring(startIndex = 0, endIndex = 1, options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${String(val).substring(startIndex, endIndex)}`); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Removes whitespace from both ends of a string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series([" Good", "odd ", " grade "]) - * const newSf = sf.str.trim(d) - * ["Good", "odd", "grade"] - * ``` - */ - trim(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.trim()); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Joins strings to specified value - * @param valToJoin string value to join to the values - * @param joinChar Character to Join with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.join("new", "_") - * // ["Good_new", "odd_new", "grade_new"] - * ``` - */ - join(valToJoin = "", joinChar = " ", options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - let leftChar = val; - let rightChar = valToJoin; - let new_char = `${leftChar}${joinChar}${rightChar}`; - newArr.push(new_char); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - - /** - * Counts the number of characters in string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.len(d) - * // [4,3,5] - * ``` - */ - len(options) { - const { inplace } = { inplace: false, ...options }; - const newArr = []; - this.values.map((val) => { - if (isNaN(val) && typeof val != "string") { - newArr.push(NaN); - } else { - newArr.push(`${val}`.length); - } - }); - if (inplace) { - this.series.$setValues(newArr); - this.series.print(); - } else { - const sf = this.series.copy(); - sf.$setValues(newArr); - return sf; - } - } - -} diff --git a/danfojs-node/src/index.js b/danfojs-node/src/index.js deleted file mode 100644 index f604279a..00000000 --- a/danfojs-node/src/index.js +++ /dev/null @@ -1,49 +0,0 @@ -import * as tf from "@tensorflow/tfjs-node"; -import NDframe from "./core/generic"; -import { utils } from './shared/utils'; -import Series from "./core/series"; -import DataFrame from "./core/frame"; -import { concat } from "./core/concat"; -import { merge } from "./core/merge"; -import { LabelEncoder, OneHotEncoder } from "./preprocessing/encodings"; -import { MinMaxScaler, StandardScaler } from "./preprocessing/scalers"; -import { date_range } from "./core/date_range"; -import get_dummies from "./core/get_dummies"; -import Str from "./core/strings"; -import Dt from "./core/datetime"; -import { toDateTime } from "./core/datetime"; -import { - readCSV as read_csv, - toCSV as to_csv, - readJSON as read_json, - toJSON as to_json, - readExcel as read_excel, - toExcel as to_excel } from "./io"; - - -export { - tf, - date_range, - toDateTime, - concat, - merge, - NDframe, - utils, - Str, - Dt, - Series, - DataFrame, - read_csv, - to_csv, - read_json, - to_json, - read_excel, - to_excel, - MinMaxScaler, - StandardScaler, - LabelEncoder, - OneHotEncoder, - get_dummies -}; - -export const _version = "0.3.4"; diff --git a/danfojs-node/src/io/index.js b/danfojs-node/src/io/index.js deleted file mode 100644 index 74ea0a1d..00000000 --- a/danfojs-node/src/io/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { - $readCSV, - $streamCSV, - $toCSV -} from "./io.csv"; -import { - $readJSON, - $toJSON -} from "./io.json"; -import { $readExcel, $toExcel } from "./io.excel"; - -export { - $readCSV as readCSV, - $streamCSV as streamCSV, - $toCSV as toCSV, - $readJSON as readJSON, - $toJSON as toJSON, - $readExcel as readExcel, - $toExcel as toExcel -}; diff --git a/danfojs-node/src/io/io.csv.js b/danfojs-node/src/io/io.csv.js deleted file mode 100644 index 07f50958..00000000 --- a/danfojs-node/src/io/io.csv.js +++ /dev/null @@ -1,143 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import fs from 'fs'; -import Papa from 'papaparse'; -import request from "request"; -import { DataFrame } from '../index'; - - -/** - * Reads a CSV file from local or remote location into a DataFrame. - * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, - * hence all PapaParse options are supported. - * @param options Configuration object. Supports all Papaparse parse config options. - * @returns DataFrame containing the parsed CSV file. - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv") - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv", { - * delimiter: ",", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("./data/sample.csv") - * ``` - */ -const $readCSV = async (filePath, options) => { - options = { header: true, dynamicTyping: true, ...options }; - if (filePath.startsWith("http")) { - return new Promise((resolve) => { - const dataStream = request.get(filePath); - const parseStream = Papa.parse(Papa.NODE_STREAM_INPUT, options); - dataStream.pipe(parseStream); - - const data = []; - parseStream.on("data", (chunk) => { - data.push(chunk); - }); - - parseStream.on("finish", () => { - resolve(new DataFrame(data)); - }); - }); - - } else { - return new Promise((resolve) => { - const fileStream = fs.createReadStream(filePath); - Papa.parse(fileStream, { - ...options, - complete: (results) => { - const df = new DataFrame(results.data); - resolve(df); - } - }); - }); - } -}; - - -/** - * Converts a DataFrame or Series to CSV. - * @param df DataFrame or Series to be converted to CSV. - * @param options Configuration object. Supports the following options: - * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const csv = toCSV(df) - * ``` - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toCSV(df, { - * filePath: "./data/sample.csv", - * header: true, - * sep: "+" - * }) - * ``` - */ -const $toCSV = (df, options) => { - let { filePath, sep, header } = { sep: ",", header: true, filePath: undefined, ...options }; - - if (df.$isSeries) { - const csv = df.values.join(sep); - - if (filePath !== undefined) { - if (!(filePath.endsWith(".csv"))) { - filePath = filePath + ".csv"; - } - fs.writeFileSync(filePath, csv, "utf8"); - } else { - return csv; - } - } else { - const rows = df.values; - let csvStr = header === true ? `${df.columns.join(sep)}\n` : ""; - - for (let i = 0; i < rows.length; i++) { - const row = `${rows[i].join(sep)}\n`; - csvStr += row; - } - - if (filePath !== undefined) { - if (!(filePath.endsWith(".csv"))) { - filePath = filePath + ".csv"; - } - fs.writeFileSync(filePath, csvStr, "utf8"); - } else { - return csvStr; - } - } -}; - -export { - $readCSV, - $toCSV -}; diff --git a/danfojs-node/src/io/io.excel.js b/danfojs-node/src/io/io.excel.js deleted file mode 100644 index 0ab4cc57..00000000 --- a/danfojs-node/src/io/io.excel.js +++ /dev/null @@ -1,124 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import fetch, { HeadersInit } from "node-fetch"; -import { DataFrame, NDframe, Series } from '../index'; -import XLSX from 'xlsx'; - -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param filePath URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx") - * ``` - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx", { - * method: "GET", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("./data/sample.xlsx") - * ``` - */ -const $readExcel = async (filePath, options) => { - const { sheet, method, headers } = { sheet: 0, method: "GET", headers: {}, ...options }; - - if (filePath.startsWith("http") || filePath.startsWith("https")) { - - return new Promise((resolve) => { - fetch(filePath, { method, headers }).then((response) => { - if (response.status !== 200) { - throw new Error(`Failed to load ${filePath}`); - } - response.arrayBuffer().then((arrBuf) => { - const arrBufInt8 = new Uint8Array(arrBuf); - const workbook = XLSX.read(arrBufInt8, { type: "array" }); - const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; - const data = XLSX.utils.sheet_to_json(worksheet); - const df = new DataFrame(data); - resolve(df); - }); - }).catch((err) => { - throw new Error(err); - }); - }); - - } else { - return new Promise((resolve) => { - const workbook = XLSX.readFile(filePath); - const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; - const data = XLSX.utils.sheet_to_json(worksheet); - const df = new DataFrame(data); - resolve(df); - }); - } -}; - -/** - * Converts a DataFrame or Series to Excel Sheet. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. - * @example - * ``` - * import { toExcel } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toExcel(df, { - * filePath: "./data/sample.xlsx", - * sheetName: "MySheet", - * }) - * ``` - */ -const $toExcel = (df, options) => { - let { filePath, sheetName } = { filePath: "./output.xlsx", sheetName: "Sheet1", ...options }; - - if (!(filePath.endsWith(".xlsx"))) { - filePath = filePath + ".xlsx"; - } - let data; - - if (df.$isSeries) { - const row = df.values; - const col = df.columns; - data = [col, ...(row.map((x) => [x]))]; - } else { - const row = df.values; - const cols = df.columns; - data = [cols, ...row]; - } - - const worksheet = XLSX.utils.aoa_to_sheet(data); - const wb = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(wb, worksheet, sheetName); - XLSX.writeFile(wb, `${filePath}`); -}; - -export { - $readExcel, - $toExcel -}; diff --git a/danfojs-node/src/io/io.json.js b/danfojs-node/src/io/io.json.js deleted file mode 100644 index 13f5a571..00000000 --- a/danfojs-node/src/io/io.json.js +++ /dev/null @@ -1,149 +0,0 @@ -import fs from 'fs'; -import fetch from "node-fetch"; -import { DataFrame } from '../index'; - -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param filePath URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json") - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json", { - * headers: { - * Accept: "text/json", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("./data/sample.json") - * ``` - */ -const $readJSON = async (filePath, options) => { - const { method, headers } = { method: "GET", headers: {}, ...options }; - - if (filePath.startsWith("http") || filePath.startsWith("https")) { - - return new Promise((resolve) => { - fetch(filePath, { method, headers }).then((response) => { - if (response.status !== 200) { - throw new Error(`Failed to load ${filePath}`); - } - response.json().then((json) => { - resolve(new DataFrame(json)); - }); - }).catch((err) => { - throw new Error(err); - }); - }); - - } else { - return new Promise((resolve) => { - const file = fs.readFileSync(filePath, "utf8"); - const df = new DataFrame(JSON.parse(file)); - resolve(df); - }); - } -}; - - -/** - * Converts a DataFrame or Series to JSON. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const json = toJSON(df) - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toJSON(df, { - * filePath: "./data/sample.json", - * format: "row" - * }) - * ``` - */ -const $toJSON = (df, options) => { - let { filePath, format } = { filePath: undefined, format: "column", ...options }; - - if (df.$isSeries) { - const obj = {}; - obj[df.columns[0]] = df.values; - if (filePath) { - if (!filePath.endsWith(".json")) { - filePath = filePath + ".json"; - } - fs.writeFileSync(filePath, JSON.stringify(obj)); - } else { - return obj; - } - } else { - const values = df.values; - const header = df.columns; - const jsonArr = []; - - if (format === "row") { - const obj = {}; - for (let i = 0; i < df.columns.length; i++) { - obj[df.columns[i]] = (df).column(df.columns[i]).values; - } - if (filePath !== undefined) { - if (!(filePath.endsWith(".json"))) { - filePath = filePath + ".json"; - } - - fs.writeFileSync(filePath, JSON.stringify(obj), "utf8"); - } else { - return obj; - } - } else { - values.forEach((val) => { - const obj = {}; - header.forEach((h, i) => { - obj[h] = val[i]; - }); - jsonArr.push(obj); - }); - if (filePath) { - if (!filePath.endsWith(".json")) { - filePath = filePath + ".json"; - } - fs.writeFileSync(filePath, JSON.stringify(jsonArr)); - } else { - return jsonArr; - } - } - } -}; - - -export { - $readJSON, - $toJSON -}; diff --git a/danfojs-node/src/plotting/plot.js b/danfojs-node/src/plotting/plot.js deleted file mode 100644 index 643908a1..00000000 --- a/danfojs-node/src/plotting/plot.js +++ /dev/null @@ -1,867 +0,0 @@ -/* eslint-disable no-undef */ -import { utils } from "../shared/utils"; -import Series from "../core/series"; - -/** - * Change: Rising Odegua 6th Feb 2021 - * We no longer bundle Plotjs with DanfoJs. I noticed that removing this single - * inport reduces the bundle size from 5.7mb to 2.1mb. I know it's still a huge - * bundle, but it's progress! - * If you need to use Plotly, then you can add the Plotly CDN - * to your script before DanfoJs CDN - */ -try { - const version = Plotly.version; - console.info(`Using Plotly version ${version}`); -} catch (error) { - console.info(`Plotly CDN not found. If you need to make Plots, then add the Plotly CDN to your script`); -} - -/** - * Plotting methods and Functions performed on Series and DataFrames - */ -export class Plot { - constructor(ndframe, div) { - this.div = div; - this.ndframe = ndframe; - } - - - /** - * Plot Series or DataFrame as lines. This function is useful to plot lines using DataFrame’s values as coordinates. - * Make plots of Series or DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - line(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!(param == "layout")) { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "line"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - if (utils.keyInObject(this_config, 'x')) { - trace["x"] = this.ndframe[this_config['x']].values; - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - } else { - trace["y"] = this.ndframe[this_config['y']].values; - trace["x"] = this.ndframe[c_name].values; - trace['name'] = c_name; - } - - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - trace["x"] = this.ndframe.index; - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot Series or DataFrame as Bars. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - bar(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "bar"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = "bar"; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['y'] = this.ndframe[this_config['x']].values; - } else { - trace['y'] = this.ndframe[this_config['y']].values; - } - trace['type'] = "bar"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - // params.forEach(param => { //TODO accept individual configuration for traces - // trace[param] = config[param] - // }) - trace['x'] = this.ndframe.index; - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = "bar"; - - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot two or more columns in a DataFrame as scatter points. If Series, plot against its index - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - scatter(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["x"] = this.ndframe.values; - trace['y'] = this.ndframe.index; - trace['type'] = "scatter"; - trace['mode'] = "markers"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = "scatter"; - trace['mode'] = "markers"; - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['y'] = this.ndframe.index; - trace['x'] = this.ndframe[this_config['x']].values; - - } else { - trace['x'] = this.ndframe.index; - trace['y'] = this.ndframe[this_config['y']].values; - - } - trace['type'] = "scatter"; - trace['mode'] = "markers"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - // params.forEach(param => { //TODO accept individual configuration for traces - // trace[param] = config[param] - // }) - trace['y'] = this.ndframe.index; - trace["x"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = "scatter"; - trace['mode'] = "markers"; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot columns in a Series/DataFrame as Histograms. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - hist(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["x"] = this.ndframe.values; - trace['type'] = "histogram"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x')) { - //plot as vertical histogram - let trace = {}; - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace['x'] = this.ndframe[this_config['x']].values; - trace['type'] = "histogram"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'y')) { - //plot as vertical histogram - let trace = {}; - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace['y'] = this.ndframe[this_config['y']].values; - trace['type'] = "histogram"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - trace["x"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = "histogram"; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - /** - * Makes Pie Plots from two Columns in a DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - pie(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - - - if (this.ndframe instanceof Series) { - let data = [{ - values: this.ndframe.values, - labels: this.ndframe.index, - type: 'pie', - name: this_config['labels'], - hoverinfo: 'label+percent+name', - automargin: true - }]; - - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'values') && utils.keyInObject(this_config, 'labels')) { - if (!this.ndframe.columns.includes(this_config['labels'])) { - throw Error(`Column Error: ${this_config['labels']} not found in columns. labels name must be one of [ ${this.ndframe.columns}]`); - } - if (!this.ndframe.columns.includes(this_config['values'])) { - throw Error(`Column Error: ${this_config['values']} not found in columns. value name must be one of [ ${this.ndframe.columns}]`); - } - let data = [{ - values: this.ndframe[this_config['values']].values, - labels: this.ndframe[this_config['labels']].values, - type: 'pie', - name: this_config['labels'], - hoverinfo: 'label+percent+name', - automargin: true - }]; - - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } else { - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - if (utils.keyInObject(this_config, 'row_pos')) { - if (this_config['row_pos'].length != cols_to_plot.length - 1) { - throw Error(`Lenght of row_pos array must be equal to number of columns. Got ${this_config['row_pos'].length}, expected ${cols_to_plot.length - 1}`); - } - } else { - let temp_arr = []; - for (let i = 0; i < cols_to_plot.length - 1; i++) { - temp_arr.push(0); - } - this_config['row_pos'] = temp_arr; - - } - - if (utils.keyInObject(this_config, 'col_pos')) { - if (this_config['col_pos'].length != cols_to_plot.length - 1) { - throw Error(`Lenght of col_pos array must be equal to number of columns. Got ${this_config['col_pos'].length}, expected ${cols_to_plot.length - 1}`); - } - } else { - let temp_arr = []; - for (let i = 0; i < cols_to_plot.length - 1; i++) { - temp_arr.push(i); - } - this_config['col_pos'] = temp_arr; - - } - let data = []; - - cols_to_plot.forEach((c_name, i) => { - let trace = {}; - trace["values"] = this.ndframe[c_name].values; - trace['labels'] = this.ndframe[this_config['labels']].values; - trace['name'] = c_name; - trace['type'] = "pie"; - trace['domain'] = { row: this_config['row_pos'][i], column: this_config['col_pos'][i] }; - trace["hoverinfo"] = 'label+percent+name'; - trace['textposition'] = "outside"; - trace['automargin'] = true; - data.push(trace); - - }); - - if (!utils.keyInObject(this_config, "grid")) { - //set default grid - let size = Number((this.ndframe.shape[1] / 2).toFixed()) + 1; - this_config['grid'] = { rows: size, columns: size }; - } - this_config['layout']['grid'] = this_config['grid']; - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - - } - - } - - - /** - * Plot Box plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - box(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "box"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = 'box'; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['x'] = this.ndframe[this_config['x']].values; - trace['y'] = this.ndframe.index; - trace['type'] = 'box'; - } else { - trace['x'] = this.ndframe.index; - trace['y'] = this_config['y']; - trace['type'] = 'box'; - } - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - trace["x"] = this.ndframe[c_name].values; - trace["y"] = this.ndframe.index; - trace['name'] = c_name; - trace['type'] = 'box'; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - - /** - * Plot Violin plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - violin(config = {}) { - - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let params = ret_params[1]; - - if (this.ndframe instanceof Series) { - let trace = {}; - let y = this.ndframe.values; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - trace["y"] = y; - trace['type'] = "violin"; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //check if plotting two columns against each other - if (utils.keyInObject(this_config, 'x') && utils.keyInObject(this_config, 'y')) { - if (!this.ndframe.columns.includes(this_config['x'])) { - throw Error(`Column Error: ${this_config['x']} not found in columns`); - } - if (!this.ndframe.columns.includes(this_config['y'])) { - throw Error(`Column Error: ${this_config['y']} not found in columns`); - } - - - let x = this.ndframe[this_config['x']].values; - let y = this.ndframe[this_config['y']].values; - - let trace = {}; - trace["x"] = x; - trace['y'] = y; - trace['type'] = 'violin'; - - - let xaxis = {}; let yaxis = {}; - xaxis['title'] = this_config['x']; - yaxis['title'] = this_config['y']; - - this_config['layout']['xaxis'] = xaxis; - this_config['layout']['yaxis'] = yaxis; - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else if (utils.keyInObject(this_config, 'x') || utils.keyInObject(this_config, 'y')) { - //plot single column specified in either of param [x | y] against index - let trace = {}; - - params.forEach((param) => { - if (!param == "layout") { - trace[param] = config[param]; - } - }); - - if (utils.keyInObject(this_config, 'x')) { - trace['x'] = this.ndframe[this_config['x']].values; - trace['y'] = this.ndframe.index; - trace['type'] = 'violin'; - } else { - trace['x'] = this.ndframe.index; - trace['y'] = this_config['y']; - trace['type'] = 'violin'; - } - - Plotly.newPlot(this.div, [trace], this_config['layout'], this_config); - - } else { - //plot columns against index - let data = []; - let cols_to_plot; - - if (utils.keyInObject(this_config, "columns")) { - cols_to_plot = this.____check_if_cols_exist(this_config['columns']); - } else { - cols_to_plot = this.ndframe.columns; - } - - cols_to_plot.forEach((c_name) => { - let trace = {}; - - params.forEach((param) => { //TODO accept individual configuration for traces - trace[param] = config[param]; - }); - trace["y"] = this.ndframe[c_name].values; - trace['name'] = c_name; - trace['type'] = 'violin'; - data.push(trace); - - }); - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - } - - - } - - /** - * Display DataFrame in a div using D3.js format - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - table(config = {}) { - let ret_params = this.__get_plot_params(config); - let this_config = ret_params[0]; - let header = {}; - let cells = {}; - let cols_data = []; - let cols_2_show; - - - if (utils.keyInObject(this_config, 'columns')) { - - this_config['columns'].forEach((cname) => { - if (!this.ndframe.columns.includes(cname)) { - throw Error(`Column Error: ${cname} not found in columns. Columns should be one of [ ${this.ndframe.columns} ]`); - } - - let idx = this.ndframe.columns.indexOf(cname); - cols_data.push(this.ndframe.getColumnData[idx]); - }); - cols_2_show = this_config['columns']; - } else { - - cols_2_show = this.ndframe.columns; - cols_data = this.ndframe.getColumnData; - - } - - header['values'] = cols_2_show.map((col) => [col]); - cells['values'] = cols_data; - - if (this_config['header_style']) { - Object.keys(this_config['header_style']).forEach((param) => { - header[param] = this_config['header_style'][param]; - }); - } - - if (this_config['cell_style']) { - Object.keys(this_config['cell_style']).forEach((param) => { - cells[param] = this_config['cell_style'][param]; - }); - } - var data = [{ - type: 'table', - header: header, - cells: cells - }]; - Plotly.newPlot(this.div, data, this_config['layout'], this_config); - - } - - - __get_plot_params(config) { - let params = Object.keys(config); - let this_config = {}; - - params.forEach((param) => { - this_config[param] = config[param]; - }); - - if (!utils.keyInObject(config, "layout")) { - this_config['layout'] = {}; - } - - - return [this_config, params]; - - } - - ____check_if_cols_exist(cols) { - cols.forEach((col) => { - if (!this.ndframe.columns.includes(col)) { - throw Error(`Column Error: ${col} not found in columns. Columns should be one of [ ${this.ndframe.columns} ]`); - } - }); - return cols; - } - - -} diff --git a/danfojs-node/src/preprocessing/encodings.js b/danfojs-node/src/preprocessing/encodings.js deleted file mode 100644 index 49b507ef..00000000 --- a/danfojs-node/src/preprocessing/encodings.js +++ /dev/null @@ -1,106 +0,0 @@ -import Series from "../core/series"; -import DataFrame from "../core/frame"; -import { utils } from "../shared/utils"; - -export class LabelEncoder { - - /** - * - * @param {data} data [Array|Series] - * @returns Array. - */ - fit(data) { - let in_data = null; - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array or a Series"); - } - - let data_set = new Set(in_data); - this.label = Array.from(data_set); - - let self = this; - let output_data = in_data.map((x) => { - return self.label.indexOf(x); - }); - - return new Series(output_data); - } - - /** - * Transform data using the label generated from fitting - * @param {data} data [Array|Series] - * @returns Array - */ - transform(data) { - let in_data = null; - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array or a Series"); - } - - let self = this; - let output_data = in_data.map((x) => { - return self.label.indexOf(x); - }); - return new Series(output_data); - } -} - -export class OneHotEncoder { - - fit(data) { - let in_data = null; - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array"); - } - - let data_set = new Set(in_data); - this.label = Array.from(data_set); - - let onehot_data = utils.zeros(in_data.length, this.label.length); - - for (let i = 0; i < in_data.length; i++) { - - let elem = in_data[i]; - let elem_index = this.label.indexOf(elem); - onehot_data[i][elem_index] = 1; - } - - return new DataFrame(onehot_data, { columns: this.label }); - - } - - transform(data) { - let in_data = null; - - if (Array.isArray(data)) { - in_data = data; - } else if (data instanceof Series) { - in_data = data.values; - } else { - throw new Error("data must be an array"); - } - - let onehot_data = utils.zeros(in_data.length, this.label.length); - - for (let i = 0; i < in_data.length; i++) { - let elem = in_data[i]; - let elem_index = this.label.indexOf(elem); - onehot_data[i][elem_index] = 1; - } - - return new DataFrame(onehot_data, { columns: this.label }); - - } -} diff --git a/danfojs-node/src/preprocessing/scalers.js b/danfojs-node/src/preprocessing/scalers.js deleted file mode 100644 index 285ec7be..00000000 --- a/danfojs-node/src/preprocessing/scalers.js +++ /dev/null @@ -1,342 +0,0 @@ -import { tensor, moments } from "@tensorflow/tfjs-node"; -import Series from "../core/series"; -import DataFrame from "../core/frame"; -import { utils } from "../shared/utils"; - -export class MinMaxScaler { - /** - * Fit minmax scaler on data, to obtain their min and max value - * @param {data} data [DataFrame | Series | Array] - * @returns Array - */ - fit(data) { - let tensor_data = null; - if (Array.isArray(data)) { - tensor_data = tensor(data); - } else if (data instanceof DataFrame || data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - tensor_data = tensor(data.values); - } else { - throw new Error("data must either be an Array, DataFrame or Series"); - } - - this.max = tensor_data.max(0); - this.min = tensor_data.min(0); - - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - - if (data instanceof Series || Array.isArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } - - /** - * Transform an array using the min and max generated from the fitting on data - * @param {data} data [Array] - * @returns array - */ - transform(data) { - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .sub(this.min) - .div(this.max.sub(this.min)) - .arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } - - /** - * Restore a transformed array to their original values, - * using the min and max generated from the fitting on data - * @param {Series|Array|DataFrame} data - * @returns Series|DataFrame - */ - inverse_transform(data) { - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .mul(this.max.sub(this.min)) - .add(this.min) - .arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data - .mul(this.max.sub(this.min)) - .add(this.min) - .arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data - .mul(this.max.sub(this.min)) - .add(this.min) - .arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } -} - -export class StandardScaler { - /** - * - * @param {data} data [DataFame | Series | Array] - * @returns Array - */ - fit(data) { - let tensor_data = null; - if (Array.isArray(data)) { - tensor_data = tensor(data); - } else if (data instanceof DataFrame || data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - tensor_data = tensor(data.values); - } else { - throw new Error("data must either be an Array, DataFrame or Series"); - } - - this.std = moments(tensor_data, 0).variance.sqrt(); - this.mean = tensor_data.mean(0); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - - if (data instanceof Series || Array.isArray(data)) { - return new Series((data = output_data)); - } else { - return new DataFrame((data = output_data)); - } - } - - transform(data) { - // if(!Array.isArray(data)){ - // throw new Error(data) - // } - - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.sub(this.mean).div(this.std).arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } - - /** - * Restore a transformed array to their original values, - * using the mean and std generated from the fitting on data - * @param {Series|Array|DataFrame} data - * @returns Series|DataFrame - */ - inverse_transform(data) { - if (data instanceof Series) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.mul(this.std).add(this.mean).arraySync(); - return new Series(output_data); - } else if (Array.isArray(data)) { - let tensor_data = tensor(data); - let output_data = tensor_data.mul(this.std).add(this.mean).arraySync(); - if (utils.is1DArray(data)) { - return new Series(output_data); - } else { - return new DataFrame(output_data); - } - } else if (data instanceof DataFrame) { - if (data.dtypes.includes("string")) { - throw Error("Dtype Error: Cannot perform operation on string dtypes"); - } - let tensor_data = tensor(data.values); - let output_data = tensor_data.mul(this.std).add(this.mean).arraySync(); - return new DataFrame(output_data); - } else { - throw Error("Value Error: Data type not supported"); - } - } -} - -// export class RobustScaler{ - -// __median(arr, isTensor,return_index) { -// if (!isTensor) { -// const sorted = arr.slice().sort((a, b) => a - b); -// const middle = Math.floor(sorted.length / 2); - -// if (sorted.length % 2 === 0) { - -// return return_index ? [(middle - 1) , middle] : (sorted[middle - 1] + sorted[middle]) / 2; -// } - -// return return_index ? middle : sorted[middle] ; -// } else { -// let result_arr = [] -// arr.map(ele => { -// const sorted = ele.slice().sort((a, b) => a - b); -// const middle = Math.floor(sorted.length / 2); - -// if (sorted.length % 2 === 0) { -// result_arr.push(return_index ? [(middle - 1) , middle] :(sorted[middle - 1] + sorted[middle]) / 2 ) -// } else { -// result_arr.push(return_index ? middle : sorted[middle]) -// } - -// }) -// return result_arr -// } - -// } - -// quantile(data,isTensor){ - -// if(isTensor){ -// data = utils.__get_col_values(data); -// } - -// let median = this.__median(data,isTensor,true) -// let med = this.__median(data,isTensor,false) - -// let q1 = [] -// let q2 = [] - -// if(!isTensor){ -// let sorted = data.slice().sort((a, b) => a - b); - -// if(Array.isArray(median)){ -// let lower = median[0] -// let lower_data = sorted.slice(0,lower+1) -// let upper_data = sorted.slice(lower+1,) - -// q1.push(this.__median(lower_data,isTensor,false)); -// q2.push(this.__median(upper_data,isTensor,false)); - -// }else{ -// let lower_data = sorted.slice(0,median) -// let upper_data = sorted.slice(median+1,) - -// q1.push(this.__median(lower_data,isTensor,false)); -// q2.push(this.__median(upper_data,isTensor,false)); -// } - -// }else{ - -// data.map((x,i)=>{ -// let sorted = x.slice().sort((a, b) => a - b); - -// if(Array.isArray(median[i])){ -// let lower = median[i][0] -// let lower_data = sorted.slice(0,lower+1) -// let upper_data = sorted.slice(lower+1,) - -// q1.push(this.__median(lower_data,!isTensor,false)); -// q2.push(this.__median(upper_data,!isTensor,false)); - -// }else{ -// let lower_data = sorted.slice(0,median[i]) -// let upper_data = sorted.slice(median[i]+1,) - -// q1.push(this.__median(lower_data,!isTensor,false)); -// q2.push(this.__median(upper_data,!isTensor,false)); -// } - -// }) -// } - -// return [q1,q2, med] - -// } - -// /** -// * Fit robust scalar on data to obtain the first quantile and third quantile -// * @param {data} data [DataFrame | Series | Array] -// * @returns Array -// */ -// fit(data){ - -// let tensor_data = null -// let isTensor = false; -// if(Array.isArray(data)){ -// tensor_data = tensor(data) -// } -// else if((data instanceof DataFrame)){ -// tensor_data = tensor(data.values) -// isTensor = true; -// } -// else if((data instanceof Series)){ -// tensor_data = tensor(data.values) -// } -// else{ -// throw new Error("data must either be an Array, DataFrame or Series") -// } - -// let [q1, q3, median] = this.quantile(data,isTensor) -// let q3_tensor = tensor(q3) -// let output_data = tensor_data.sub(median).div(q3_tensor.sub(q1)).arraySync() - -// return output_data; -// } -// } diff --git a/danfojs-node/src/shared/config.js b/danfojs-node/src/shared/config.js deleted file mode 100644 index 40f011c5..00000000 --- a/danfojs-node/src/shared/config.js +++ /dev/null @@ -1,83 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -/** - * Package wide configuration class - */ -export default class Configs { - - constructor(options) { - const { - tableDisplayConfig, - tableMaxRow, - tableMaxColInConsole, - dtypeTestLim, - lowMemoryMode - } = { - tableDisplayConfig: {}, - tableMaxRow: 10, - tableMaxColInConsole: 21, - dtypeTestLim: 10, - lowMemoryMode: false, - ...options - }; - this.tableDisplayConfig = tableDisplayConfig; - this.tableMaxRow = tableMaxRow; // The maximum number of rows to display in console - this.tableMaxColInConsole = tableMaxColInConsole; // The maximum number of columns to display in console - this.dtypeTestLim = dtypeTestLim; // The number of rows to use when inferring data type - this.lowMemoryMode = lowMemoryMode; // Whether to use minimal memory or not. - } - - setTableDisplayConfig(config) { - this.tableDisplayConfig = config; - } - - get getTableDisplayConfig() { - return this.tableDisplayConfig; - } - - setTableMaxColInConsole(val) { - this.tableMaxColInConsole = val; - } - - get getTableMaxColInConsole() { - return this.tableMaxColInConsole; - } - - setMaxRow(val) { - this.tableMaxRow = val; - } - - get getMaxRow() { - return this.tableMaxRow; - } - - get getDtypeTestLim() { - return this.dtypeTestLim; - } - - setDtypeTestLim(val) { - this.dtypeTestLim = val; - } - - get isLowMemoryMode() { - return this.lowMemoryMode; - } - - setIsLowMemoryMode(val) { - this.lowMemoryMode = val; - } -} - diff --git a/danfojs-node/src/shared/errors.js b/danfojs-node/src/shared/errors.js deleted file mode 100644 index ebd91219..00000000 --- a/danfojs-node/src/shared/errors.js +++ /dev/null @@ -1,93 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -/** - * Package wide error throwing class - */ -class ErrorThrower { - - throwColumnNamesLengthError(ndframe, columns){ - const msg = `ParamError: Column names length mismatch. You provided a column of length ${columns.length} but Ndframe columns has lenght of ${ndframe.shape[1]}`; - throw new Error(msg); - } - - throwIndexLengthError(ndframe, index){ - const msg = `IndexError: You provided an index of length ${index.length} but Ndframe rows has lenght of ${ndframe.shape[0]}`; - throw new Error(msg); - } - - throwIndexDuplicateError(){ - const msg = `IndexError: Row index must contain unique values`; - throw new Error(msg); - } - - throwColumnDuplicateError(){ - const msg = `ColumnIndexError: Column index must contain unique values`; - throw new Error(msg); - } - - throwDtypesLengthError(ndframe, dtypes){ - const msg = `DtypeError: You provided a dtype array of length ${dtypes.length} but Ndframe columns has lenght of ${ndframe.shape[1]}`; - throw new Error(msg); - } - - throwDtypeNotSupportedError (dtype){ - const msg = `DtypeError: Dtype "${dtype}" not supported. dtype must be one of "${DATA_TYPES}"`; - throw new Error(msg); - } - - throwColumnLengthError(ndframe, arrLen){ - const msg = `ParamError: Column data length mismatch. You provided data with length ${arrLen} but Ndframe has column of lenght ${ndframe.shape[1]}`; - throw new Error(msg); - } - - throwRowLengthError(ndframe, arrLen){ - const msg = `ParamError: Row data length mismatch. You provided data with length ${arrLen} but Ndframe has row of lenght ${ndframe.shape[0]}`; - throw new Error(msg); - } - - throwColumnNotFoundError(ndframe){ - const msg = `ParamError: Column not found!. Column name must be one of ${ndframe.columns}`; - throw new Error(msg); - } - - throwNotImplementedError(){ - const msg = `Method not implemented`; - throw new Error(msg); - } - - throwIlocRowIndexError(){ - const msg = `ParamError: rows parameter must be a Array. For example: rows: [1,2] or rows: ["0:10"]`; - throw new Error(msg); - } - - throwIlocColumnsIndexError(){ - const msg = `ParamError: columns parameter must be a Array. For example: columns: [1,2] or columns: ["0:10"]`; - throw new Error(msg); - } - - throwStringDtypeOperationError(operation){ - const msg = `DtypeError: String data type does not support ${operation} operation`; - throw new Error(msg); - } - - throwSeriesMathOpLengthError(ndframe, other){ - const msg = `ParamError: Row length mismatch. Length of other (${other.shape[0]}), must be the same as Ndframe (${ndframe.shape[0]})`; - throw new Error(msg); - } - -} - -export default new ErrorThrower(); diff --git a/danfojs-node/src/shared/utils.js b/danfojs-node/src/shared/utils.js deleted file mode 100644 index 5d3ec866..00000000 --- a/danfojs-node/src/shared/utils.js +++ /dev/null @@ -1,798 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ - -import { BASE_CONFIG } from './defaults'; -import Config from './config'; -import { Series } from '..'; -import { DataFrame } from '..'; -import ErrorThrower from './errors'; - -const config = new Config(BASE_CONFIG); - -/** - * Utility class for working with Frames and Series - */ -class Utils { - /** - * Removes an element from a 1D array - * - * ```js - * - * ``` - * @param arr The array to filter. - * @param index The index to filter by. - */ - removeElementFromArray(arr, index) { - const newArr = arr.filter((_, i) => i != index); - return newArr; - } - - /** - * Check if value is a string. - * @param value The value to check. - * @returns - */ - isString(value) { - return typeof value === "string"; - } - - /** - * Checks if value is a number. - * @param value The value to check. - * @returns - */ - isNumber(value) { - return typeof value === "number" && isFinite(value); - } - - /** - * Checks if value is an object. - * @param value The value to check. - * @returns - */ - isObject(value) { - return typeof value === "object" && value.constructor && value.constructor.name === "Object"; - } - - /** - * Checks if a value is null - * @param value The value to check. - * @returns - */ - isNull(value) { - return value === null; - } - - /** - * Checks if a value is undefined - * @param value The value to check. - * @returns - */ - isUndefined(value) { - return typeof value === "undefined"; - } - - /** - * Checks if a value is empty. Empty means it's either null, undefined or NaN - * @param value The value to check. - * @returns - */ - isEmpty(value) { - return value === undefined || value === null || (isNaN(value) && typeof value !== "string"); - } - - /** - * Generates an array of integers between specified range - * @param start The starting number. - * @param end The ending number. - */ - range(start, end) { - if (end < start) { - throw new Error("ParamError: end must be greater than start"); - } - - if (start === end) { - return [start]; - } - - const arr = []; - for (let i = start; i <= end; i++) { - arr.push(i); - } - return arr; - } - - /** - * Checks if object has the specified key - * @param obj The object to check. - * @param key The key to find. - */ - keyInObject(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - } - - /** - * Transposes an array of array - * @param obj The object to check. - * @param key The key to find. - */ - transposeArray(arr) { //old name: __get_col_values - if (arr.length === 0) return arr; - - const rowLen = arr.length; - if (Array.isArray(arr[0])) { - const colLen = arr[0].length; - const newArr = []; - - for (let i = 0; i <= colLen - 1; i++) { - const temp = []; - for (let j = 0; j < rowLen; j++) { - const _elem = (arr)[j][i]; - temp.push(_elem); - } - newArr.push(temp); - } - return newArr; - } else { - return arr; - } - } - - /** - * Retrieve row array and column names from an object of the form {a: [1,2,3,4], b: [30,20, 30, 20]} - * @param obj The object to retrieve rows and column names from. - */ - getRowAndColValues(obj) { - const colNames = Object.keys(obj); - const colData = Object.values(obj); - const firstColLen = colData[0].length; - - colData.forEach((cdata) => { - if (cdata.length != firstColLen) { - throw Error("Length Error: Length of columns must be the same!"); - } - }); - - const rowsArr = this.transposeArray(colData); - return [rowsArr, colNames]; - } - - /** - * Converts a 2D array of array to 1D array for Series Class - * @param arr The array to convert. - */ - convert2DArrayToSeriesArray(arr) { - const newArr = arr.map((val) => { - if (this.isObject(val)) { - return JSON.stringify(val); - } else { - return `${val}`; - } - }); - return newArr; - } - - /** - * Replaces all missing values with NaN. Missing values are undefined, Null and Infinity - * @param arr The array - * @param isSeries Whether the arr is a series or not - */ - replaceUndefinedWithNaN(arr, isSeries) { - if (arr.length === 0) return arr; - - if (isSeries && Array.isArray(arr)) { - const newArr = arr.map((ele) => { - if (typeof ele === "undefined") { - return NaN; - } - if (typeof ele === "number" && (isNaN(ele) || ele == Infinity)) { - return NaN; - } - if (ele == null) { - return NaN; - } - return ele; - }); - return newArr; - } else { - const newArr = []; - if (Array.isArray(arr)) { - for (let i = 0; i < arr.length; i++) { - const innerArr = arr[i]; - const temp = (innerArr).map((ele) => { - if (typeof ele === "undefined") { - return NaN; - } - if (typeof ele === "number" && (isNaN(ele) || ele == Infinity)) { - return NaN; - } - if (ele == null) { - return NaN; - } - return ele; - }); - newArr.push(temp); - } - } - return newArr; - } - } - - /** - * Infer data type from an array or array of arrays - * @param arr An array or array of arrays - */ - inferDtype(arr) { - const self = this; - if (this.is1DArray(arr)) { - return [this.$typeChecker(arr)]; - } else { - const arrSlice = this.transposeArray(arr.slice(0, config.getDtypeTestLim)); - const dtypes = arrSlice.map((innerArr) => { - return self.$typeChecker(innerArr); - }); - return dtypes; - } - } - - /** - * Private type checker used by inferDtype function - * @param arr The array - */ - $typeChecker(arr) { - let dtypes; - let lim; - let intTracker = []; - let floatTracker = []; - let stringTracker = []; - let boolTracker = []; - - if (arr.length < config.getDtypeTestLim) { - lim = arr.length; - } else { - lim = config.getDtypeTestLim; - } - - const arrSlice = arr.slice(0, lim); - - for (let i = 0; i < lim; i++) { - const ele = arrSlice[i]; - if (typeof ele == "boolean") { - floatTracker.push(false); - intTracker.push(false); - stringTracker.push(false); - boolTracker.push(true); - } else if (this.isEmpty(ele)) { - floatTracker.push(true); - intTracker.push(false); - stringTracker.push(false); - boolTracker.push(false); - } else if (!isNaN(Number(ele))) { - if ((ele).toString().includes(".")) { - floatTracker.push(true); - intTracker.push(false); - stringTracker.push(false); - boolTracker.push(false); - } else { - floatTracker.push(false); - intTracker.push(true); - stringTracker.push(false); - boolTracker.push(false); - } - } else { - floatTracker.push(false); - intTracker.push(false); - stringTracker.push(true); - boolTracker.push(false); - } - } - - const even = (ele) => ele == true; - - if (stringTracker.some(even)) { - dtypes = "string"; - } else if (floatTracker.some(even)) { - dtypes = "float32"; - } else if (intTracker.some(even)) { - dtypes = "int32"; - } else if (boolTracker.some(even)) { - dtypes = "boolean"; - } else { - dtypes = "undefined"; - } - - return dtypes; - } - - /** - * Returns the unique values in an 1D array - * @param arr The array - */ - unique(arr) { - const uniqueArr = new Set(arr); - return Array.from(uniqueArr); - } - - /** - * Checks if array is 1D - * @param arr The array - */ - is1DArray(arr) { - if ( - typeof arr[0] == "number" || - typeof arr[0] == "string" || - typeof arr[0] == "boolean" - ) { - return true; - } else { - return false; - } - } - - /** - * Converts an array to an object using array index as object keys - * @param arr The array - */ - convertArrayToObject(arr) { - const arrObj = {}; - for (let i = 0; i < arr.length; i++) { - arrObj[i] = arr[i]; - - } - return arrObj; - } - - /** - * Count the NaN and non-NaN values present in an array - * @param arr Array object - * @param val whether to return the value count instead of the null count - * @param isSeries Whether the array is of type series or not - */ - countNaNs(arr, returnVal = true, isSeries) { - if (isSeries) { - let nullCount = 0; - let valCount = 0; - for (let i = 0; i < arr.length; i++) { - const ele = arr[i]; - if (Number.isNaN(ele)) { - nullCount = nullCount + 1; - } else { - valCount = valCount + 1; - } - - } - if (returnVal) { - return valCount; - } else { - return nullCount; - } - } else { - const resultArr = []; - for (let i = 0; i < arr.length; i++) { - const innerArr = arr[i]; - let nullCount = 0; - let valCount = 0; - for (let i = 0; i < (innerArr).length; i++) { - const ele = (innerArr)[i]; - if (Number.isNaN(ele)) { - nullCount = nullCount + 1; - } else { - valCount = valCount + 1; - } - } - - if (returnVal) { - resultArr.push(valCount); - } else { - resultArr.push(nullCount); - } - } - return resultArr; - } - } - - /** - * Round elements of an array or array of arrays to specified dp - * @param arr The Array to round - * @param dp The number of dp to round to - * @param isSeries Whether the array is of type Series or not - */ - round(arr, dp = 1, isSeries) { - - if (isSeries) { - const newArr = []; - for (let i = 0; i < arr.length; i++) { - const ele = arr[i]; - - if (typeof ele == "number" && !isNaN(ele) && ele !== undefined && ele !== null) { - newArr.push(Number((ele).toFixed(dp))); - } else { - newArr.push(ele); - } - } - return newArr; - } else { - const resultArr = []; - for (let i = 0; i < arr.length; i++) { - const innerVal = arr[i]; - const newArr = []; - if (Array.isArray(innerVal)) { - for (let i = 0; i < innerVal.length; i++) { - const ele = innerVal[i]; - if (typeof ele == "number" && !isNaN(ele) && ele !== undefined && ele !== null) { - newArr.push(Number((ele).toFixed(dp))); - } else { - newArr.push(ele); - } - } - resultArr.push(newArr); - } else { - if (typeof innerVal == "number" && !isNaN(innerVal) && innerVal !== undefined && innerVal !== null) { - newArr.push(Number((innerVal).toFixed(dp))); - } else { - newArr.push(innerVal); - } - } - - } - return resultArr; - } - } - - /** - * Checks if a func is a function - * @param func - */ - isFunction(func) { - return typeof func == "function"; - } - - /** - * Generates n random numbers between start and end. - * @param start - * @param end - * @param size - */ - randNumberGenerator(start, end, size) { - let genNum = []; - - function randi(a, b) { - return Math.floor(Math.random() * (b - a) + a); - } - - function recursive(val, arr) { - if (!arr.includes(val)) { - return val; - } - val = randi(start, end); - recursive(val, arr); - } - - for (let i = 0; i < size; i++) { - let genVal = randi(start, end); - let recursiveVal = recursive(genVal, genNum); - genNum.push(recursiveVal); - } - return genNum; - } - - /** - * Throws error when a required parameter is missing. - * @param paramsObject The parameters passed to the function - * @param paramsNeeded The required parameters in the function - */ - throwErrorOnWrongParams(paramsObject, paramsNeeded) { - const keys = Object.keys(paramsObject); - const bool = []; - for (let i = 0; i < keys.length; i++) { - if (paramsNeeded.includes(keys[i])) { - bool.push(true); - } else { - bool.push(false); - } - } - const truthy = (element) => element == false; - if (bool.some(truthy)) { - throw Error( - `Params Error: Required parameter not found. Your params must include the following [${paramsNeeded}]` - ); - } - } - - /** - * Maps integer values (0, 1) to boolean (false, true) - * @param arr The array of integers - * @param dim The dimension of the array - */ - mapIntegersToBooleans(arr, dim) { - if (dim == 2) { - const newArr = []; - arr.map((innerArr) => { - const temp = []; - (innerArr).map((val) => temp.push(val == 1)); - newArr.push(temp); - }); - return newArr; - } else { - const newArr = []; - arr.map((val) => newArr.push(val == 1)); - return newArr; - } - } - - /** - * Maps boolean values (false, true) to integer equivalent (0, 1) - * @param arr The array of booleans - * @param dim The dimension of the array - */ - mapBooleansToIntegers(arr, dim) { - if (dim == 2) { - const newArr = []; - arr.map((innerArr) => { - const temp = []; - (innerArr).map((val) => temp.push(val ? 1 : 0)); - newArr.push(temp); - }); - return newArr; - } else { - const newArr = []; - arr.map((val) => newArr.push(val ? 1 : 0)); - return newArr; - } - } - - /** - * Generates an array of dim (row x column) with inner values set to zero - * @param row - * @param column - */ - zeros(row, column) { - const zeroData = []; - for (let i = 0; i < row; i++) { - const colData = Array(column); - for (let j = 0; j < column; j++) { - colData[j] = 0; - } - zeroData.push(colData); - } - return zeroData; - } - - /** - * Shuffles and returns a random slice of an array - * @param num - * @param array - */ - shuffle(array, num) { - let i = array.length; - let j = 0; - let temp; - - while (i--) { - j = Math.floor(Math.random() * (i + 1)); - temp = array[i]; - array[i] = array[j]; - array[j] = temp; - } - - return array.slice(0, num); - } - - /** - * Sorts an array in specified order - * @param arr - * @param ascending - * @returns - */ - sort(arr, ascending = true) { - const sorted = [...arr]; - return sorted.sort((a, b) => { - if (ascending) { - if (typeof a === "string" && typeof b === "string") { - return a.charCodeAt(0) - b.charCodeAt(0); - } else { - return (a) - (b); - } - } else { - if (typeof a === "string" && typeof b === "string") { - return b.charCodeAt(0) - a.charCodeAt(0); - } else { - return (b) - (a); - } - } - }); - } - - /** - * Checks if current environment is Browser - */ - isBrowserEnv() { - const isBrowser = new Function( - "try {return this===window;}catch(e){ return false;}" - ); - return isBrowser(); - } - - /** - * Checks if current environment is Node - */ - isNodeEnv() { - const isNode = new Function( - "try {return this===global;}catch(e){return false;}" - ); - return isNode(); - } - - /** - * Remove NaN values from 1D array - * @param arr - */ - removeMissingValuesFromArray(arr) { - const values = arr.filter((val) => { - return !(this.isEmpty(val)); - }); - return values; - } - - - /** - * Replace NaN with null before tensor operations - * @param arr - */ - replaceNanWithNull(arr) { - const values = arr.map((val) => { - if (isNaN(val)) { - return null; - } else { - return val; - } - }); - return values; - } - - /** - * Get duplicate values in a array - * @param arr - */ - getDuplicate(arr) { - const tempObj = {}; - const resultObj = {}; - - for (let i = 0; i < arr.length; i++) { - const val = arr[i]; - if (this.keyInObject(tempObj, val)) { - tempObj[val]["count"] += 1; - tempObj[val]["index"].push(i); - } else { - tempObj[val] = {}; - tempObj[val]["count"] = 1; - tempObj[val]["index"] = [i]; - } - } - - for (let key in tempObj) { - if (tempObj[key]["count"] >= 2) { - resultObj[key] = {}; - resultObj[key]["count"] = tempObj[key]["count"]; - resultObj[key]["index"] = tempObj[key]["index"]; - } - } - - return resultObj; - } - - /** - * Returns the index of a sorted array - * @param arr1 The first array - * @param arr2 The second array - * @param dtype The data type of the arrays - * - * @returns sorted index - */ - sortArrayByIndex(arr1, arr2, dtype) { - const sortedIdx = arr1.map((item, index) => { - return [arr2[index], item]; - }); - if (dtype == "string") { - sortedIdx.sort(); - } else { - sortedIdx.sort(([arg1], [arg2]) => (arg2) - (arg1)); - } - - return sortedIdx.map(([, item]) => item); - } - - /** - * Returns a new series with properties of the old series - * - * @param series The series to copy - */ - createNdframeFromNewDataWithOldProps({ ndFrame, newData, isSeries }) { - if (isSeries) { - return new Series( - newData, - { - index: [...ndFrame.index], - columns: [...ndFrame.columns], - dtypes: [...ndFrame.dtypes], - config: { ...ndFrame.config } - }); - } else { - return new DataFrame(newData, - { - index: [...ndFrame.index], - columns: [...ndFrame.columns], - dtypes: [...ndFrame.dtypes], - config: { ...ndFrame.config } - }); - } - } - - /** - * Checks if two series are compatible for a mathematical operation - * @param object - * - * firstSeries ==> First Series object - * - * secondSeries ==> Second Series object to comapre with - * - * operation ==> The mathematical operation - */ - checkSeriesOpCompactibility({ firstSeries, secondSeries, operation }) { - - if (firstSeries.shape[0] != secondSeries.shape[0]) { - ErrorThrower.throwSeriesMathOpLengthError(firstSeries, secondSeries); - } - if (firstSeries.dtypes[0] == 'string' || secondSeries.dtypes[0] == 'string') { - ErrorThrower.throwStringDtypeOperationError(operation); - } - } - - /** - * Custom sort for an array of index and values - * @param arr The array of objects to sort - * @param ascending Whether to sort in ascending order or not - */ - sortObj( - arr, - ascending - ) { - return arr.sort((obj1, obj2) => { - const a = obj2.value; - const b = obj1.value; - if (!ascending) { - if (typeof a === "string" && typeof b === "string") { - return a.charCodeAt(0) - b.charCodeAt(0); - } else if ((typeof a === "number" && typeof b === "number") || (typeof a === "boolean" && typeof b === "boolean")) { - return Number(a) - Number(b); - } else { - throw Error('ParamError: column values must be either numbers or strings'); - } - } else { - if (typeof a === "string" && typeof b === "string") { - return b.charCodeAt(0) - a.charCodeAt(0); - } else if ((typeof a === "number" && typeof b === "number") || (typeof a === "boolean" && typeof b === "boolean")) { - return Number(b) - Number(a); - } else { - throw Error('ParamError: column values must be either numbers or strings'); - } - } - }); - } -} - -const utils = new Utils(); -export { utils }; - diff --git a/danfojs-node/tests/core/frame.js b/danfojs-node/tests/core/frame.js deleted file mode 100644 index ae9f60fa..00000000 --- a/danfojs-node/tests/core/frame.js +++ /dev/null @@ -1,2200 +0,0 @@ -import { assert, expect } from "chai"; -import { Series, DataFrame } from "../../dist"; -import fs from "fs"; - -const testCSVPath = "./tester.csv"; - -describe("DataFrame", function () { - - // describe("to_csv", function () { - // afterEach(function () { - // // Clean up generated file - // fs.unlinkSync(testCSVPath); - // }); - - // it("save dataframe to CSV file", async function () { - // let data = [[1, 2, 3], [4, 5, 6]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // await df.to_csv(testCSVPath); - // assert.isTrue(fs.existsSync(testCSVPath)); - // }); - - // it("return dataframe csv string", async function () { - // let data = [[1, 2, 3], [4, 5, 6]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // const csvContent = await df.to_csv(testCSVPath); - // assert.deepEqual(csvContent, "A,B,C\n1,2,3\n4,5,6\n"); - // }); - - // }); - - describe("drop", function () { - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.throws(function () { df.drop({ columns: [3], axis: 0, inplace: false }); }, Error, 'ParamError: specified column "3" not found in columns'); - }); - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.throws(function () { df.drop({ columns: ["D"], axis: 1, inplace: false }); }, Error, 'ParamError: specified column "D" not found in columns'); - }); - - it("drop a column inplace", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.drop({ columns: ["C", "B"], axis: 1, inplace: true }); - let column = ["A"]; - assert.deepEqual(df.columns, column); - }); - it("check if data is updated after column is dropped", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.drop({ columns: ["C"], axis: 1, inplace: true }); - let new_data = [[1, 2], [4, 5]]; - assert.deepEqual(df.values, new_data); - assert.deepEqual(df.dtypes.length, 2); - - }); - - it("check if data is updated after row is dropped", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.drop({ index: [0], axis: 0, inplace: true }); - let new_data = [[4, 5, 6]]; - assert.deepEqual(df.values, new_data); - }); - it("check if new dataframe is properly created after column is dropped (not-in-inplace)", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let df_drop = df.drop({ columns: ["C"], axis: 1, inplace: false }); - - let expected_data = [[1, 2], [4, 5]]; - let expected_cols = ["A", "B"]; - let expected_df = new DataFrame(expected_data, { columns: expected_cols }); - assert.deepEqual(df_drop.values, expected_df.values); - }); - it("check that the dtype is updated after column drop", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.drop({ columns: ["A"], axis: 1, inplace: true }); - let dtype = ['int32', 'int32']; - assert.deepEqual(df.ctypes.values, dtype); - }); - it("drop row by single string labels", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 34, 5]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols, index: ["a", "b", "c"] }); - df.drop({ index: ["a"], axis: 0, inplace: true }); - let new_data = [[4, 5, 6], [20, 34, 5]]; - assert.deepEqual(df.values, new_data); - }); - it("drop row by two or more string labels", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 34, 5], [2, 3.4, 5], [2.0, 340, 5]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols, index: ["a", "b", "c", "d", "e"] }); - df.drop({ index: ["a", "b"], axis: 0, inplace: true }); - let new_data = [[20, 34, 5], [2, 3.4, 5], [2.0, 340, 5]]; - assert.deepEqual(df.values, new_data); - - }); - }); - - describe("head", function () { - it("Gets the first n rows in a DataFrame", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.deepEqual(df.head(2).values, [[1, 2, 3], [4, 5, 6]]); - }); - - }); - - describe("tail", function () { - it("Prints the last n rows of a DataFrame", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.deepEqual(df.tail(2).values, [[20, 30, 40], [39, 89, 78]]); - }); - it("Return last 3 row index in a DataFrame", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.deepEqual(df.tail(2).index, [2, 3]); - }); - it("Check print format on head call", function () { - let data = [[1, 2, 34, 5, 0, 6, 4, 5, 6, 7], [20, 30, 40, 39, 89, 78, 45, 56, 56, 45]]; - let df = new DataFrame(data); - assert.deepEqual(df.tail(2).values, [[1, 2, 34, 5, 0, 6, 4, 5, 6, 7], [20, 30, 40, 39, 89, 78, 45, 56, 56, 45]]); - }); - }); - - describe("sample", function () { - it("Samples n number of random elements from a DataFrame", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let expected = [[1, 2, 3], [20, 30, 40]]; - let values = (await df.sample(2)).values; - assert.deepEqual(values, expected); - }); - it("Throw error if n is greater than lenght of Dataframe", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - try { - await df.sample(100); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('ParamError: Sample size cannot be bigger than number of rows'); - } - }); - it("Throw error if n is less than -1", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - try { - await df.sample(-2); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); - } - }); - it("Throw error if n is 0", async function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - try { - await df.sample(0); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); - } - }); - }); - - describe("loc", function () { - - it("throw error for wrong column name", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.throws(function () { df.loc({ "rows": [0, 1], "columns": ["A", "D"] }); }, Error, "ColumnIndexError: Specified column (D) not found"); - }); - it("check data after selecting column", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": [0, 1], "columns": ["B", "C"] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after selecting row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": [1], "columns": ["B", "C"] }); - let col_data = [[5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row and column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": ["0:2"], "columns": ["B:C"] }); - let col_data = [[2], [5]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": ["0:2"], "columns": ["B", "C"] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.loc({ "rows": [0, 1], "columns": ["A:C"] }); - let col_data = [[1, 2], [4, 5]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("loc by single string index", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); - let sub_df = df.loc({ rows: ["a"], columns: ["Name", "Count"] }); - let expected = [["Apples", 21]]; - assert.deepEqual(sub_df.values, expected); - - }); - it("loc by multiple string index", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); - let sub_df = df.loc({ rows: ["a", "b"], columns: ["Name", "Count"] }); - let expected = [["Apples", 21], ["Mango", 5]]; - assert.deepEqual(sub_df.values, expected); - - }); - it("loc by slice string index", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); - let sub_df = df.loc({ rows: [`"a":"c"`], columns: ["Name", "Count"] }); - let expected = [["Apples", 21], ["Mango", 5]]; - assert.deepEqual(sub_df.values, expected); - - }); - - - }); - - describe("iloc", function () { - - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.throws(function () { df.iloc({ "rows": 0, "columns": [0, 3] }); }, Error, `rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); - }); - - it("throw error for wrong column indexing", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.throws(function () { df.iloc({ "rows": [0, 1], "columns": 3 }); }, Error, `columns parameter must be an Array. For example: columns: [1,2] or columns: ["0:10"]`); - }); - - it("throw error for wrong row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - assert.throws(function () { df.iloc({ "rows": [0, 8], "columns": [1, 2] }); }, Error, "Invalid row parameter: Specified index 8 cannot be bigger than index length 2"); - }); - - it("check data after selecting column", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [0, 1], "columns": [1, 2] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after selecting row index", function () { - let data = [[1, 2, 3], [4, 5, 6]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [1], "columns": [1, 2] }); - let col_data = [[5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row and column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": ["0:2"], "columns": ["1:2"] }); - let col_data = [[2], [5]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after row slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": ["0:2"], "columns": [1, 2] }); - let col_data = [[2, 3], [5, 6]]; - - assert.deepEqual(col_df.values, col_data); - - }); - it("check data after column slice", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [0, 1, 2], "columns": ["1:2"] }); - let col_data = [[2], [5], [30]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("Return all columns if columns parameter is not specified", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "rows": [0, 1, 2] }); - let col_data = [[1, 2, 3], [4, 5, 6], [20, 30, 40]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("Return all rows if rows parameter is not specified", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let col_df = df.iloc({ "columns": ["1:2"] }); - let col_data = [[2], [5], [30], [89]]; - assert.deepEqual(col_df.values, col_data); - - }); - it("column slice starting with 0 and returning a single result works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new DataFrame(data); - let sub_df = df.iloc({ rows: ["2:3"], columns: ["0:1"] }); - const result = [["Banana"]]; - assert.deepEqual(sub_df.values, result); - - }); - it("column slice with format '0:' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new DataFrame(data); - let sub_df = df.iloc({ rows: ["2:3"], columns: ["0:"] }); - const result = [["Banana", 30, 40]]; - assert.deepEqual(sub_df.values, result); - - }); - it("column slice with format ':2' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new DataFrame(data); - let sub_df = df.iloc({ rows: ["2:3"], columns: [":2"] }); - const result = [["Banana", 30]]; - assert.deepEqual(sub_df.values, result); - - }); - it("row slice with format ':2' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new DataFrame(data); - let sub_df = df.iloc({ rows: [":2"], columns: [":1"] }); - const result = [['Apples'], ['Mango']]; - assert.deepEqual(sub_df.values, result); - - }); - it("row slice with format '1:' works", function () { - let data = { - "Name": ["Apples", "Mango", "Banana", "Pear"], - "Count": [21, 5, 30, 10], - "Price": [200, 300, 40, 250] - }; - let df = new DataFrame(data); - let sub_df = df.iloc({ rows: [":2"], columns: [":2"] }); - const result = [['Apples', 21], ['Mango', 5]]; - assert.deepEqual(sub_df.values, result); - - }); - - }); - - - describe("add", function () { - it("Return Addition of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.add(2).values, [[2, 4, 6], [362, 182, 362]]); - }); - it("Return addition of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2, 1]); - let df = new DataFrame(data); - assert.deepEqual(df.add(sf).values, [[1, 4, 5], [361, 182, 361]]); - }); - it("Return addition of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2]); - let df = new DataFrame(data); - assert.deepEqual(df.add(sf, { axis: 0 }).values, [[1, 3, 5], [362, 182, 362]]); - }); - it("Return addition of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.add(df2).values, [[1, 4, 8], [370, 185, 360]]); - }); - it("Return addition of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.add(df2, { axis: 0 }).values, [[1, 4, 8], [370, 185, 360]]); - }); - - }); - - describe("sub", function () { - it("Return subtraction of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.sub(2).values, [[-2, 0, 2], [358, 178, 358]]); - }); - it("Return subtraction of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2, 1]); - let df = new DataFrame(data); - assert.deepEqual(df.sub(sf).values, [[-1, 0, 3], [359, 178, 359]]); - }); - it("Return subtraction of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2]); - let df = new DataFrame(data); - assert.deepEqual(df.sub(sf, { axis: 0 }).values, [[-1, 1, 3], [358, 178, 358]]); - }); - it("Return subtraction of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.sub(df2).values, [[-1, 0, 0], [350, 175, 360]]); - }); - it("Return subtraction of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.sub(df2).values, [[-1, 0, 0], [350, 175, 360]]); - }); - - }); - - describe("mul", function () { - it("Return multiplication of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.mul(2).values, [[0, 4, 8], [720, 360, 720]]); - }); - it("Return multiplication of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2, 1]); - let df = new DataFrame(data); - assert.deepEqual(df.mul(sf).values, [[0, 4, 4], [360, 360, 360]]); - }); - it("Return multiplication of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2]); - let df = new DataFrame(data); - assert.deepEqual(df.mul(sf, { axis: 0 }).values, [[0, 2, 4], [720, 360, 720]]); - }); - it("Return multiplication of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mul(df2).values, [[0, 4, 16], [3600, 900, 0]]); - }); - it("Return multiplication of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mul(df2, { axis: 0 }).values, [[0, 4, 16], [3600, 900, 0]]); - }); - - }); - - describe("div", function () { - it("Return division of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.div(2).values, [[0, 1, 2], [180, 90, 180]]); - }); - it("Return division of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2, 1]); - let df = new DataFrame(data); - assert.deepEqual(df.div(sf).values, [[0, 1, 4], [360, 90, 360]]); - }); - it("Return division of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2]); - let df = new DataFrame(data); - assert.deepEqual(df.div(sf, { axis: 0 }).values, [[0, 2, 4], [180, 90, 180]]); - }); - it("Return division of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.div(df2).values, [[0, 1, 1], [36, 36, Infinity]]); - }); - it("Return division of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - assert.deepEqual(df1.div(df1).values, [[NaN, 1, 1], [1, 1, 1]]); - }); - it("Return division of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.div(df2).values, [[0, 1, 1], [36, 36, Infinity]]); - }); - - }); - - describe("pow", function () { - it("Return exponential of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.pow(2).values, [[0, 4, 16], [129600, 32400, 129600]]); - }); - it("Return exponential of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2, 1]); - let df = new DataFrame(data); - assert.deepEqual(df.pow(sf).values, [[0, 4, 4], [360, 32400, 360]]); - }); - it("Return exponential of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let sf = new Series([1, 2]); - let df = new DataFrame(data); - assert.deepEqual(df.pow(sf, { axis: 0 }).values, [[0, 2, 4], [129600, 32400, 129600]]); - }); - it("Return exponential of a DataFrame with another DataFrame along default axis 1", function () { - let df1 = new DataFrame([[0, 2, 4], [3, 10, 4]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.pow(df2).values, [[0, 4, 256], [59049, 100000, 1]]); - }); - it("Return exponential of a DataFrame with another DataFrame along axis 0", function () { - let df1 = new DataFrame([[0, 2, 4], [3, 10, 4]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.pow(df2, { axis: 0 }).values, [[0, 4, 256], [59049, 100000, 1]]); - }); - - }); - - describe("mod", function () { - it("Return modulus of DataFrame with a single Number", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.mod(2).values, [[0, 0, 0], [0, 0, 0]]); - }); - it("Return modulus of a DataFrame with a Series along default axis 1", function () { - let data = [[0, 2, 4], [31, 15, 360]]; - let sf = new Series([1, 2, 1]); - let df = new DataFrame(data); - assert.deepEqual(df.mod(sf).values, [[0, 0, 0], [0, 1, 0]]); - }); - it("Return modulus of a DataFrame with a Series along axis 0", function () { - let data = [[0, 2, 4], [31, 15, 360]]; - let sf = new Series([1, 2]); - let df = new DataFrame(data); - assert.deepEqual(df.mod(sf, { axis: 0 }).values, [[0, 0, 0], [1, 1, 0]]); - }); - it("Return modulus of a DataFrame with a DataFrame along default axis 1", function () { - let df1 = new DataFrame([[0, 2, 4], [31, 15, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mod(df2).values, [[0, 0, 0], [1, 0, NaN]]); - }); - it("Return modulus of a DataFrame with a DataFrame along axis 0", function () { - let df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); - let df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); - assert.deepEqual(df1.mod(df2).values, [[0, 0, 0], [0, 0, NaN]]); - }); - - }); - - describe("mean", function () { - it("Returns the mean of a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data, { columns: ["col1", "col2", "col3"] }); - assert.deepEqual(df.mean().values, [180, 91, 182]); - assert.deepEqual(df.mean().index, ["col1", "col2", "col3"]); - - }); - it("Return mean of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.mean({ axis: 0 }).values, [2, 300]); - }); - it("Removes NaN before calculating mean of a DataFrame", function () { - let data = [[11, 20, 3], [NaN, 15, 6], [2, 30, 40], [2, 89, 78]]; - let df = new DataFrame(data); - assert.deepEqual(df.mean().values, [5, 38.5, 31.75]); - }); - }); - - describe("median", function () { - it("Returns the median of a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.median().values, [180, 91, 182]); - }); - it("Return median of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.median({ "axis": 0 }).values, [2, 360]); - }); - - }); - - describe("mode", function () { - it("Returns the mode of a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360], [0, 2, 4]]; - let df = new DataFrame(data); - assert.deepEqual(df.mode().values, [0, 2, 4]); - }); - it("Returns mode of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 0], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.mode({ "axis": 0 }).values, [0, 360]); - }); - }); - - describe("min", function () { - it("Returns the minimum values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.min().values, [0, 2, 4]); - }); - it("Returns the minimum values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.min({ "axis": 0 }).values, [0, 180]); - }); - - }); - - describe("max", function () { - it("Returns the maximum values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.max().values, [360, 180, 360]); - }); - it("Returns the maximum values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.max({ "axis": 0 }).values, [4, 360]); - }); - - }); - - describe("std", function () { - it("Returns the standard deviations of values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.std().values, [254.55844122715712, 125.86500705120545, 251.7300141024109]); - }); - it("Return the standard deviations of values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.std({ "axis": 0 }).values, [2, 103.92304845413264]); - }); - - - }); - - describe("var", function () { - it("Returns the variance of values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.var().values, [64800, 15842, 63368]); - }); - it("Return the variance of values of a DataFrame along axis 0 (row)", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.var({ "axis": 0 }).values, [4, 10800]); - }); - - - }); - - describe("describe", function () { - it("Returns descriptive statistics of columns in a DataFrame created from an array", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 360, "b"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data); - let res = [[3, 3, 3], [120.66666666666667, 62, 123.33333333333333], - [207.27115895206774, 102.19589032832974, 204.961785055979], - [0, 2, 4], [2, 4, 6], - [360, 180, 360], - [42961.33333333333, 10444, 42009.333333333336]]; - - assert.deepEqual(df.describe().values, res); - }); - it("Returns descriptive statistics of columns in a DataFrame created from an Object", function () { - let data = { - "col1": [0, 2, 4], - "col2": [360, 180, 360], - "col3": [2, 4, 6], - "col4": ["boy", "girl", "man"], - "col5": ["apple", "car", "bee"] - }; - let df = new DataFrame(data); - - let res = [[3, 3, 3], [2, 300, 4], - [2, 103.92304845413264, 2], - [0, 180, 2], [2, 360, 4], - [4, 360, 6], - [4, 10800, 4]]; - - assert.deepEqual(df.describe().values, res); - }); - - }); - - describe("count", function () { - it("Returns the count of non-nan values in a DataFrame (Default axis is [1:column])", function () { - let data = [[0, 2, 4], [360, 180.1, 360.11], [NaN, 2, 4], [360, undefined, 360]]; - let df = new DataFrame(data); - assert.deepEqual(df.count().values, [3, 3, 4]); - }); - it("Return the count of non NaN values of a DataFrame along axis 0", function () { - let data = [[0, 2, 4, NaN], [360, undefined, 360, 70]]; - let df = new DataFrame(data); - assert.deepEqual(df.count({ axis: 0 }).values, [3, 3]); - }); - - }); - - describe("round", function () { - it("Rounds values in a DataFrame to 3dp", function () { - let data = [[10.1, 2.092, 4.23], [360.232244, 180.0190290, 36.902612]]; - let df = new DataFrame(data); - let expected = [[10.1, 2.092, 4.23], [360.232, 180.0190, 36.903]]; - assert.deepEqual(df.round(3).values, expected); - }); - it("Rounds values in a DataFrame to 1dp", function () { - let data = [[10.1, 2.092, 4.23], [360.232244, 180.0190290, 36.902612]]; - let df = new DataFrame(data); - let expected = [[10.1, 2.1, 4.2], [360.2, 180.0, 36.9]]; - assert.deepEqual(df.round(1).values, expected); - }); - it("Rounds series in a DataFrame to 1dp", function () { - let data = [[10.1, 2.092, 4.23], [360.232244, 180.0190290, 36.902612]]; - let df = new DataFrame(data); - let expected = [10.1, 360.2]; - assert.deepEqual(df["0"].round(1).values, expected); - }); - }); - - describe("sort_values", function () { - it("Sort values in DataFrame by specified column in ascending order (Default)", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 360, "b"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - df.sort_values({ "by": "col1", inplace: true, ascending: true }); - let expected = [[0, 2, 4, "a"], [2, 4, 6, "c"], [360, 180, 360, "b"]]; - assert.deepEqual(df.values, expected); - assert.deepEqual(df.index, [0, 2, 1]); - - }); - - it("Sort values in DataFrame by specified column in ascending order (Default)", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 1, "b"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let df_sort = df.sort_values({ "by": "col3" }); - let expected = [[360, 180, 1, "b"], [0, 2, 4, "a"], [2, 4, 6, "c"]]; - assert.deepEqual(df_sort.values, expected); - assert.deepEqual(df_sort.index, [1, 0, 2]); - - }); - it("Sort values in DataFrame by specified column in descending order", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 360, "b"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let expected = [[360, 180, 360, "b"], [2, 4, 6, "c"], [0, 2, 4, "a"]]; - assert.deepEqual(df.sort_values({ "by": "col1", "ascending": false }).values, expected); - }); - - it("Sort values in DataFrame by specified column in descending order (second col)", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 1, "b"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let expected = [[2, 4, 6, "c"], [0, 2, 4, "a"], [360, 180, 1, "b"]]; - assert.deepEqual(df.sort_values({ "by": "col3", "ascending": false }).values, expected); - }); - it("Sort values in DataFrame by specified column containing alpha(numeric) values", function () { - let data = [[0, 2, 4, "a"], - [360, 180, 1, "b"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let expected = [[2, 4, 6, 'c'], [360, 180, 1, 'b'], [0, 2, 4, 'a']]; - assert.deepEqual(df.sort_values({ "by": "col4", "ascending": false }).values, expected); - }); - it("Sort duplicate DataGrame with duplicate columns", function () { - - let data = { - "A": [1, 2, 3, 4, 5, 3, 5, 6, 4, 5, 3, 4], - "B": [2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] - }; - - let df = new DataFrame(data); - let expected = [[1, 2], - [2, 3], - [3, 4], - [3, 7], - [3, 3], - [4, 5], - [4, 1], - [4, 4], - [5, 6], - [5, 8], - [5, 2], - [6, 9]]; - assert.deepEqual(df.sort_values({ "by": "A", "ascending": true }).values, expected); - }); - - - }); - - describe("copy", function () { - it("Makes a deep copy of DataFrame", function () { - let data = [[0, 2, 4], [360, 180, 360]]; - let df = new DataFrame(data); - let df_copy = df.copy(); - assert.deepEqual(df_copy.values, [[0, 2, 4], [360, 180, 360]]); - }); - }); - - - describe("set_index", function () { - it("Sets the index of a DataFrame created from an Object", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new DataFrame(data); - let df_new = df.set_index({ "index": ["one", "two", "three"] }); - assert.deepEqual(df_new.index, ["one", "two", "three"]); - }); - it("Sets the index of a DataFrame from column name", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new DataFrame(data); - let df_new = df.set_index({ "column": "alpha" }); - assert.deepEqual(df_new.index, ["A", "B", "C"]); - }); - it("Sets the index of a DataFrame from column name", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new DataFrame(data); - let df_new = df.set_index({ column: "alpha", drop: true }); - assert.deepEqual(df_new.index, ["A", "B", "C"]); - }); - it("Sets the index of a DataFrame created from an Array", function () { - let data = [[0, 2, 4], [360, 180, 360], [0, 2, 4], [360, 180, 360], [0, 2, 4]]; - let df = new DataFrame(data); - df.set_index({ "index": ["one", "two", "three", "four", "five"], "inplace": true }); - assert.deepEqual(df.index, ["one", "two", "three", "four", "five"]); - }); - - }); - - describe("reset_index", function () { - it("Resets the index of a DataFrame created from an Object", function () { - let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - let df = new DataFrame(data); - let df_new = df.set_index({ "index": ["one", "two", "three"] }); - let df_reset = df_new.reset_index(); - assert.deepEqual(df_reset.index, [0, 1, 2]); - }); - it("Resets the index of a DataFrame created from an Array", function () { - let data = [[0, 2, 4], [360, 180, 360], [0, 2, 4], [360, 180, 360], [0, 2, 4]]; - let df = new DataFrame(data); - df.set_index({ "index": ["one", "two", "three", "four", "five"], "inplace": true }); - df.reset_index({ inplace: true }); - assert.deepEqual(df.index, [0, 1, 2, 3, 4]); - }); - - }); - - - describe("apply_map", function () { - it("Apply a function to all values of a DataFrame", function () { - let data = [[0, 2, 4], - [360, 180, 360], - [0, 2, 4]]; - let df = new DataFrame(data); - - let apply_func = (x) => { - return x + 1000; - }; - let expected = [[1000, 1002, 1004], [1360, 1180, 1360], [1000, 1002, 1004]]; - assert.deepEqual(df.apply_map(apply_func).values, expected); - }); - }); - - - describe("query", function () { - - it("Get the DataFrame containing rows with the filtered column", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let query_df = df.query({ condition: df["B"].ge(5) }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(query_df.values, query_data); - }); - it("Get the Dataframe containing rows with the filtered column in String values", function () { - let data = { "Abs": [20, 30, 47], "Count": [34, 4, 5], "country code": ["NG", "FR", "GH"] }; - let cols = ["Abs", "Count", "country code"]; - let df = new DataFrame(data, { columns: cols }); - let query_df = df.query({ condition: df["country code"].eq("NG") }); - let query_data = [[20, 34, "NG"]]; - assert.deepEqual(query_df.values, query_data); - }); - - it("Confirms that query index are updated", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let df_query = df.query({ condition: df["B"].ge(5) }); - assert.deepEqual(df_query.index, [1, 2, 3]); - }); - - it("Confirms that query happens inplace", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.query({ condition: df["B"].ge(5), inplace: true }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(df.values, query_data); - }); - - it("Get the DataFrame containing rows with the filtered column (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let query_df = df.query({ "column": "B", "is": ">=", "to": 5 }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(query_df.values, query_data); - }); - it("Get the Dataframe containing rows with the filtered column in String values (Without Condition)", function () { - let data = { "Abs": [20, 30, 47], "Count": [34, 4, 5], "country code": ["NG", "FR", "GH"] }; - let cols = ["Abs", "Count", "country code"]; - let df = new DataFrame(data, { columns: cols }); - let query_df = df.query({ column: "country code", is: "==", to: "NG" }); - let query_data = [[20, 34, "NG"]]; - assert.deepEqual(query_df.values, query_data); - }); - it("Print Error for value key not specified (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "column": "B", "is": ">=" }); }, Error, "ParamError: specify a value to query by"); - }); - it("Print Error for operator key not specified (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "column": "B", "to": 5 }); }, Error, "ParamError: specify an operator to apply. operator must be one of >,<,<=,>=,==,!="); - }); - - it("Print Error for column key not specified (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "is": ">=", "to": 5 }); }, Error, "ParamError: specify a column name to query"); - }); - it("Print Error for column name not in dataframe (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - assert.throws(function () { df.query({ "column": "D", "is": ">=", "to": 5 }); }, Error, "ParamError: column D not found in column names"); - }); - it("Confirms that query index are updated (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let df_query = df.query({ "column": "B", "is": ">=", "to": 5 }); - assert.deepEqual(df_query.index, [1, 2, 3]); - }); - it("Confirms that columns data are updated inplace (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.query({ "column": "B", "is": ">=", "to": 5, inplace: true }); - assert.deepEqual(df.getColumnData, [[4, 20, 39], [5, 30, 89], [6, 40, 78]]); - }); - it("Confirms that query happens inplace (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.query({ "column": "B", "is": ">=", "to": 5, inplace: true }); - let query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]]; - assert.deepEqual(df.values, query_data); - }); - it("Confirms that query happens inplace and index are updated (Without Condition)", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - df.query({ "column": "B", "is": ">=", "to": 5, inplace: true }); - assert.deepEqual(df.index, [1, 2, 3]); - }); - it("Confirms that column names are not changed", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let df_query = df.query({ "column": "B", "is": ">=", "to": 5 }); - assert.deepEqual(df_query.index, [1, 2, 3]); - assert.deepEqual(df_query.columns, ["A", "B", "C"]); - }); - - }); - - describe("addColumn", function () { - it("Print the data, after changing a column data", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let new_col = [1, 2, 3, 4]; - - df.addColumn({ "column": "C", "values": new_col }); - - let new_data = [[1, 2, 1], [4, 5, 2], [20, 30, 3], [39, 89, 4]]; - - assert.deepEqual(df.values, new_data); - }); - it("Print the Dataframe column names, after a new column is added ", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let new_col = [1, 2, 3, 4]; - - df.addColumn({ "column": "D", "values": new_col, inplace: true }); - - let new_column = ["A", "B", "C", "D"]; - - assert.deepEqual(df.columns, new_column); - }); - it("Print Error for column name not in keyword passed", function () { - - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let new_col = [1, 2, 3, 4]; - - assert.throws(function () { df.addColumn({ "values": new_col, inplace: true }); }, Error, "ParamError: column must be specified"); - }); - it("Check if new column value length is the same with Dataframe length", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let new_col = [1, 2, 3]; - assert.throws(function () { df.addColumn({ "column": "D", "values": new_col, inplace: true }); }, Error, "ParamError: Column data length mismatch. You provided data with length 3 but Ndframe has column of lenght 3"); - }); - - it("Check that dtype is updated after a new column is added ", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let new_col = ["n", "b", "c", "f"]; - - df.addColumn({ "column": "D", "values": new_col, inplace: true }); - let dtype = ["int32", "int32", "int32", "string"]; - - assert.deepEqual(df.dtypes, dtype); - }); - - it("add series as value to a new column ", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let sf = new Series(["n", "b", "c", "f"]); - - let newdf = df.addColumn({ "column": "D", "values": sf }); - let dtype = ["int32", "int32", "int32", "string"]; - - assert.deepEqual(newdf.dtypes, dtype); - }); - - }); - - // describe("groupby", function () { - // it("Check group by One column data", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A"]); - - // let group_dict = { - // '1': [[1, 2, 3]], - // '4': [[4, 5, 6]], - // '20': [[20, 30, 40]], - // '39': [[39, 89, 78]] - // }; - - // assert.deepEqual(group_df.col_dict, group_dict); - // }); - // it("Obtain the DataFrame of one of the group", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A"]); - // let new_data = [[1, 2, 3]]; - - // assert.deepEqual(group_df.get_groups([1]).values, new_data); - // }); - // it("Check group by Two column data", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [[1, 2, 3]] }, - // '4': { '5': [[4, 5, 6]] }, - // '20': { '30': [[20, 30, 40]] }, - // '39': { '89': [[39, 89, 78]] } - // }; - - // assert.deepEqual(group_df.col_dict, new_data); - // }); - - // it("Obtain the DataFrame of one of the group, grouped by two column", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = [[1, 2, 3]]; - - // assert.deepEqual(group_df.get_groups([1, 2]).values, new_data); - // }); - - // it("Count column in group", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [1] }, - // '4': { '5': [1] }, - // '20': { '30': [1] }, - // '39': { '89': [1] } - // }; - - // assert.deepEqual(group_df.col(["C"]).count(), new_data); - // }); - // it("sum column element in group", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [3] }, - // '4': { '5': [6] }, - // '20': { '30': [40] }, - // '39': { '89': [78] } - // }; - - // assert.deepEqual(group_df.col(["C"]).sum(), new_data); - // }); - - // it("sum column element group by one column", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A"]); - - // let new_data = { '1': [2, 3], '4': [5, 6], '20': [30, 40], '39': [89, 78] }; - - // assert.deepEqual(group_df.col(["B", "C"]).sum(), new_data); - // }); - - // it("Perform aggregate on column for groupby", function () { - - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let group_df = df.groupby(["A", "B"]); - // let new_data = { - // '1': { '2': [2, 1] }, - // '4': { '5': [5, 1] }, - // '20': { '30': [30, 1] }, - // '39': { '89': [89, 1] } - // }; - - // assert.deepEqual(group_df.agg({ "B": "mean", "C": "count" }), new_data); - // }); - - - // }); - - // describe("column", function () { - // it("Obtain a column from a dataframe created from object", function () { - // let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; - // let options = { columns: ["Gender", "count"] }; - // let df = new DataFrame(data, options); - // let col_data = df.column("count"); - // let rslt_data = [1, 2, 3]; - // assert.deepEqual(col_data.values, rslt_data); - // }); - // it("Obtain a column from a dataframe", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // let col_data = df.column("C"); - // let rslt_data = [3, 6, 40, 78]; - // assert.deepEqual(col_data.values, rslt_data); - // }); - // it("Throw Error for wrong column", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - // let cols = ["A", "B", "C"]; - // let df = new DataFrame(data, { columns: cols }); - // assert.throws(() => { df.column("D"); }, Error, "ParamError: Column not found!. Column name must be one of A,B,C"); - - // }); - // }); - - // describe("Concatenate", function () { - - // it("Check the axis 0 concatenation", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols = ["A", "B", "C"] - // let df = new DataFrame(data, { columns: cols }) - - // let data1 = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols1 = ["A", "B", "C"] - // let df1 = new DataFrame(data1, { columns: cols1 }) - - // let data2 = [[1, 2, 3, 5], [4, 5, 6, 8], [20, 30, 40, 10]] - // let cols2 = ["A", "B", "C", "D"] - // let df2 = new DataFrame(data2, { columns: cols2 }) - - // let new_df = DataFrame.concat({ "df_list": [df, df1, df2], "axis": 0 }) - - // let data_values = [[1, 2, 3, NaN], [4, 5, 6, NaN], [20, 30, 40, NaN], [39, 89, 78, NaN], - // [1, 2, 3, NaN], [4, 5, 6, NaN], [20, 30, 40, NaN], [39, 89, 78, NaN], - // [1, 2, 3, 5], [4, 5, 6, 8], [20, 30, 40, 10]] - - // assert.deepEqual(new_df.values, data_values); - // }); - - // it("Check the axis 1 concatenation", function () { - // let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols = ["A", "B", "C"] - // let df = new DataFrame(data, { columns: cols }) - - // let data1 = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]] - // let cols1 = ["A", "B", "C"] - // let df1 = new DataFrame(data1, { columns: cols1 }) - - // let data2 = [[1, 2, 3, 5], [4, 5, 6, 8], [20, 30, 40, 10]] - // let cols2 = ["A", "B", "C", "D"] - // let df2 = new DataFrame(data2, { columns: cols2 }) - - // let new_df = DataFrame.concat({ "df_list": [df, df1, df2], "axis": 1 }) - - // let data_values = [[1, 2, 3, 1, 2, 3, 1, 2, 3, 5], [4, 5, 6, 4, 5, 6, 4, 5, 6, 8], - // [20, 30, 40, 20, 30, 40, 20, 30, 40, 10], [39, 89, 78, 39, 89, 78, NaN, - // NaN, NaN, NaN]] - // assert.deepEqual(new_df.values, data_values); - // }); - // }); - - - describe("Apply", function () { - - it("Apply add operation element wise dataframe on axis 0", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let result = [6, 15, 90, 206]; - - let apply_rslt = df.apply((x) => { - return x.reduce((a, b) => a + b, 0); - }, { - axis: 0 - }); - - assert.deepEqual(apply_rslt.values, result); - }); - - it("Apply add operation element wise dataframe on axis 0", function () { - let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - - let result = [64, 126, 127]; - - let apply_rslt = df.apply((x) => { - return x.reduce((a, b) => a + b, 0); - }, { - axis: 1 - }); - - assert.deepEqual(apply_rslt.values, result); - }); - }); - - describe("dropna", function () { - it("drop inplace at axis 0", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [[5, 6, 7, 8]]; - - assert.deepEqual(df.dropna(0).values, df_val); - - }); - it("drop inplace at axis 1, inplace false ", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [[1, 3], [4, 9], [6, 8]]; - - assert.deepEqual(df.dropna(1).values, df_val); - - }); - it("drop inplace at axis 1, inplace true ", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [[1, 3], [4, 9], [6, 8]]; - df.dropna(1, { inplace: true }); - - - assert.deepEqual(df.values, df_val); - - }); - it("drop inplace at axis 0 at inplace true", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [[5, 6, 7, 8]]; - - df.dropna(0, { inplace: true }); - assert.deepEqual(df.values, df_val); - - }); - it("drop works for undefined values", function () { - let data = [[null, 1, 2, 3], [3, 4, undefined, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [[5, 6, 7, 8]]; - - df.dropna(0, { inplace: true }); - assert.deepEqual(df.values, df_val); - - }); - }); - - describe("isna", function () { - - it("check if each value are nan", function () { - let data = [[NaN, 1, 2, 3], [3, 4, undefined, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [ - [true, false, false, false], - [false, false, true, false], - [false, false, false, false] - ]; - - assert.deepEqual(df.isna().values, df_val); - }); - }); - - describe("fillna", function () { - - it("replace all NaN value", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [[-999, 1, 2, 3], [3, 4, -999, 9], [5, 6, 7, 8]]; - df.fillna(-999, { inplace: true }); - assert.deepEqual(df.values, df_val); - }); - it("replace all NaN value", function () { - let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - - let df_val = [[-999, 1, 2, 3], [3, 4, -999, 9], [5, 6, 7, 8]]; - - let df_filled = df.fillna(-999); - assert.deepEqual(df_filled.values, df_val); - }); - - it("Fills only a specified column", function () { - let data = [[1, 2, 3], - [4, 5, 6], - [20, NaN, 40], - [39, NaN, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let new_vals = [[1, 2, 3], [4, 5, 6], [20, 2, 40], [39, 2, 78]]; - let df_filled = df.fillna([2], { columns: ["B"] }); - - assert.deepEqual(df_filled.values, new_vals); - }); - it("Fills column with specified values not in place", function () { - let data = [[1, 2, 3], [4, 5, 6], [NaN, 20, 40], [NaN, -1, 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let new_vals = [[1, 2, 3], [4, 5, 6], [-2, 20, 40], [-2, -1, 78]]; - let df_filled = df.fillna([-2], { columns: ["A"] }); - - assert.deepEqual(df_filled.values, new_vals); - }); - - it("Fills a list of columns with specified values", function () { - let data = [[1, undefined, 3], [4, undefined, 6], [NaN, "boy", 40], [NaN, "girl", 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let new_vals = [[1, "girl", 3], [4, "girl", 6], [200, "boy", 40], [200, "girl", 78]]; - let df_filled = df.fillna([200, "girl"], { columns: ["A", "B"] }); - assert.deepEqual(df_filled.values, new_vals); - }); - it("Fills a list of columns with specified values inplace", function () { - let data = [[1, undefined, 3], [4, undefined, 6], [NaN, "boy", 40], [NaN, "girl", 78]]; - let cols = ["A", "B", "C"]; - let df = new DataFrame(data, { columns: cols }); - let new_vals = [[1, "girl", 3], [4, "girl", 6], [200, "boy", 40], [200, "girl", 78]]; - df.fillna([200, "girl"], { columns: ["A", "B"], inplace: true }); - assert.deepEqual(df.values, new_vals); - }); - }); - - - // describe("nanindex", function () { - - // it("print out the nanIndex", function () { - // let data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; - // let column = ["A", "B", "C", "D"]; - // let df = new DataFrame(data, { columns: column }); - - // let df_val = [0, 1]; - // assert.deepEqual(df.nanIndex(), df_val); - // }); - // }); - - describe("select_dtypes", function () { - - it("Returns float columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], [3.2, 4, 30, "girl"], [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['float32']); - assert.deepEqual(df_sub["A"].values, [30, 3.2, 5.09]); - }); - - it("Returns int columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['int32']); - assert.deepEqual(df_sub.values, [[1, 2], [4, 30], [6, 7]]); - }); - - it("Returns string columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['string']); - assert.deepEqual(df_sub["D"].values, ["boy", "girl", "cat"]); - }); - - it("Returns string and float columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let expected = [[30, "boy"], - [3.2, "girl"], - [5.09, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['string', 'float32']); - assert.deepEqual(df_sub.values, expected); - }); - - it("Returns int and float columns in a DataFrame", function () { - let data = [[30, 1, 2, "boy"], - [3.2, 4, 30, "girl"], - [5.09, 6, 7, "cat"]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - let df_sub = df.select_dtypes(['int32', 'float32']); - assert.deepEqual(df_sub.values, [[30, 1, 2], [3.2, 4, 30], [5.09, 6, 7]]); - }); - }); - - describe("cum_ops", function () { - - it("check cumsum data", function () { - let data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - let rslt = [[2, 1, 2, 3], [5, 5, 13, 12], [10, 11, 20, 20]]; - - assert.deepEqual(df.cumsum({ axis: 1 }).values, rslt); - }); - it("check cumsum data along axis 1", function () { - let data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; - let column = ["A", "B", "C", "D"]; - let df = new DataFrame(data, { columns: column }); - let rslt = [[2, 3, 5, 8], [3, 7, 18, 27], [5, 11, 18, 26]]; - - assert.deepEqual(df.cumsum({ axis: 0 }).values, rslt); - }); - }); - - describe("lt", function () { - it("Returns Less than of DataFrame and other DataFrame (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new DataFrame(data1); - let df2 = new DataFrame(data2); - let expected = [[true, true, true, false], - [false, false, false, false]]; - assert.deepEqual(df.lt(df2).values, expected); - }); - - it("Return Less than of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let sf = new DataFrame(data1); - let expected = [[true, false, false, true], - [true, true, true, true]]; - assert.deepEqual(sf.lt(30).values, expected); - }); - it("Return Less than of series and DataFrame scalar along axis 1 (column)", function () { - let data1 = [[10, 45, 56, 10], - [23, 20, 10, 10]]; - let sf = new Series([10, 23, 56, 100]); - let df = new DataFrame(data1); - let expected = [[false, false, false, true], [false, true, true, true]]; - assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); - }); - - it("Return Less than of Array and DataFrame scalar along axis 1 (column)", function () { - let data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; - let sf = [10, 23, 56, 100]; - let df = new DataFrame(data1); - let expected = [[false, false, false, true], [false, true, true, true]]; - assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); - }); - - }); - - describe("gt", function () { - it("Return Greater than of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new DataFrame(data1); - let df2 = new DataFrame(data2); - let expected = [[false, false, false, true], [false, true, true, false]]; - assert.deepEqual(df.gt(df2).values, expected); - }); - - it("Return Greater than of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let sf = new DataFrame(data1); - let expected = [[false, true, true, false], [false, false, false, false]]; - assert.deepEqual(sf.gt(30).values, expected); - }); - - it("Return Less than of Array and DataFrame scalar along axis 1 (column)", function () { - let data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; - let sf = [10, 23, 56, 100]; - let df = new DataFrame(data1); - let expected = [[false, true, false, false], [true, false, false, false]]; - assert.deepEqual(df.gt(sf, { axis: 1 }).values, expected); - }); - - }); - - describe("le", function () { - it("Return Less than or Equal to of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new DataFrame(data1); - let df2 = new DataFrame(data2); - let expected = [[true, true, true, false], [true, false, false, true]]; - assert.deepEqual(df.le(df2).values, expected); - }); - - it("Return Less than or Equal to of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new DataFrame(data1); - let expected = [[true, false, false, true], [true, true, true, true]]; - assert.deepEqual(sf.le(30).values, expected); - }); - - }); - - describe("ge", function () { - it("Return Greater than or Equal to of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new DataFrame(data1); - let df2 = new DataFrame(data2); - let expected = [[false, false, false, true], [true, true, true, true]]; - assert.deepEqual(df.ge(df2).values, expected); - }); - - it("Return Greater than or Equal to of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new DataFrame(data1); - let expected = [[false, true, true, false], [false, false, true, false]]; - assert.deepEqual(sf.ge(30).values, expected); - }); - - }); - - describe("ne", function () { - it("Return Not Equal to of series and other series (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new DataFrame(data1); - let df2 = new DataFrame(data2); - let expected = [[true, true, true, true], [false, true, true, false]]; - assert.deepEqual(df.ne(df2).values, expected); - }); - - it("Return Not Equal to of series scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new DataFrame(data1); - let expected = [[true, true, true, true], [true, true, false, true]]; - assert.deepEqual(sf.ne(30).values, expected); - }); - - }); - - describe("eq", function () { - it("Return Equal to of DataFrame and other DataFrame (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; - let data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; - - let df = new DataFrame(data1); - let df2 = new DataFrame(data2); - let expected = [[false, false, false, false], [true, false, false, true]]; - assert.deepEqual(df.eq(df2).values, expected); - }); - - it("Return Equal to of DataFrame with scalar (element-wise)", function () { - let data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; - let sf = new DataFrame(data1); - let expected = [[false, false, false, false], [false, false, true, false]]; - assert.deepEqual(sf.eq(30).values, expected); - }); - it("Return Equal to of series and DataFrame scalar along axis 1 (column)", function () { - let data1 = { "Col1": [10, 45, 56, 10], "Col2": [23, 20, 10, 10] }; - let sf = new Series([10, 23]); - let df = new DataFrame(data1); - let expected = [[true, true], [false, false], [false, false], [true, false]]; - assert.deepEqual(df.eq(sf, { axis: 1 }).values, expected); - }); - - }); - - describe("replace", function () { - it("Replace values given in replace param", function () { - let data1 = [[10, 45, 56, 25], [23, 20, 10, 24]]; - let sf = new DataFrame(data1); - let expected = [[-999, 45, 56, 25], [23, 20, -999, 24]]; - let df_rep = sf.replace(10, -999); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values given in replace param with value (String type)", function () { - let data1 = [["A", "A", "A", "B"], ["B", "C", "C", "D"]]; - let df = new DataFrame(data1); - let expected = [["boy", "boy", "boy", "B"], ["B", "C", "C", "D"]]; - let df_rep = df.replace("A", "boy"); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values in specified two column(s)", function () { - let data1 = [["A", "A", 1, "girl"], - ["B", "A", 2, "woman"], - ["A", "B", 3, "man"]]; - let df = new DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); - let expected = [["boy", "boy", 1, "girl"], - ["B", "boy", 2, "woman"], - ["boy", "B", 3, "man"]]; - let df_rep = df.replace("A", "boy", { columns: ["col1", "col2"] }); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values in specified single column(s)", function () { - let data1 = [[2, "A", 1, "girl"], - [3, "A", 2, "woman"], - [4, "B", 3, "man"]]; - let df = new DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); - let expected = [[2, "A", 1, "girl"], - [10, "A", 2, "woman"], - [4, "B", 3, "man"]]; - let df_rep = df.replace(3, 10, { columns: ["col1"] }); - assert.deepEqual(df_rep.values, expected); - }); - - }); - - - describe("sum", function () { - it("Sum values of a DataFrame by Default axis column (axis=1)", function () { - let data1 = [[30, 40, 3.1], - [5, 5, 5.1], - [5, 5, 3.2]]; - let sf = new DataFrame(data1); - let res = [40, 50, 11.399999999999999]; - assert.deepEqual(sf.sum().values, res); - }); - it("Sum values of a DataFrame along row axis (axis=0)", function () { - let data1 = [[30, 40, 3.1], - [5, 5, 5.1], - [5, 5, 3.2]]; - let df = new DataFrame(data1); - let res = [73.1, 15.1, 13.2]; - assert.deepEqual(df.sum({ axis: 0 }).values, res); - }); - it("Sum values of a mixed DataFrame along row axis (axis=0)", function () { - let data1 = [[30, 40, 3.1, true], - [5, 5, 5.1, true], - [5, 5, 3.2, true]]; - let df = new DataFrame(data1); - let res = [74.1, 16.1, 14.2]; - assert.deepEqual(df.sum({ axis: 0 }).values, res); - }); - it("Sum values of a boolean DataFrame along row axis (axis=0)", function () { - let data1 = [[true, true, false, true], - [false, false, false, false], - [false, true, true, false]]; - let df = new DataFrame(data1); - let res = [3, 0, 2]; - assert.deepEqual(df.sum({ axis: 0 }).values, res); - }); - it("Sum values of a boolean DataFrame along default column axis (axis=1)", function () { - let data1 = [[true, true, false, true], - [false, false, false, false], - [false, true, true, false]]; - let df = new DataFrame(data1); - let res = [1, 2, 1, 1]; - assert.deepEqual(df.sum().values, res); - }); - it("Sum values of a df with missing values", function () { - let data1 = [[11, 20, 3], [null, 15, 6], [2, 30, 40], [2, 89, 78]]; - let df = new DataFrame(data1); - let res = [15, 154, 127]; - assert.deepEqual(df.sum().values, res); - }); - - }); - - describe("abs", function () { - it("Returns the absolute values in DataFrame of ints", function () { - let data1 = [[-10, 45, 56, 10], [-25, 23, 20, -10]]; - let df = new DataFrame(data1); - let expected = [[10, 45, 56, 10], [25, 23, 20, 10]]; - assert.deepEqual(df.abs().values, expected); - }); - - it("Returns the absolute values in mixed DataFrame", function () { - let data1 = [[-10, -45.1, 56, 10], [-25, -23.2, 20, -10]]; - let df = new DataFrame(data1); - let expected = [[10, 45.1, 56, 10], [25, 23.2, 20, 10]]; - assert.deepEqual(df.abs().values, expected); - }); - }); - - describe("T", function () { - it("Returns the Tranpose of a DataFrame", function () { - let data1 = [[10, 45, 56, 10], - [25, 23, 20, 10]]; - - let cols = ["a", "b", "c", "d"]; - let df = new DataFrame(data1, { columns: cols }); - let df_trans = df.T; - let expected_vals = [[10, 25], [45, 23], [56, 20], [10, 10]]; - let expected_index = cols; - let expected_col_names = ['0', '1']; - assert.deepEqual(df_trans.index, expected_index); - assert.deepEqual(df_trans.values, expected_vals); - assert.deepEqual(df_trans.columns, expected_col_names); - - }); - - }); - - - describe("astype", function () { - it("set type of float column to int", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["a", "b", "c", "c"] - }; - let ndframe = new DataFrame(data); - let df = ndframe.astype({ column: "A", dtype: "int32" }); - - assert.deepEqual(df.dtypes, ['int32', 'int32', 'float32', 'string']); - assert.deepEqual(df['A'].values, [-20, 30, 47, -20]); - - }); - it("set type of int column to float", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["a", "b", "c", "c"] - }; - let ndframe = new DataFrame(data); - let df = ndframe.astype({ column: "B", dtype: "float32" }); - - assert.deepEqual(df.dtypes, ['float32', 'float32', 'float32', 'string']); - assert.deepEqual(df['B'].values, [34, -4, 5, 6]); - - }); - it("set type of string column to int", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["20.1", "21", "23.4", "50.78"] - }; - let ndframe = new DataFrame(data); - let df = ndframe.astype({ column: "D", dtype: "int32" }); - - assert.deepEqual(df.dtypes, ['float32', 'int32', 'float32', 'int32']); - assert.deepEqual(df['D'].values, [20, 21, 23, 50]); - - }); - it("set type of string column to float", function () { - let data = { - "A": [-20.1, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20.1, -20.23, 30.3, 40.11], - "D": ["20.1", "21", "23.4", "50.78"] - }; - let ndframe = new DataFrame(data); - let df = ndframe.astype({ column: "D", dtype: "float32" }); - - assert.deepEqual(df.dtypes, ['float32', 'int32', 'float32', 'float32']); - assert.deepEqual(df['D'].values, [20.1, 21, 23.4, 50.78]); - - }); - }); - - - describe("nunique", function () { - it("Returns the number of unique elements along axis 1", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new DataFrame(data); - let df = ndframe.nunique(1); - let res = [3, 4, 2, 3]; - assert.deepEqual(df.values, res); - - }); - it("Returns the number of unique elements along axis 0", function () { - let data = { - "A": [20, 30, 47.3, 30], - "B": [34, -4, 5, 30], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new DataFrame(data); - let df = ndframe.nunique(0); - let res = [3, 4, 4, 2]; - assert.deepEqual(df.values, res); - - }); - - }); - - describe("rename", function () { - it("Rename columns along axis 1", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new DataFrame(data); - let df = ndframe.rename({ mapper: { "A": "a1", "B": "b1" } }); - let res = ["a1", "b1", "C", "D"]; - assert.deepEqual(df.columns, res); - - }); - - it("Rename columns along axis 1 inplace", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let df = new DataFrame(data); - df.rename({ mapper: { "A": "a1", "B": "b1" }, inplace: true }); - let res = ["a1", "b1", "C", "D"]; - assert.deepEqual(df.columns, res); - - }); - it("Rename string index along axis 0", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let ndframe = new DataFrame(data, { index: ["a", "b", "c", "d"] }); - let df = ndframe.rename({ mapper: { "a": 0, "b": 1 }, axis: 0 }); - let res = [0, 1, "c", "d"]; - assert.deepEqual(df.index, res); - - }); - it("Rename string index along axis 0 inplace", function () { - let data = { - "A": [-20, 30, 47.3, -20], - "B": [34, -4, 5, 6], - "C": [20, 20, 30, 30], - "D": ["a", "b", "c", "c"] - }; - - let df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); - df.rename({ mapper: { "a": 0, "b": 1 }, axis: 0, inplace: true }); - let res = [0, 1, "c", "d"]; - assert.deepEqual(df.index, res); - - }); - it("Get new column via subseting works after rename (inplace)", function () { - let data = { - "A": [-20, 30, 47.3], - "B": [34, -4, 5], - "C": [20, 2, 30] - }; - let df = new DataFrame(data); - df.rename({ mapper: { "A": "new_name" }, inplace: true }); - df["new_name"].print(); - assert.deepEqual(df["new_name"].values, data["A"]); - }); - - it("Get new column via subseting works after rename (not-inplace)", function () { - let data = { - "A": [-20, 30, 47.3], - "B": [34, -4, 5], - "C": [20, 2, 30] - }; - let df = new DataFrame(data); - let new_df = df.rename({ mapper: { "A": "new_name" } }); - assert.deepEqual(new_df["new_name"].values, data["A"]); - }); - }); - - describe("sort_index", function () { - - it("sort index in ascending order", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - let df2 = df.sort_index(); - let rslt = [[360, 180, 360, 'a'], [0, 2, 4, 'b'], [2, 4, 6, 'c']]; - - assert.deepEqual(df2.values, rslt); - }); - it("sort index in descending order", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - let df2 = df.sort_index({ ascending: false }); - let rslt = [[2, 4, 6, 'c'], [0, 2, 4, 'b'], [360, 180, 360, 'a']]; - - assert.deepEqual(df2.values, rslt); - }); - it("sort index in descending order with inplace set to true", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - df.sort_index({ ascending: false, inplace: true }); - let rslt = [[2, 4, 6, 'c'], [0, 2, 4, 'b'], [360, 180, 360, 'a']]; - assert.deepEqual(df.values, rslt); - }); - it("sort index in descending order and retains index", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); - let df2 = df.sort_index({ ascending: false }); - let rslt = ["c", "b", "a"]; - - assert.deepEqual(df2.index, rslt); - }); - }); - - describe("append", function () { - - it("Add a new single row (array) to the end of a DataFrame", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data); - let expected_val = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"], - [20, 40, 60, "d"]]; - - let rslt_df = df.append([[20, 40, 60, "d"]], [3]); - assert.deepEqual(rslt_df.values, expected_val); - - }); - - it("Add a new single row (object) to the end of a DataFrame", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let df2 = new DataFrame([[20, 40, 60, "d"]], { "columns": ["col1", "col2", "col3", "col4"] }); - - let expected_val = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"], - [20, 40, 60, "d"]]; - - let rslt_df = df.append(df2, [3]); - assert.deepEqual(rslt_df.values, expected_val); - - }); - it("Confirm index Change after append", function () { - let data = [[0, 2, 4, "b"], - [360, 180, 360, "a"], - [2, 4, 6, "c"]]; - - let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); - let df2 = new DataFrame([[20, 40, 60, "d"]], { "columns": ["col1", "col2", "col3", "col4"] }); - - let rslt_df = df.append(df2, [3]); - assert.deepEqual(rslt_df.index, [0, 1, 2, 3]); - - }); - }); - - describe("Str", function () { - it("Str (startsWith) works for columns selected from a DF", function () { - let data = { - "Name": ["Apples", "Bake", "Application", undefined], - "Count": [2, 5, 4, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new DataFrame(data); - let name_sf = df['Name']; - assert.deepEqual(name_sf.str.startsWith("App").values, [true, false, true, NaN]); - }); - it("Str (toLowerCase) works for columns selected from a DF", function () { - let data = { - "Name": ["Apples", "Bake", "Application", undefined], - "Count": [2, 5, 4, 10], - "Price": [200, 300, 40, 250] - }; - - let df = new DataFrame(data); - let name_sf = df['Name']; - assert.deepEqual(name_sf.str.toLowerCase().values, ["apples", "bake", "application", NaN]); - }); - }); - -}); diff --git a/danfojs-node/tests/core/generic.js b/danfojs-node/tests/core/generic.js deleted file mode 100644 index f1f4d090..00000000 --- a/danfojs-node/tests/core/generic.js +++ /dev/null @@ -1,260 +0,0 @@ -import { assert } from "chai"; -import { NDframe } from '../../dist'; -import * as tf from '@tensorflow/tfjs-node'; - - -describe("Generic (NDFrame)", function () { - describe("NDframe Created from Array", function () { - it("prints the shape of a 1D array", function () { - let data = [ 1, 2, 3, "Boy", "Girl" ]; - let ndframe = new NDframe({ data, isSeries:true }); - assert.deepEqual(ndframe.shape, [ 5, 1 ]); - }); - it("prints the default assigned column name in a series", function () { - let data = [ "Boy", 20, 25 ]; - let ndframe = new NDframe({ data, isSeries:true }); - assert.deepEqual(ndframe.columns, [ "0" ]); - }); - it("prints the assigned column name in a series", function () { - let data = [ "Boy", 20, 25 ]; - let options = { "columns": 'Records', isSeries : true }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.columns, "Records"); - }); - it("prints the shape of a 2D array", function () { - let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.shape, [ 2, 2 ]); - }); - it("prints the default assigned column names in 2D frame", function () { - let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.columns, [ "0", "1" ]); - }); - it("prints the assigned column names", function () { - let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; - let options = { "columns": [ "Gender", "Age" ], isSeries : false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.columns, [ "Gender", "Age" ]); - }); - it("prints the size of a frame", function () { - let data = [ [ "Boy", 20, 1 ], [ "Girl", 25, 3 ] ]; - let options = { "columns": [ "Gender", "Age", "count"], isSeries : false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.size, 6); - }); - it("prints the dimension of a frame", function () { - let data = [ [ "Boy", 20, 1 ], [ "Girl", 25, 3 ] ]; - let options = { "columns": [ "Gender", "Age", "count"], isSeries:false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.ndim, 2); - }); - it("prints the values of a frame", function () { - let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ] ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, data); - }); - it("prints the values of a frame", function () { - let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ] ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, data); - }); - }); - - describe("NDframe Created from JavaScript Object", function () { - - it("prints the shape of a 2D frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.shape, [ 3, 2 ]); - }); - it("prints the column names of frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.columns, [ "alpha", "count" ]); - }); - it("prints the shape of a 1D frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 } ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.shape, [ 1, 2 ]); - }); - - it("prints the size of a frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let options = { isSeries : false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.size, 6); - }); - it("prints the dimension of a frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; - let options = { isSeries : false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.ndim, 2); - }); - it("prints the values of a frame created from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, [ [ "A", 1 ], [ "B", 2 ] ]); - }); - it("prints the values of a frame created from an Object with null values", function () { - let data = [ { alpha: "A", count: null }, { alpha: null, count: 2 } ]; - let ndframe = new NDframe({ data, isSeries:false }); - assert.deepEqual(ndframe.values, [ [ "A", null ], [ null, 2 ] ]); - }); - }); - - describe("NDframe Created from a Tensor", function () { - - it("prints the shape of a 2D frame created from a 2D tensor", function () { - let data = tf.tensor([ 1, 2, 3, 4 ]); - let ndframe = new NDframe({ data, isSeries:true }); - assert.deepEqual(ndframe.ndim, 1); - assert.deepEqual(ndframe.values, [ 1, 2, 3, 4 ]); - - }); - it("prints the shape of a 2D frame created from a 1D tensor", function () { - let data = tf.tensor([ [ 2, 3, 4 ], [ 4, 5, 6 ] ]); - let ndframe = new NDframe({ data, columns: [ "alpha", "count", "sum" ], isSeries : false }); - assert.deepEqual(ndframe.columns, [ "alpha", "count", "sum" ]); - }); - - }); - - describe("index", function () { - it("Returns the index of an NDframe", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let df = new NDframe({ data, isSeries:false }); - assert.deepEqual(df.index, [ 0, 1, 2 ]); - }); - it("Returns the index of an NDframe created from an Array", function () { - let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; - let df = new NDframe({ data, isSeries:false }); - assert.deepEqual(df.index, [ 0, 1, 2, 3 ]); - }); - }); - - describe("NDframe Created from JavaScript Object of Arrays", function () { - it("retrieves the row data created from OA ", function () { - let data = { alpha: [ "A", "B" ], count: [ 1, 2 ] }; - let ndframe = new NDframe({ data, isSeries:false }); - // assert.deepEqual(ndframe.shape, [4, 2]) - assert.deepEqual(ndframe.values, [ [ "A", 1 ], [ "B", 2 ] ]); - }); - }); - - describe("$setIndex", function () { - it("sets the index of an NDframe", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - let df = new NDframe({ data, isSeries:false }); - df.$setIndex([ "A", "B", "C" ]); - assert.deepEqual(df.index, [ "A", "B", "C" ]); - }); - it("Returns the index of an NDframe created from an Array", function () { - let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; - let df = new NDframe({ data, isSeries:false }); - df.$setIndex([ 10, 20, 30, 40 ]); - assert.deepEqual(df.index, [ 10, 20, 30, 40 ]); - }); - }); - - - describe("dtype", function () { - it("Returns int dtype set during creation of 1DFrame (Series) from an Object", function () { - let data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; - let options = { dtypes: [ 'int32' ], isSeries : true }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ 'int32' ]); - }); - - it("Returns string dtype set during creation of 1DFrame (Series) from an Array", function () { - let data = [ "Alice", "Yemi", "Rising", "Mark" ]; - let options = { dtypes: [ 'string' ], isSeries : true }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string" ]); - }); - - it("Returns string dtype automatically inferred from 1DFrame (Series)", function () { - let data = [ "Alice", "Yemi", "Rising", "Mark" ]; - let options = { columns: 'Names', isSeries : true }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string" ]); - }); - - it("Returns int dtype automatically inferred from 1DFrame (Series)", function () { - let data = [ 20, 30, 20, 20 ]; - let options = { columns: 'Size', isSeries : true }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "int32" ]); - }); - it("Returns float dtype automatically inferred from 1DFrame (Series)", function () { - let data = [ 20.1, 30.4, 20.2, 4.23, 20.1 ]; - let options = { columns: 'Size', isSeries : true }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "float32" ]); - }); - - - it("Returns dtype set during creation of 2DFrame from an Object", function () { - let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; - let options = { dtypes: [ 'string', 'int32' ], isSeries : false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ 'string', 'int32' ]); - }); - it("Returns dtype set during creation of 2DFrame from an Array", function () { - let data = [ [ "Alice", 2, 3.0 ], [ "Boy", 5, 6.1 ], [ "Girl", 30, 40 ], [ 39, 89, 78.2 ] ]; - let cols = [ "Name", "Count", "Score" ]; - let options = { columns: cols, dtypes: [ 'string', 'int32', 'float32' ], isSeries : false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string", "int32", "float32" ]); - }); - - it("Returns dtype automatically inferred from 2DFrame", function () { - let data = [ [ "Alice", 2, 3.1 ], [ "Boy", 5, 6.1 ], [ "Girl", 30, 40.2 ], [ 39, 89, 78.2 ] ]; - let cols = [ "Name", "Count", "Score" ]; - let options = { columns: cols, isSeries : false }; - let ndframe = new NDframe({ data, ...options }); - assert.deepEqual(ndframe.dtypes, [ "string", "int32", "float32" ]); - }); - - }); - - - // describe("to_csv", async function () { - // it("Converts DataFrame to csv format and return string", async function () { - // let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - // let df = new NDframe({ data, isSeries:true }); - // let result = `alpha,count\nA,1\nB,2\nC,3\n`; - // df.to_csv().then((csv) => { - // assert.deepEqual(csv, result); - // }); - // }); - // it("Converts DataFrame of Series to csv format and return string when path is not specified", async function () { - // let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; - // let df = new NDframe(data, { columns: [ "A", "B", "C" ] }); - // let result = `A,B,C\n12,2,20\n90,5,23\n45,56,70\n9,10,19\n`; - // assert.deepEqual(await df.to_csv(), result); - // }); - // }); - - // describe("to_json", async function () { - // it("Converts DataFrame to json format and return string", async function () { - // let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; - // let result = JSON.stringify([ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]); - - // let df = new NDframe({ data, isSeries:true }); - // df.to_json().then((json) => { - // assert.deepEqual(json, result); - // }); - // }); - // it("Converts DataFrame to json format", async function () { - // let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ] ]; - // let df = new NDframe(data, { columns: [ "A", "B", "C" ] }); - // let result = JSON.stringify([ { A: 12, B: 2, C: 20 }, { A: 90, B: 5, C: 23 }, { A: 45, B: 56, C: 70 } ]); - // df.to_json().then((json) => { - // assert.deepEqual(json, result); - // }); - // }); - // }); - - -}); diff --git a/danfojs-node/tests/core/get_dummies.js b/danfojs-node/tests/core/get_dummies.js deleted file mode 100644 index 06dc9d48..00000000 --- a/danfojs-node/tests/core/get_dummies.js +++ /dev/null @@ -1,176 +0,0 @@ -import { assert } from "chai"; -import { DataFrame, Series, get_dummies } from "../../dist"; - -describe("DummyEncoder", function () { - it("get_dummies works on Series", function () { - - const data = ["dog", "male", "female", "male", "female", "male", "dog"]; - const series = new Series(data); - const df = get_dummies(series, { prefix: "test", prefixSeparator: "/" }); - - const dfValues = [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [1, 0, 0] - ]; - const dfColumns = ['test/dog', 'test/male', 'test/female']; - assert.deepEqual(df.values, dfValues); - assert.deepEqual(df.columns, dfColumns); - }); - it("get_dummies works on Series with default prefix and prefixSeperator", function () { - - const data = ["dog", "male", "female", "male", "female", "male", "dog"]; - const series = new Series(data); - const df = get_dummies(series); - - const dfValues = [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [0, 0, 1], - [0, 1, 0], - [1, 0, 0] - ]; - const dfColumns = ['0_dog', '1_male', '2_female']; - assert.deepEqual(df.values, dfValues); - assert.deepEqual(df.columns, dfColumns); - }); - - it("get_dummies works on DataFrame", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new DataFrame(data, { columns: columns }); - - const df1 = get_dummies(df, { prefixSeparator: ["_", "#"], columns: ["A", "d"], prefix: "test" }); - const expectedColumns = ['B', 'C', 'test_1', 'test_3', 'test_4', 'test#fat', 'test#good', 'test#best']; - const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], - ['fog', 2.0, 0, 1, 0, 0, 1, 0], - ['gof', 3.0, 0, 0, 1, 0, 0, 1]]; - assert.deepEqual(df1.values, expected); - assert.deepEqual(df1.columns, expectedColumns); - - }); - it("Throw error if the prefix specified is not equal to the column specified", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new DataFrame(data, { columns: columns }); - - assert.throws(function () { get_dummies(df, { prefix: ["fg"], prefixSeparator: "_", columns: ["A", "d"] }); }, Error, - `ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "fg"}`); - - }); - it("replace column sepecified with prefix", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new DataFrame(data, { columns: columns }); - - const df1 = get_dummies(df, { prefix: ["F", "G"], prefixSeparator: "_", columns: ["A", "d"] }); - const expectedColumns = [ - 'B', 'C', - 'F_1', 'F_3', - 'F_4', 'G_fat', - 'G_good', 'G_best' - ]; - - const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], - ['fog', 2.0, 0, 1, 0, 0, 1, 0], - ['gof', 3.0, 0, 0, 1, 0, 0, 1]]; - - assert.deepEqual(df1.values, expected); - assert.deepEqual(df1.columns, expectedColumns); - - }); - - it("get_dummies auto infers and encode columns with string dtype", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new DataFrame(data, { columns: columns }); - - const df1 = get_dummies(df, { prefixSeparator: "_" }); - const expectedColumns = [ - 'A', 'C', - 'B_dog', 'B_fog', - 'B_gof', 'd_fat', - 'd_good', 'd_best' - ]; - const expected = [ - [ - 1, 1, 1, 0, - 0, 1, 0, 0 - ], - [ - 3, 2, 0, 1, - 0, 0, 1, 0 - ], - [ - 4, 3, 0, 0, - 1, 0, 0, 1 - ] - ]; - assert.deepEqual(df1.values, expected); - assert.deepEqual(df1.columns, expectedColumns); - - }); - - it("should one hot encode all other columns", function () { - - const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; - const columns = ["A", "B", "C", "d"]; - const df = new DataFrame(data, { columns: columns }); - const rslt = [ - [1, 'dog', 1, 1, 0, 0], - [3, 'fog', 2, 0, 1, 0], - [4, 'gof', 3, 0, 0, 1] - ]; - - assert.deepEqual(get_dummies(df, { columns: ["d"] }).values, rslt); - - }); - - it("Dummification works for object DF", function () { - - let data = { - fruits: ['pear', 'mango', "pawpaw", "mango", "bean"], - Count: [20, 30, 89, 12, 30], - Country: ["NG", "NG", "GH", "RU", "RU"] - }; - - let df = new DataFrame(data); - const expected = [ - [ - 20, 1, 0, 0, - 0, 1, 0, 0 - ], - [ - 30, 0, 1, 0, - 0, 1, 0, 0 - ], - [ - 89, 0, 0, 1, - 0, 0, 1, 0 - ], - [ - 12, 0, 1, 0, - 0, 0, 0, 1 - ], - [ - 30, 0, 0, 0, - 1, 0, 0, 1 - ] - ]; - - let dum_df = get_dummies(df, { prefixSeparator: "_" }); - dum_df.print(); - assert.deepEqual(dum_df.values, expected); - - }); -}); diff --git a/danfojs-node/tests/core/groupby.js b/danfojs-node/tests/core/groupby.js deleted file mode 100644 index 91cec842..00000000 --- a/danfojs-node/tests/core/groupby.js +++ /dev/null @@ -1,297 +0,0 @@ -import { assert } from "chai"; -import { DataFrame } from "../../dist"; - - -describe("groupby", function () { - it("Check group by One column data", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A" ]); - - let group_dict = { - '1': [ [ 1, 2, 3 ] ], - '4': [ [ 4, 5, 6 ] ], - '20': [ [ 20, 30, 40 ] ], - '39': [ [ 39, 89, 78 ] ] - }; - - assert.deepEqual(group_df.col_dict, group_dict); - }); - it("Obtain the DataFrame of one of the group", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A" ]); - let new_data = [ [ 1, 2, 3 ] ]; - - assert.deepEqual(group_df.get_groups([ 1 ]).values, new_data); - }); - it("Check group by Two column data", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - let new_data = { - '1': { '2': [ [ 1, 2, 3 ] ] }, - '4': { '5': [ [ 4, 5, 6 ] ] }, - '20': { '30': [ [ 20, 30, 40 ] ] }, - '39': { '89': [ [ 39, 89, 78 ] ] } - }; - - assert.deepEqual(group_df.col_dict, new_data); - }); - - it("Obtain the DataFrame of one of the group, grouped by two column", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - let new_data = [ [ 1, 2, 3 ] ]; - - assert.deepEqual(group_df.get_groups([ 1, 2 ]).values, new_data); - }); - - it("Count column in group", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - let new_data = [ - [ 1, 2, 1 ], - [ 4, 5, 1 ], - [ 20, 30, 1 ], - [ 39, 89, 1 ] - ]; - - assert.deepEqual(group_df.col([ "C" ]).count().values, new_data); - }); - it("sum column element in group", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - let new_data = [ - [ 1, 2, 3 ], - [ 4, 5, 6 ], - [ 20, 30, 40 ], - [ 39, 89, 78 ] - ]; - assert.deepEqual(group_df.col([ "C" ]).sum().values, new_data); - }); - - it("sum column element group by one column", function () { - - let data = [ [ 1, 2, 3 ], [ 1, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - - let new_data = [ - [ 1, 2, 2, 3 ], - [ 1, 5, 5, 6 ], - [ 20, 30, 30, 40 ], - [ 39, 89, 89, 78 ] - ]; - - assert.deepEqual(group_df.col([ "B", "C" ]).sum().values, new_data); - }); - - it("Perform aggregate on column for groupby", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - let new_data = [ - [ 1, 2, 2, 1 ], - [ 4, 5, 5, 1 ], - [ 20, 30, 30, 1 ], - [ 39, 89, 89, 1 ] - ]; - - assert.deepEqual(group_df.agg({ "B": "mean", "C": "count" }).values, new_data); - }); - it("cummulative sum for groupby", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - let new_data = [ - [ 1, 2, 2, 3 ], - [ 4, 5, 5, 6 ], - [ 20, 30, 30, 40 ], - [ 39, 89, 89, 78 ] - ]; - assert.deepEqual(group_df.col([ "B", "C" ]).cumsum().values, new_data); - }); - it("cummulative max for groupby", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A" ]); - let new_data = [ [ 1, 3 ], [ 4, 6 ], [ 20, 40 ], [ 39, 78 ] ]; - - - assert.deepEqual(group_df.col([ "C" ]).cummax().values, new_data); - }); - it("cummulative min for groupby", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A" ]); - let new_data = [ [ 1, 3 ], [ 4, 6 ], [ 20, 40 ], [ 39, 78 ] ]; - - assert.deepEqual(group_df.col([ "C" ]).cummin().values, new_data); - }); - - it("cummulative prod for groupby", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A" ]); - let new_data = [ [ 1, 3 ], [ 4, 6 ], [ 20, 40 ], [ 39, 78 ] ]; - - assert.deepEqual(group_df.col([ "C" ]).cumprod().values, new_data); - }); - it("mean for groupby", function () { - - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; - let cols = [ "A", "B", "C" ]; - let df = new DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A", "B" ]); - let new_data = [ - [ 1, 2, 2, 3 ], - [ 4, 5, 5, 6 ], - [ 20, 30, 30, 40 ], - [ 39, 89, 89, 78 ] - ]; - - assert.deepEqual(group_df.col([ "B", "C" ]).mean().values, new_data); - }); - - it("printing multiindex table, example with cumsum operation for dataframe group by one column", function(){ - let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', - 'foo', 'bar', 'foo', 'foo' ], - 'B': [ 'one', 'one', 'two', 'three', - 'two', 'two', 'one', 'three' ], - 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - - - let df = new DataFrame(data); - - let grp = df.groupby([ "A" ]); - let rslt = [ - [ 'foo', 1 ], - [ 'foo', 3 ], - [ 'foo', 8 ], - [ 'foo', 14 ], - [ 'foo', 21 ], - [ 'bar', 3 ], - [ 'bar', 7 ], - [ 'bar', 9 ] - ]; - assert.deepEqual(grp.col([ "C" ]).cumsum().values, rslt); - - }); - it("printing multiindex table, example with cumsum operation for dataframe group by one column", function(){ - let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', - 'foo', 'bar', 'foo', 'foo' ], - 'B': [ 'one', 'one', 'two', 'three', - 'two', 'two', 'one', 'three' ], - 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - - let df = new DataFrame(data); - - - let grp = df.groupby([ "A", "B" ]); - let rslt = [ - [ 'foo', 'one', 1, 3 ], - [ 'foo', 'one', 7, 10 ], - [ 'foo', 'two', 2, 4 ], - [ 'foo', 'two', 7, 9 ], - [ 'foo', 'three', 7, 8 ], - [ 'bar', 'one', 3, 2 ], - [ 'bar', 'two', 2, 6 ], - [ 'bar', 'three', 4, 1 ] - ]; - assert.deepEqual(grp.col([ "C", "D" ]).cumsum().values, rslt); - - }); - it("should apply grouby operation to all column", function(){ - let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', - 'foo', 'bar', 'foo', 'foo' ], - 'B': [ 'one', 'one', 'two', 'three', - 'two', 'two', 'one', 'three' ], - 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - - let df = new DataFrame(data); - - let grp = df.groupby([ "A", "B" ]); - let rslt = [ - [ 'foo', 'one', 2, 2 ], - [ 'foo', 'two', 2, 2 ], - [ 'foo', 'three', 1, 1 ], - [ 'bar', 'one', 1, 1 ], - [ 'bar', 'two', 1, 1 ], - [ 'bar', 'three', 1, 1 ] - ]; - - assert.deepEqual(grp.count().values, rslt); - }); - it("should apply function to specific column", function () { - - let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', - 'foo', 'bar', 'foo', 'foo' ], - 'B': [ 'one', 'one', 'two', 'three', - 'two', 'two', 'one', 'three' ], - 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - let df = new DataFrame(data); - let group_df = df.groupby([ "A"]); - let rslt = [ - [ 'foo', 5, 3 ], - [ 'foo', 6, 4 ], - [ 'foo', 7, 7 ], - [ 'foo', 9, 8 ], - [ 'foo', 10, 9 ], - [ 'bar', 4, 5 ], - [ 'bar', 3, 6 ], - [ 'bar', 8, 4 ] - ]; - assert.deepEqual(group_df.col(['D', 'C']).apply((x) => x.add(2)).values, rslt); - }); - it("should apply function to group column", function () { - - let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', - 'foo', 'bar', 'foo', 'foo' ], - 'B': [ 'one', 'one', 'two', 'three', - 'two', 'two', 'one', 'three' ], - 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - let df = new DataFrame(data); - let group_df = df.groupby([ "A", "B"]); - let rslt = [ - [ 'foo', 'one', 2, 2 ], - [ 'foo', 'two', 2, 2 ], - [ 'foo', 'three', 1, 1 ], - [ 'bar', 'one', 1, 1 ], - [ 'bar', 'two', 1, 1 ], - [ 'bar', 'three', 1, 1 ] - ]; - assert.deepEqual(group_df.apply((x) => x.count()).values, rslt); - }); -}); diff --git a/danfojs-node/tests/core/series.js b/danfojs-node/tests/core/series.js deleted file mode 100644 index 4c215a58..00000000 --- a/danfojs-node/tests/core/series.js +++ /dev/null @@ -1,1329 +0,0 @@ -import { assert, expect } from "chai"; -import { Series } from "../../dist"; -import * as tf from '@tensorflow/tfjs-node'; - -describe("Series", function () { - describe("tensor", function () { - it("Returns the tensor object of a Series", function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new Series(data); - assert.deepEqual(sf.dtype, "int32"); - }); - it("Returns the float dtype of a tensor object", function () { - let data = [1.1, 2.2, 3, 4.1, 5, 620, 30.1, 40, 39, 89, 78]; - let sf = new Series(data); - assert.deepEqual(sf.dtype, "float32"); - }); - it("Compares a tensor returned from a Series to Tensorflow's tensor", function () { - let data = [1.1, 2.2, 3, 4.1, 5, 620, 30.1, 40, 39, 89, 78]; - let sf = new Series(data); - let tf_data = tf.tensor(data); - assert.deepEqual(sf.tensor.arraySync(), tf_data.arraySync()); - }); - }); - describe("tensor", function () { - it("Returns the dtype string Series", function () { - let data = ["b", "c", "d"]; - let sf = new Series(data); - assert.deepEqual(sf.dtype, "string"); - }); - it("Returns the dtype int Series", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new Series(data); - assert.deepEqual(sf.dtype, "int32"); - }); - it("Returns the dtype int Series", function () { - let data = [1.1, 2.2, 3.3, 4.5, 5]; - let sf = new Series(data); - assert.deepEqual(sf.dtype, "float32"); - }); - }); - - describe("head", function () { - it("Gets the first n rows in a Series", function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let cols = ["A"]; - let sf = new Series(data, { columns: cols }); - assert.deepEqual(sf.head(2).values, [1, 2]); - }); - }); - - describe("tail", function () { - it("Prints the last n rows of a Series", function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new Series(data); - assert.deepEqual(sf.tail(2).values, [89, 78]); - }); - }); - - describe("sample", function () { - it("Samples n number of random elements from a DataFrame", async function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new Series(data); - assert.deepEqual((await sf.sample(7)).values.length, 7); - }); - it("Throw error if n is greater than lenght of Series", async function () { - let data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; - let sf = new Series(data); - try { - await sf.sample(100); - } catch (e) { - expect(e).to.be.instanceOf(Error); - expect(e.message).to.eql('Sample size n cannot be bigger than size of dataset'); - } - }); - }); - - describe("add", function () { - it("Return Addition of series with another series", function () { - let data = [1, 2, 3, 4, 5, 6]; - let data2 = [30, 40, 39, 1, 2, 1]; - let sf = new Series(data); - let sf2 = new Series(data2); - assert.deepEqual(sf.add(sf2).values, [31, 42, 42, 5, 7, 7]); - }); - it("Return Addition of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new Series(data); - assert.deepEqual(sf.add(1).values, [2, 3, 4, 5, 6]); - }); - it("Throws type error on addition of string type", function () { - let data = [1, 2, 3, 4]; - let data2 = ["A", "B", "C", "d"]; - let sf = new Series(data); - let sf2 = new Series(data2); - assert.throws( - () => { - sf.add(sf2); - }, - Error, - "DtypeError: String data type does not support add operation" - ); - }); - it("Throws length error if series lenght mixmatch", function () { - let data = [1, 2, 3, 4]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf = new Series(data); - let sf2 = new Series(data2); - assert.throws(() => { sf.add(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); - }); - }); - - describe("sub", function () { - it("Return Subtraction of series with another series", function () { - let data1 = [30, 40, 39, 1, 2, 1]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.sub(sf2).values, [29, 38, 36, -3, -3, -5]); - }); - it("Return Subtraction of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new Series(data); - assert.deepEqual(sf.sub(1).values, [0, 1, 2, 3, 4]); - }); - it("Throws type error on Subtraction of string type", function () { - let data = [1, 2, 3, 4]; - let data2 = ["A", "B", "C", "d"]; - let sf = new Series(data); - let sf2 = new Series(data2); - assert.throws( - () => { - sf.sub(sf2); - }, - Error, - "DtypeError: String data type does not support sub operation" - ); - }); - it("Throws length error if series lenght mixmatch", function () { - let data = [1, 2, 3, 4]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf = new Series(data); - let sf2 = new Series(data2); - assert.throws(() => { sf.sub(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); - }); - }); - - describe("mul", function () { - it("Return multiplication of series with another series", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [1, 2, 3, 4]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.mul(sf2).values, [30, 80, 9, 20]); - }); - it("Return multiplication of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new Series(data); - assert.deepEqual(sf.mul(1).values, [1, 2, 3, 4, 5]); - }); - it("Throws type error on multiplication of string type", function () { - let data = [1, 2, 3, 4]; - let data2 = ["A", "B", "C", "d"]; - let sf = new Series(data); - let sf2 = new Series(data2); - assert.throws(() => { sf.mul(sf2); }, Error, "DtypeError: String data type does not support mul operation"); - }); - it("Throws length error if series lenght mixmatch", function () { - let data = [1, 2, 3, 4]; - let data2 = [1, 2, 3, 4, 5, 6]; - let sf = new Series(data); - let sf2 = new Series(data2); - assert.throws(() => { sf.mul(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); - }); - }); - - describe("div", function () { - it("Return float division of series with another series", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [1, 2, 3, 4]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.div(sf2).values, [30, 20, 1, 1.25]); - }); - it("Return division of series with a single value (Broadcasting)", function () { - let data = [10, 2, 3, 90]; - let sf = new Series(data); - assert.deepEqual(sf.div(2).values, [5, 1, 1.5, 45]); - }); - }); - - describe("pow", function () { - it("Return Exponetial power of series with another series", function () { - let data1 = [2, 3, 4, 5]; - let data2 = [1, 2, 3, 0]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.pow(sf2).values, [2, 9, 64, 1]); - }); - it("Return Exponetial power of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new Series(data); - assert.deepEqual(sf.pow(2).values, [1, 4, 9, 16, 25]); - }); - }); - - describe("mod", function () { - it("Return modulo of series with another float series", function () { - let data1 = [2, 30, 4, 5]; - let data2 = [1.1, 2.2, 3.3, 2.4]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - let expected = [ - 0.8999999999999999, - 1.3999999999999977, - 0.7000000000000002, - 0.20000000000000018 - ]; - assert.deepEqual(sf1.mod(sf2).values, expected); - }); - it("Return modulo of series with another int series", function () { - let data1 = [2, 30, 4, 5]; - let data2 = [1, 2, 3, 1]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.mod(sf2).values, [0, 0, 1, 0]); - }); - it("Return modulo power of series with a single value (Broadcasting)", function () { - let data = [1, 2, 3, 4, 5]; - let sf = new Series(data); - assert.deepEqual(sf.mod(2).values, [1, 0, 1, 0, 1]); - }); - }); - - describe("mean", function () { - it("Computes the mean of elements in a int series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new Series(data1); - assert.deepEqual(sf.mean(), 19.5); - }); - it("Computes the mean of elements in a float series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.mean(), 19.625); - }); - it("Computes the mean of elements in a float series with NaN", function () { - let data1 = [30.1, 40.2, 3.1, 5.1, NaN]; - let sf = new Series(data1); - assert.deepEqual(sf.mean(), 19.625); - }); - it("Throws error if dtype is string", function () { - let data1 = ["boy", "girl", "Man"]; - let sf = new Series(data1); - assert.throws( - () => { - sf.mean(); - }, - Error, - "DtypeError: String data type does not support mean operation" - ); - }); - }); - - describe("median", function () { - it("Computes the median value of elements across int Series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new Series(data1); - assert.deepEqual(sf.median(), 17.5); - }); - it("Computes the median value of elements across float Series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1, NaN]; - let sf = new Series(data1); - assert.deepEqual(sf.median(), 17.6); - }); - }); - - describe("sum", function () { - it("Sum values of a Int Series", function () { - let data1 = [30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3]; - let sf = new Series(data1); - assert.deepEqual(sf.sum(), 131); - }); - it("Sum values of a Float Series", function () { - let data1 = [30.1, 3.1, 40.2, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.sum(), 81.6); - }); - it("Sum values of a bool Series", function () { - let data1 = [true, true, false, false, false]; - let sf = new Series(data1); - assert.deepEqual(sf.sum(), 2); - }); - it("Sum values a Series with missing values", function () { - let data1 = [11, NaN, 2, 2]; - let sf = new Series(data1); - assert.deepEqual(sf.sum(), 15); - }); - }); - - describe("mode", function () { - it("Computes the multi-modal values of a Series", function () { - let data1 = [30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3]; - let sf = new Series(data1); - assert.deepEqual(sf.mode(), [5, 3]); - }); - it("Computes the modal value of a Series", function () { - let data1 = [30.1, 3.1, 40.2, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.mode(), [3.1]); - }); - }); - - describe("min", function () { - it("Returns the single smallest elementin a Series", function () { - let data = [30, 40, 3, 5]; - let sf = new Series(data); - assert.deepEqual(sf.min(), 3); - }); - it("Computes the minimum of elements across an float Series", function () { - let data1 = [30.1, 40.2, 3.12, 5.1]; - let sf = new Series(data1, { dtypes: ["float32"] }); - assert.deepEqual(Number(sf.min().toFixed(2)), 3.12); - }); - }); - - describe("max", function () { - it("Computes the maximum of elements across dimensions of a Series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new Series(data1); - assert.deepEqual(sf.max(), 40); - }); - it("Return sum of float values in a series", function () { - let data1 = [30.1, 40.21, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(Number(sf.max().toFixed(2)), 40.21); - }); - it("Throws error on addition of string Series", function () { - let data1 = ["boy", "gitl", "woman", "man"]; - let sf = new Series(data1); - assert.throws( - () => { - sf.max(); - }, - Error, - "DtypeError: String data type does not support max operation" - ); - }); - }); - - describe("std", function () { - it("Computes the standard of elements in a int series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new Series(data1); - assert.deepEqual(sf.std(), 18.375708603116962); - }); - it("Computes the standard deviation of elements in a float series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.std(), 18.412925713566906); - }); - it("Computes the standard deviation of elements in a float series with missing values", function () { - let data1 = [30, 40, 3, 5, undefined]; - let sf = new Series(data1); - assert.deepEqual(sf.std(), 18.375708603116962); - }); - }); - - describe("var", function () { - it("Computes the variance of elements in a int series", function () { - let data1 = [30, 40, 3, 5]; - let sf = new Series(data1); - assert.deepEqual(sf.var(), 337.6666666666667); - }); - it("Computes the variance of elements in a float series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.var(), 339.03583333333336); - }); - it("Computes the variance of elements in a int series with missing values", function () { - let data1 = [30, undefined, 40, 3, 5]; - let sf = new Series(data1); - assert.deepEqual(sf.var(), 337.6666666666667); - }); - }); - - describe("describe", function () { - it("Computes the descriptive statistics on an int Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - assert.deepEqual(sf.describe().round().values, [ - 7, - 27, - 17.4, - 10, - 23, - 56, - 302 - ]); - }); - it("Computes the descriptive statistics on a float Series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.describe().round().values, [4, 19.6, 18.4, 3.1, 17.6, 40.2, 339]); - }); - it("Computes the descriptive statistics on a float Series", function () { - let data1 = [30.1, 40.2, 3.1, 5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.describe().index, [ - "count", - "mean", - "std", - "min", - "median", - "max", - "variance" - ]); - }); - }); - - describe("maximum", function () { - it("Returns the max of a and b (a > b ? a : b) element-wise. Supports broadcasting.", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [10, 41, 2, 0]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.maximum(sf2).values, [30, 41, 3, 5]); - }); - it("Throws error on checking maximum of incompatible Series", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [10, 41, 2]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.throws( - () => { - sf1.maximum(sf2); - }, - Error, - "ParamError: Row length mismatch. Length of other (3), must be the same as Ndframe (4)" - ); - }); - }); - - describe("minimum", function () { - it("Returns the min of a and b (a < b ? a : b) element-wise. Supports broadcasting.", function () { - let data1 = [30, 40, 3, 5]; - let data2 = [10, 41, 2, 0]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.minimum(sf2).values, [10, 40, 2, 0]); - }); - it("Return sum of float values in a series", function () { - let data1 = [30.1, 40.9, 3, 5]; - let data2 = [10.2, 41, 2, 0]; - let sf1 = new Series(data1); - let sf2 = new Series(data2); - assert.deepEqual(sf1.minimum(sf2).values, [10.2, 40.9, 2, 0]); - - }); - }); - - describe("count", function () { - it("Returns the count of non NaN values in a string Series", function () { - let data = ["boy", "gitl", "woman", NaN]; - let sf = new Series(data); - assert.deepEqual(sf.count(), 3); - }); - it("Returns the count of non NaN values in a string Series", function () { - let data = ["boy", "gitl", "woman", "Man"]; - let sf = new Series(data); - assert.deepEqual(sf.count(), 4); - }); - it("Returns the count of non NaN values in a int Series", function () { - let data = [20, 30, NaN, 2, NaN, 30, 21]; - let sf = new Series(data); - assert.deepEqual(sf.count(), 5); - }); - it("Returns the count of non NaN values in a float Series", function () { - let data = [20.1, 30.4, NaN, 2.1, NaN, 30.0, 21.3]; - let sf = new Series(data); - assert.deepEqual(sf.count(), 5); - }); - }); - - describe("round", function () { - it("Rounds elements in a Series to nearest whole number", function () { - let data1 = [30.21091, 40.190901, 3.564, 5.0212]; - let sf = new Series(data1); - assert.deepEqual(sf.round(0).values, [30, 40, 4, 5]); - }); - it("Rounds elements in a Series to 1dp", function () { - let data1 = [30.21091, 40.190901, 3.564, 5.0212]; - let sf = new Series(data1); - assert.deepEqual(sf.round(1).values, [30.2, 40.2, 3.6, 5.0]); - }); - it("Rounds elements in a Series to 2dp", function () { - let data1 = [30.2191, 40.190901, 3.564, 5.0212]; - let sf = new Series(data1); - assert.deepEqual(sf.round(2).values, [30.22, 40.19, 3.56, 5.02]); - }); - }); - - describe("isna", function () { - it("Return a boolean same-sized object indicating if string Series contain NaN", function () { - let data1 = [NaN, undefined, "girl", "Man"]; - let sf = new Series(data1); - assert.deepEqual(sf.isna().values, [true, true, false, false]); - }); - it("Return a boolean same-sized object indicating if float Series values are NaN", function () { - let data1 = [30.21091, NaN, 3.564, undefined]; - let sf = new Series(data1); - assert.deepEqual(sf.isna().values, [false, true, false, true]); - }); - it("Return a boolean same-sized object indicating if int Series values are NaN", function () { - let data1 = [30, 40, 3, 5, undefined, undefined]; - let sf = new Series(data1); - assert.deepEqual(sf.isna().values, [ - false, - false, - false, - false, - true, - true - ]); - }); - }); - - describe("sort_values", function () { - it("Sort values in a Series in ascending order (not inplace)", function () { - let sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [0, 1, 2, 4, 4, 20, 30, 57, 89]; - let sorted_sf = sf.sort_values(); - assert.deepEqual(sorted_sf.values, result); - }); - it("confirms that sort_values in ascending order does not happen inplace", function () { - let sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [0, 1, 2, 4, 4, 20, 30, 57, 89]; - let expected_index = [7, 2, 3, 8, 4, 0, 1, 5, 6]; - sf.sort_values({ inplace: true }); - assert.deepEqual(sf.values, result); - assert.deepEqual(sf.index, expected_index); - }); - it("Sort values in a Series in Descending order", function () { - let sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [89, 57, 30, 20, 4, 4, 2, 1, 0]; - let sorted_sf = sf.sort_values({ ascending: false }); - assert.deepEqual(sorted_sf.values, result); - }); - it("confirms that sort_values in descending order happens inplace", function () { - let sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [89, 57, 30, 20, 4, 4, 2, 1, 0]; - sf.sort_values({ ascending: false, inplace: true }); - assert.deepEqual(sf.values, result); - }); - it("Confirms that series index is sorted in ascending order (not in inplace)", function () { - let sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [7, 2, 3, 8, 4, 0, 1, 5, 6]; - let sorted_sf = sf.sort_values(); - assert.deepEqual(sorted_sf.index, result); - }); - it("Confirms that series index is sorted in descending order (not in inplace)", function () { - let sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); - let result = [6, 5, 1, 0, 4, 8, 3, 2, 7]; - let sorted_sf = sf.sort_values({ ascending: false }); - assert.deepEqual(sorted_sf.index, result); - }); - it("Sort string values in a Series", function () { - let sf = new Series(["boy", "zebra", "girl", "man"]); - let result = ["boy", "girl", "man", "zebra"]; - let sorted_sf = sf.sort_values({ ascending: false }); - assert.deepEqual(sorted_sf.values, result); - }); - }); - - describe("copy", function () { - it("Checks if copied values are the same as the first one", function () { - let sf = new Series([30.21091, 40.190901, 3.564, 5.0212]); - let sf_copy = sf.copy(); - assert.deepEqual(sf.values, sf_copy.values); - }); - it("Checks if copied index are the same", function () { - let sf = new Series([30.21091, 40.190901, 3.564, 5.0212]); - sf = sf.set_index({ index: ["a", "b", "c", "d"] }); - let sf_copy = sf.copy(); - assert.deepEqual(sf.index, sf_copy.index); - }); - it("Checks if copied dtype is the same", function () { - let sf = new Series([30.21091, 40.190901, 3.564, 5.0212]); - sf.round(); - sf.astype('int32'); - let sf_copy = sf.copy(); - assert.deepEqual(sf.dtypes[0], sf_copy.dtypes[0]); - assert.deepEqual(sf.values, sf_copy.values); - - }); - }); - - describe("reset_index", function () { - it("resets the index of a Series", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new Series(data); - let df_new = df.set_index({ index: ["one", "two", "three"] }); - let df_reset = df_new.reset_index(); - assert.deepEqual(df_reset.index, [0, 1, 2]); - }); - it("Reset the index of a Series created from an Array", function () { - let data = [1, 2, 3, 4, 5, 6]; - let df = new Series(data); - df.set_index({ - index: ["one", "two", "three", "four", "five", "six"], - inplace: true - }); - let df_new = df.reset_index(); - assert.deepEqual(df_new.index, [0, 1, 2, 3, 4, 5]); - }); - it("checks that the original series changed after reseting new index inplace", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new Series(data); - df.reset_index({ inplace: true }); - assert.deepEqual(df.index, [0, 1, 2]); - }); - }); - - describe("set_index", function () { - it("sets the index of an Series", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new Series(data); - let df_new = df.set_index({ index: ["one", "two", "three"] }); - assert.deepEqual(df_new.index, ["one", "two", "three"]); - assert.notDeepEqual(df.index, df_new.index); - }); - it("checks that the original series is not modified after setting new index not-inplace", function () { - let data = [ - { alpha: "A", count: 1 }, - { alpha: "B", count: 2 }, - { alpha: "C", count: 3 } - ]; - let df = new Series(data); - let df_new = df.set_index({ index: ["one", "two", "three"] }); - assert.notDeepEqual(df.index, df_new.index); - }); - it("sets the index of an Series inplace", function () { - let data = [12, 2, 20, 50]; - let df = new Series(data); - df.set_index({ index: ["one", "two", "three", "four"], inplace: true }); - assert.deepEqual(df.index, ["one", "two", "three", "four"]); - }); - }); - - describe("Map", function () { - it("map series element to object keys", function () { - let sf = new Series([1, 2, 3, 4]); - let map = { 1: "ok", 2: "okie", 3: "frit", 4: "gop" }; - - let rslt = ["ok", "okie", "frit", "gop"]; - - assert.deepEqual(sf.map(map).values, rslt); - }); - - it("map series element to a function statement", function () { - let sf = new Series([1, 2, 3, 4]); - let func_map = (x) => { - return x + 1; - }; - - let rslt = [2, 3, 4, 5]; - - assert.deepEqual(sf.map(func_map).values, rslt); - }); - }); - - describe("Apply", function () { - it("apply a function to a series element", function () { - let sf = new Series([1, 2, 3, 4, 5, 6, 7, 8]); - - let apply_func = (x) => { - return x + x; - }; - - let rslt = [2, 4, 6, 8, 10, 12, 14, 16]; - assert.deepEqual(sf.apply(apply_func).values, rslt); - }); - }); - - describe("unique", function () { - it("returns the unique values in a Series of type int", function () { - let sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5]); - let expected = [1, 2, 3, 4, 5, 6, 7, 8, 22]; - assert.deepEqual(sf.unique().values, expected); - }); - it("returns the unique values in a Series of type string", function () { - let sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected = ["a", "b", "c", "d", "e"]; - assert.deepEqual(sf.unique().values, expected); - }); - it("returns the unique values in a Series of type string", function () { - let sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected = ["a", "b", "c", "d", "e"]; - assert.deepEqual(sf.unique().values, expected); - }); - it("returns the nunique values in a Series of type string", function () { - let sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected = 5; - assert.deepEqual(sf.nunique(), expected); - }); - }); - - describe("value_counts", function () { - it("returns the unique values and their counts in a Series of type int", function () { - let sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5]); - let expected_index = [1, 2, 3, 4, 5, 6, 7, 8, 22]; - let expected_vals = [3, 1, 1, 1, 4, 1, 1, 2, 1]; - assert.deepEqual(sf.value_counts().values, expected_vals); - assert.deepEqual(sf.value_counts().index, expected_index); - }); - it("returns the unique values and their counts in a Series of type string", function () { - let sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); - let expected_vals = [2, 1, 2, 3, 2]; - let expected_index = ["a", "b", "c", "d", "e"]; - assert.deepEqual(sf.value_counts().values, expected_vals); - assert.deepEqual(sf.value_counts().index, expected_index); - }); - }); - - describe("abs", function () { - it("Returns the absolute values in Series", function () { - let data1 = [-10, 45, 56, -25, 23, -20, 10]; - let sf = new Series(data1); - assert.deepEqual(sf.abs().values, [10, 45, 56, 25, 23, 20, 10]); - }); - it("Computes the descriptive statistics on a float Series", function () { - let data1 = [-30.1, -40.2, -3.1, -5.1]; - let sf = new Series(data1); - assert.deepEqual(sf.abs().values, [30.1, 40.2, 3.1, 5.1]); - }); - }); - - describe("fillna", function () { - it("replace all NaN value with specified value", function () { - let data = [NaN, 1, 2, 33, 4, NaN, 5, 6, 7, 8]; - let sf = new Series(data); - let sf_val = [-999, 1, 2, 33, 4, -999, 5, 6, 7, 8]; - sf.fillna({ value: -999, inplace: true }); - assert.deepEqual(sf.values, sf_val); - }); - it("replace all NaN value in string Series with specified value", function () { - let data = [NaN, "boy", NaN, "hey", "Man", undefined]; - let sf = new Series(data); - let sf_val = ["filled", "boy", "filled", "hey", "Man", "filled"]; - let sf_fill = sf.fillna({ value: "filled" }); - assert.deepEqual(sf_fill.values, sf_val); - }); - }); - - describe("cumsum", function () { - it("Return cumulative sum over a Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - assert.deepEqual(sf.cumsum().values, [10, 55, 111, 136, 159, 179, 189]); - }); - }); - - describe("cummax", function () { - it("Return cumulative maximum over a Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - assert.deepEqual(sf.cummax().values, [10, 45, 56, 56, 56, 56, 56]); - }); - }); - - describe("cummin", function () { - it("Return cumulative minimum over a Series", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - assert.deepEqual(sf.cummin().values, [10, 10, 10, 10, 10, 10, 10]); - }); - }); - - describe("cumprod", function () { - it("Return cumulative product over a Series", function () { - let data1 = [1, 2, 10, 3, 12, 14, 1]; - let sf = new Series(data1); - let rslt = [1, 2, 20, 60, 720, 10080, 10080]; - assert.deepEqual(sf.cumprod().values, rslt); - }); - }); - - describe("lt", function () { - it("Return Less than of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 5, 25, 2, 0]; - - let sf = new Series(data1); - let sf2 = new Series(data2); - let expected = [true, true, true, false, true, false, false]; - assert.deepEqual(sf.lt(sf2).values, expected); - }); - - it("Return Less than of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - let expected = [true, false, false, true, true, true, true]; - assert.deepEqual(sf.lt(30).values, expected); - }); - it("Correct index is returned after operation", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new Series(data1, { index: ["one", "two", "three", "four", "five"] }); - - const expected = ["one", "two", "three", "four", "five"]; - assert.deepEqual(sf.lt(data2).index, expected); - }); - }); - - describe("gt", function () { - it("Return Greater than of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 5, 25, 2, 0]; - - let sf = new Series(data1); - let sf2 = new Series(data2); - let expected = [false, false, false, true, false, true, true]; - assert.deepEqual(sf.gt(sf2).values, expected); - }); - - it("Return Greater than of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - let expected = [false, true, true, false, false, false, false]; - assert.deepEqual(sf.gt(30).values, expected); - }); - }); - - describe("le", function () { - it("Return Less than or Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 5, 25, 2, 0]; - - let sf = new Series(data1); - let sf2 = new Series(data2); - let expected = [true, true, true, false, true, false, false]; - assert.deepEqual(sf.le(sf2).values, expected); - }); - - it("Return Less than or Equal to of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - let expected = [true, false, false, true, true, true, true]; - assert.deepEqual(sf.le(30).values, expected); - }); - }); - - describe("ge", function () { - it("Return Greater than or Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 56, 5, 25, 20, 0]; - - let sf = new Series(data1); - let sf2 = new Series(data2); - let expected = [false, false, true, true, false, true, true]; - assert.deepEqual(sf.ge(sf2).values, expected); - }); - - it("Return Greater than or Equal to of series scalar (element-wise)", function () { - let data1 = [30, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - let expected = [true, true, true, false, false, false, false]; - assert.deepEqual(sf.ge(30).values, expected); - }); - }); - - describe("ne", function () { - it("Return Not Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [10, 450, 56, 5, 25, 2, 0]; - - let sf = new Series(data1); - let sf2 = new Series(data2); - let expected = [false, true, false, true, true, true, true]; - assert.deepEqual(sf.ne(sf2).values, expected); - }); - - it("Return Not Equal to of series scalar (element-wise)", function () { - let data1 = [10, 30, 56, 30, 23, 20, 10]; - let sf = new Series(data1); - let expected = [true, false, true, false, true, true, true]; - assert.deepEqual(sf.ne(30).values, expected); - }); - }); - - describe("eq", function () { - it("Return Equal to of series and other series (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let data2 = [100, 450, 590, 25, 25, 2, 0]; - - let sf = new Series(data1); - let sf2 = new Series(data2); - let expected = [false, false, false, true, false, false, false]; - assert.deepEqual(sf.eq(sf2).values, expected); - }); - - it("Return Equal to of series scalar (element-wise)", function () { - let data1 = [10, 45, 56, 25, 23, 20, 30]; - let sf = new Series(data1); - let expected = [false, false, false, false, false, false, true]; - assert.deepEqual(sf.eq(30).values, expected); - }); - }); - - describe("replace", function () { - it("Replace values given in replace param with value", function () { - let data1 = [10, 45, 56, 25, 23, 20, 10]; - let sf = new Series(data1); - let expected = [-50, 45, 56, 25, 23, 20, -50]; - let df_rep = sf.replace({ oldValue: 10, newValue: -50 }); - assert.deepEqual(df_rep.values, expected); - }); - - it("Replace values given in replace param with value (String type)", function () { - let data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; - let sf = new Series(data1); - let expected = ["boy", "boy", "boy", "B", "B", "C", "C", "D"]; - sf.replace({ oldValue: "A", newValue: "boy", inplace: true }); - assert.deepEqual(sf.values, expected); - }); - it("Throw error on wrong param passed", function () { - let data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; - let sf = new Series(data1); - let expected = `Params Error: Must specify param 'oldValue' to replace`; - assert.throws( - () => { - sf.replace({ newValue: "boy", inplace: true }); - }, - Error, - expected - ); - }); - }); - - describe("drop_duplicates", function () { - it("Return Series with duplicate values removed (Default, first values kept)", function () { - let data1 = [10, 45, 56, 10, 23, 20, 10, 10]; - let sf = new Series(data1); - let expected = [10, 45, 56, 23, 20]; - let expected_index = [0, 1, 2, 4, 5]; - let df_drop = sf.drop_duplicates(); - assert.deepEqual(df_drop.values, expected); - assert.deepEqual(df_drop.index, expected_index); - }); - - it("Return Series with duplicate values removed (last values kept)", function () { - let data1 = [10, 45, 56, 10, 23, 20, 10, 10]; - let sf = new Series(data1); - let expected = [45, 56, 23, 20, 10]; - let expected_index = [1, 2, 4, 5, 7]; - let df_drop = sf.drop_duplicates({ keep: "last" }); - assert.deepEqual(df_drop.values, expected); - assert.deepEqual(df_drop.index, expected_index); - }); - - it("Return Series with duplicate values removed (String)", function () { - let data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; - let sf = new Series(data1); - let expected = ["A", "B", "C", "D"]; - let expected_index = [0, 3, 5, 7]; - sf.drop_duplicates({ inplace: true }); - assert.deepEqual(sf.values, expected); - assert.deepEqual(sf.index, expected_index); - }); - }); - - describe("dropna", function () { - it("Return a new Series with missing values removed (Int)", function () { - let data1 = [10, 45, undefined, 10, 23, 20, undefined, 10]; - let sf = new Series(data1); - let expected = [10, 45, 10, 23, 20, 10]; - let expected_index = [0, 1, 3, 4, 5, 7]; - let sf_drop = sf.dropna(); - assert.deepEqual(sf_drop.values, expected); - assert.deepEqual(sf_drop.index, expected_index); - }); - - it("Return a new Series with missing values removed (String)", function () { - let data1 = ["A", NaN, "A", "B", "B", NaN, "C", undefined]; - let sf = new Series(data1); - let expected = ["A", "A", "B", "B", "C"]; - let expected_index = [0, 2, 3, 4, 6]; - - sf.dropna({ inplace: true }); - assert.deepEqual(sf.values, expected); - assert.deepEqual(sf.index, expected_index); - }); - }); - - describe("argsort", function () { - it("Return the integer indices that would sort the Series values", function () { - let data1 = [10, 45, 20, 10, 23, 20, 30, 11]; - let sf = new Series(data1); - let expected = [3, 0, 7, 5, 2, 4, 6, 1]; - let sf_sort = sf.argsort(); - assert.deepEqual(sf_sort.values, expected); - }); - - it("Return the integer indices that would sort the Series values (Float)", function () { - let data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; - let sf = new Series(data1); - let expected = [2, 1, 3, 0, 7, 5, 4, 6]; - let sf_sort = sf.argsort(false); - assert.deepEqual(sf_sort.values, expected); - }); - }); - - describe("argmax", function () { - it("Return int position of the largest value in the Series.", function () { - let data1 = [10, 45, 20, 10, 23, 20, 30, 11]; - let sf = new Series(data1); - let expected = 1; - let argmax = sf.argmax(); - assert.deepEqual(argmax, expected); - }); - - it("Return int position of the largest value in the Float Series.", function () { - let data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; - let sf = new Series(data1); - let expected = 6; - let argmax = sf.argmax(); - assert.deepEqual(argmax, expected); - }); - }); - - describe("argmin", function () { - it("Return int position of the smallest value in the Series", function () { - let data1 = [10, 45, 20, 122, 23, 20, 30, 11]; - let sf = new Series(data1); - let expected = 0; - let argmin = sf.argmin(); - assert.deepEqual(argmin, expected); - }); - - it("Return int position of the smallest value in a Float Series", function () { - let data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; - let sf = new Series(data1); - let expected = 2; - let argmin = sf.argmin(); - assert.deepEqual(argmin, expected); - }); - }); - - describe("Str", function () { - it("Converts all characters to lowercase.", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["lower", "capitals", "this is a sentence", "swapcase"]; - let sf = new Series(data); - assert.deepEqual(sf.str.toLowerCase().values, res); - }); - it("Converts all characters to uppercase.", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["LOWER", "CAPITALS", "THIS IS A SENTENCE", "SWAPCASE"]; - let sf = new Series(data); - assert.deepEqual(sf.str.toUpperCase().values, res); - }); - it("Converts all characters to capital case.", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["Lower", "Capitals", "This is a sentence", "Swapcase"]; - let sf = new Series(data); - assert.deepEqual(sf.str.capitalize().values, res); - }); - - it("Returns the character at the specified index (position)", function () { - let data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; - let res = ["w", "P", "i", "A"]; - let sf = new Series(data); - assert.deepEqual(sf.str.charAt(2).values, res); - }); - - it("Throws error on concat of numeric series", function () { - let data = [1, 2, 3, 4, 5, 6]; - let sf = new Series(data); - assert.throws( - () => { - sf.str.concat("20", 1); - }, - Error, - "Cannot call accessor str on non-string type" - ); - - }); - }); - - describe("dt", function () { - it("check month generated", function () { - let data = ["02Sep2019", "03Dec2019", "04Jan2019"]; - let sf = new Series(data); - let new_data = [8, 11, 0]; - assert.deepEqual(sf.dt.month().values, new_data); - }); - - it("check month Name generated", function () { - let data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - let sf = new Series(data); - let new_data = ["Jun", "Jul", "Aug"]; - assert.deepEqual(sf.dt.month_name().values, new_data); - }); - - it("check days of the weeks generated", function () { - let data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - let sf = new Series(data); - let new_data = ["Sun", "Mon", "Wed"]; - assert.deepEqual(sf.dt.weekdays().values, new_data); - }); - - it("check day of the month generated", function () { - let data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - let sf = new Series(data); - let new_data = [30, 29, 28]; - assert.deepEqual(sf.dt.monthday().values, new_data); - }); - }); - - describe("astype", function () { - it("set type of float column to int", function () { - let data = [-20.1, 30, 47.3, -20]; - let ndframe = new Series(data); - let df = ndframe.astype("int32"); - - assert.deepEqual(df.dtypes, ["int32"]); - assert.deepEqual(df.values, [-20, 30, 47, -20]); - }); - it("set type of int column to float", function () { - let data = [34, -4, 5, 6]; - let ndframe = new Series(data); - let df = ndframe.astype("float32"); - assert.deepEqual(df.dtypes, ["float32"]); - assert.deepEqual(df.values, [34, -4, 5, 6]); - }); - it("set type of string column to int", function () { - let data = ["20.1", "21", "23.4", "50.78"]; - let ndframe = new Series(data); - let df = ndframe.astype("int32"); - - assert.deepEqual(df.dtypes, ["int32"]); - assert.deepEqual(df.values, [20, 21, 23, 50]); - }); - it("set type of string column to float", function () { - let data = ["20.1", "21", "23.4", "50.78"]; - let ndframe = new Series(data); - let df = ndframe.astype("float32"); - - assert.deepEqual(df.dtypes, ["float32"]); - assert.deepEqual(df.values, [20.1, 21, 23.4, 50.78]); - }); - }); - - describe("iloc", function () { - it("indexing by list of index", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new Series(data); - - let expected_val = [2, "a", 3, 4, "b"]; - - assert.deepEqual(sf.iloc([1, 4, 2, 3, 5]).values, expected_val); - }); - it("indexing by slicing", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new Series(data); - - let expected_val = [2, 3, 4]; - - assert.deepEqual(sf.iloc(["1:4"]).values, expected_val); - }); - it("indexing by slicing format ':5' works", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new Series(data); - let expected_val = [1, 2, 3, 4, 'a']; - assert.deepEqual(sf.iloc([":5"]).values, expected_val); - }); - it("indexing by slicing format '2:` works", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new Series(data); - let expected_val = [3, 4, "a", "b", "c"]; - assert.deepEqual(sf.iloc(["2:"]).values, expected_val); - }); - }); - - describe("append", function () { - it("Add a new single value to the end of a Series", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c", "d"]; - sf.append("d", "r1", { inplace: true }); - assert.deepEqual(sf.values, expected_val); - }); - it("Add a new array of values to the end of a Series", function () { - let data = [1, 2, 3, 4]; - let to_add = ["a", "b", "c"]; - let sf = new Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c"]; - sf.append(to_add, ["r1", "r2", "r3"], { inplace: true }); - assert.deepEqual(sf.values, expected_val); - }); - it("Add a Series to the end of another Series", function () { - let sf1 = new Series([1, 2, 3, 4]); - let sf2 = new Series(["a", "b", "c"]); - let expected_val = [1, 2, 3, 4, "a", "b", "c"]; - sf1.append(sf2, ["r1", "r2", "r3"], { inplace: true }); - assert.deepEqual(sf1.values, expected_val); - }); - it("Add a new single value to the end of a Series", function () { - let data = [1, 2, 3, 4, "a", "b", "c"]; - let sf = new Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c", "d"]; - sf = sf.append("d", "r1"); - assert.deepEqual(sf.values, expected_val); - }); - it("Add a new array of values to the end of a Series", function () { - let data = [1, 2, 3, 4]; - let to_add = ["a", "b", "c"]; - let sf = new Series(data); - let expected_val = [1, 2, 3, 4, "a", "b", "c"]; - sf = sf.append(to_add, ["r1", "r2", "r3"]); - assert.deepEqual(sf.values, expected_val); - }); - }); - - describe("or", function () { - it("Return logical OR of series and other series (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new Series(data1); - const sf2 = new Series(data2); - - const expected = [true, true, true, true, false]; - assert.deepEqual(sf.or(sf2).values, expected); - }); - - it("Return logical OR of series and other scalar", function () { - const data1 = [true, true, true, false, false]; - const sf = new Series(data1); - - const expected = [true, true, true, true, true]; - assert.deepEqual(sf.or(true).values, expected); - }); - - it("Return logical OR of series and other array (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new Series(data1); - - const expected = [true, true, true, true, false]; - assert.deepEqual(sf.or(data2).values, expected); - }); - it("Correct index is returned after operation", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new Series(data1, { index: ["one", "two", "three", "four", "five"] }); - - const expected = ["one", "two", "three", "four", "five"]; - assert.deepEqual(sf.and(data2).index, expected); - }); - }); - - describe("and", function () { - it("Return logical AND of series and other series (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new Series(data1); - const sf2 = new Series(data2); - - const expected = [true, false, true, false, false]; - assert.deepEqual(sf.and(sf2).values, expected); - }); - - it("Return logical AND of series and other scalar", function () { - const data1 = [true, true, true, false, false]; - const sf = new Series(data1); - - const expected = [true, true, true, false, false]; - assert.deepEqual(sf.and(true).values, expected); - }); - - it("Return logical AND of series and other array (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new Series(data1); - - const expected = [true, false, true, false, false]; - assert.deepEqual(sf.and(data2).values, expected); - }); - - it("Chaining works for logical AND of series and other array (element-wise)", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const data3 = [true, false, false, true, false]; - - const sf = new Series(data1); - const expected = [true, false, false, false, false]; - assert.deepEqual(sf.and(data2).and(data3).values, expected); - }); - - it("Chaining works for logical AND and OR combined", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const data3 = [true, false, false, true, false]; - - const sf = new Series(data1); - const expected = [true, false, true, true, false]; - assert.deepEqual(sf.and(data2).or(data3).values, expected); - }); - it("Correct index is returned after operation", function () { - const data1 = [true, true, true, false, false]; - const data2 = [true, false, true, true, false]; - const sf = new Series(data1, { index: ["one", "two", "three", "four", "five"] }); - - const expected = ["one", "two", "three", "four", "five"]; - assert.deepEqual(sf.and(data2).index, expected); - }); - }); - -}); diff --git a/danfojs-node/tests/core/strings.js b/danfojs-node/tests/core/strings.js deleted file mode 100644 index c90a9d9f..00000000 --- a/danfojs-node/tests/core/strings.js +++ /dev/null @@ -1,167 +0,0 @@ -import { assert } from "chai"; -import { Series, Str } from "../../dist"; - - -describe("Str", function () { - it("Converts all characters to lowercase.", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = ['lower', 'capitals', 'this is a sentence', 'swapcase']; - let str = new Str(new Series(data)); - assert.deepEqual(str.toLowerCase().values, res); - }); - it("Converts all characters to uppercase.", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = ['LOWER', 'CAPITALS', 'THIS IS A SENTENCE', 'SWAPCASE']; - let str = new Str(new Series(data)); - assert.deepEqual(str.toUpperCase().values, res); - }); - it("Converts all characters to capital case.", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = ['Lower', 'Capitals', 'This is a sentence', 'Swapcase']; - let str = new Str(new Series(data)); - assert.deepEqual(str.capitalize().values, res); - }); - - it("Returns the character at the specified index (position)", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = ["w", "P", "i", "A"]; - let str = new Str(new Series(data)); - assert.deepEqual(str.charAt(2).values, res); - }); - it("Joins two or more strings. 0 joins from the start", function () { - let data = ['lower', 'CAPITALS', 'sentence', 'SwApCaSe']; - let data2 = ['XX', 'YY', 'BB', '01']; - - let res = ['XXlower', 'YYCAPITALS', 'BBsentence', '01SwApCaSe']; - let str = new Str(new Series(data)); - assert.deepEqual(str.concat(data2, 0).values, res); - }); - - it("Joins two or more strings. 1 joins from the end", function () { - let data = ['lower', 'CAPITALS', 'sentence', 'SwApCaSe']; - let data2 = ['XX', 'YY', 'BB', '01']; - - let res = ['lowerXX', 'CAPITALSYY', 'sentenceBB', 'SwApCaSe01']; - let str = new Str(new Series(data)); - assert.deepEqual(str.concat(data2, 1).values, res); - }); - - it("Joins two arrays of strings. 0 joins from the start", function () { - let data = ['lower', 'CAPITALS', 'sentence', 'SwApCaSe']; - let res = ['prelower', 'preCAPITALS', 'presentence', 'preSwApCaSe']; - let str = new Str(new Series(data)); - assert.deepEqual(str.concat("pre", 0).values, res); - }); - - it("Joins two or more strings. 1 joins from the end", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = ['lowerpost', 'CAPITALSpost', 'this is a sentencepost', 'SwApCaSepost']; - let str = new Str(new Series(data)); - assert.deepEqual(str.concat("post", 1).values, res); - }); - - it("Checks whether a string begins with specified characters", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = [true, false, false, false]; - let str = new Str(new Series(data)); - assert.deepEqual(str.startsWith("l").values, res); - }); - it("Checks whether a string ends with specified characters", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = [false, false, true, true]; - let str = new Str(new Series(data)); - assert.deepEqual(str.endsWith("e").values, res); - }); - - it("Checks whether a string contains the specified string/characters", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = [false, false, true, false]; - let str = new Str(new Series(data)); - assert.deepEqual(str.includes("sentence").values, res); - }); - - it("Returns the position of the first found occurrence of a specified value in a string", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = [-1, 0, -1, 4]; - let str = new Str(new Series(data)); - assert.deepEqual(str.indexOf("C").values, res); - }); - - it("Returns the position of the last found occurrence of a specified value in a string", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = [4, -1, -1, -1]; - let str = new Str(new Series(data)); - assert.deepEqual(str.lastIndexOf("r").values, res); - }); - - it("Returns a new string with a specified number of copies of an existing string", function () { - let data = ['a', 'b', 'c', 'd']; - let res = ['aaa', 'bbb', 'ccc', 'ddd']; - let str = new Str(new Series(data)); - assert.deepEqual(str.repeat(3).values, res); - }); - - it("Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = ['lower', 'CXXXPITALS', 'this is a sentence', 'SwXXXpCaSe']; - let str = new Str(new Series(data)); - assert.deepEqual(str.replace("A", "XXX").values, res); - }); - - it("Searches a string for a specified value, or regular expression, and returns the position of the match", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = [-1, 1, -1, 2]; - let str = new Str(new Series(data)); - assert.deepEqual(str.search("A").values, res); - }); - - it("Extracts a part of a string and returns a new string", function () { - let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = ['ow', 'AP', 'hi', 'wA']; - let str = new Str(new Series(data)); - assert.deepEqual(str.slice(1, 3).values, res); - }); - - it("Splits a string into an array of substrings", function () { - let data = ['lower part', 'CAPITALS city', 'is a sentence', 'SwAp CaSe']; - let res = ["lower,part", "CAPITALS,city", "is,a,sentence", "SwAp,CaSe"]; - let str = new Str(new Series(data)); - assert.deepEqual(str.split(" ").values, res); - }); - - it("Extracts the characters from a string, beginning at a specified start position, and through the specified number of character", function () { - let data = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; - let res = [" p", "AL", "is", "Ca"]; - let str = new Str(new Series(data)); - assert.deepEqual(str.substr(5, 2).values, res); - }); - - it("Extracts the characters from a string, between two specified indices", function () { - let data = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; - let res = ["w", "P", "i", "A"]; - let str = new Str(new Series(data)); - assert.deepEqual(str.substring(2, 3).values, res); - }); - - it("Removes whitespace from both ends of a string", function () { - let data = ['lower part ', ' CAPITALS city', ' this is a sentence', ' SwAp CaSe']; - let res = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; - let str = new Str(new Series(data)); - assert.deepEqual(str.trim().values, res); - }); - - it("Joins strings to specified value", function () { - let data = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; - let res = ['lower part,new', 'CAPITALS city,new', 'this is a sentence,new', 'SwAp CaSe,new']; - let str = new Str(new Series(data)); - assert.deepEqual(str.join("new", ",").values, res); - }); - - it("Counts the number of characters in string", function () { - let data = ['lower part', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; - let res = [10, 8, 18, 8]; - let str = new Str(new Series(data)); - assert.deepEqual(str.len().values, res); - }); - -}); diff --git a/danfojs-node/tests/core/timeseries.js b/danfojs-node/tests/core/timeseries.js deleted file mode 100644 index c1cbe7eb..00000000 --- a/danfojs-node/tests/core/timeseries.js +++ /dev/null @@ -1,92 +0,0 @@ -import { assert } from "chai"; -import { Series, toDateTime } from "../../dist"; - -describe("TimeSeries", function () { - - it("Returns correct month number", function () { - const data = ["02Sep2019", "03Aug2019", "04July2019"]; - const dateTime = toDateTime(data); - const expected = [8, 7, 6]; - assert.deepEqual(dateTime.month().values, expected); - }); - - it("Returns correct year number", function () { - const data = ["02Sep2019", "03Aug2029", "04July2020"]; - const dateTime = toDateTime(data); - const expected = [2019, 2029, 2020]; - assert.deepEqual(dateTime.year().values, expected); - }); - - it("Return month name generated", function () { - const data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - const dateTime = toDateTime(data); - const expected = ["Jun", "Jul", "Aug"]; - assert.deepEqual(dateTime.month_name().values, expected); - }); - - it("Return day of the week generated", function () { - const data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - const dateTime = toDateTime(data); - const expected = ["Sun", "Mon", "Wed"]; - assert.deepEqual(dateTime.weekdays().values, expected); - }); - - it("Return day of the month generated", function () { - const data = ["06-30-02019", "07-29-2019", "08-28-2019"]; - const dateTime = toDateTime(data); - const expected = [30, 29, 28]; - assert.deepEqual(dateTime.monthday().values, expected); - }); - - it("Return seconds generated", function () { - const data = ["06-30-02019 00:00:12", "07-29-2019 00:30:40", "08-28-2019 00:12:04"]; - const dateTime = toDateTime(data); - const expected = [12, 40, 4]; - assert.deepEqual(dateTime.seconds().values, expected); - }); - - it("Return minutes generated", function () { - const data = ["06-30-02019 00:00:12", "07-29-2019 00:30:40", "08-28-2019 00:12:04"]; - const dateTime = toDateTime(data); - const expected = [0, 30, 12]; - assert.deepEqual(dateTime.minutes().values, expected); - }); - - it("Return hours generated", function () { - const data = ["06-30-02019 05:00:12", "07-29-2019 01:30:40", "08-28-2019 06:12:04"]; - const dateTime = toDateTime(data); - const expected = [5, 1, 6]; - assert.deepEqual(dateTime.hours().values, expected); - }); - - it("Return correct date from Series format 1", function () { - const data = new Series(["12/30/19 00:01", "12/29/19 07:03", "11/12/20 18:21"]); - const dateTime = toDateTime(data); - - const expectedMonth = [11, 11, 10]; - const expectedYear = [2019, 2019, 2020]; - const expectedDayOfMonth = [30, 29, 12]; - const expectedMonthName = ["Dec", "Dec", "Nov"]; - - assert.deepEqual(dateTime.month().values, expectedMonth); - assert.deepEqual(dateTime.year().values, expectedYear); - assert.deepEqual(dateTime.monthday().values, expectedDayOfMonth); - assert.deepEqual(dateTime.month_name().values, expectedMonthName); - }); - - it("Return correct date from Series format 2", function () { - const data = new Series(["12.30.19", "12.22.19", "11.01.20"]); - const dateTime = toDateTime(data); - - const expectedMonth = [11, 11, 10]; - const expectedYear = [2019, 2019, 2020]; - const expectedDay = [ 'Mon', 'Sun', 'Sun' ]; - const expectedMonthName = ["Dec", "Dec", "Nov"]; - - assert.deepEqual(dateTime.month().values, expectedMonth); - assert.deepEqual(dateTime.year().values, expectedYear); - assert.deepEqual(dateTime.weekdays().values, expectedDay); - assert.deepEqual(dateTime.month_name().values, expectedMonthName); - - }); -}); diff --git a/danfojs-node/tests/io/reader.js b/danfojs-node/tests/io/reader.js deleted file mode 100644 index 05c862e7..00000000 --- a/danfojs-node/tests/io/reader.js +++ /dev/null @@ -1,78 +0,0 @@ -import { assert } from "chai"; -import { read_csv, read_json, read_excel } from "../../dist"; -import path from "path"; - -describe("read_csv", async function () { - this.timeout(10000); // all tests in this suite get 10 seconds before timeout - it("reads a csv file from source over the internet", async function () { - const csvUrl = - "https://storage.googleapis.com/tfjs-examples/multivariate-linear-regression/data/boston-housing-train.csv"; - - const df = await read_csv(csvUrl); - const num_of_columns = df.columns.length; - assert.equal(num_of_columns, 13); - - }); - - it("reads a csv file from source from local disk", async function () { - const csvUrl = path.join(process.cwd(), "tests", "samples", "titanic.csv"); - const df = await read_csv(csvUrl, { header: true }); - const num_of_columns = df.columns.length; - assert.equal(num_of_columns, 8); - }); -}); - -describe("read_json", async function () { - this.timeout(100000); // all tests in this suite get 10 seconds before timeout - it("reads a json file from source over the internet", async function () { - const jUrl = - "https://raw.githubusercontent.com/opensource9ja/danfojs/dev/danfojs-node/tests/samples/book.json"; - - const df = await read_json(jUrl); - assert.deepEqual(df.columns, [ - 'book_id', - 'title', - 'image_url', - 'authors' - ]); - assert.deepEqual(df.dtypes, [ - 'int32', 'string', - 'string', 'string' - ]); - - }); - - it("reads a json file from source from local disk", async function () { - const jUrl = path.join(process.cwd(), "tests", "samples", "book.json"); - - const df = await read_json(jUrl); - const num_of_columns = df.columns.length; - assert.equal(num_of_columns, 4); - }); -}); - -describe("read_excel", async function () { - this.timeout(10000); // all tests in this suite get 10 seconds before timeout - it("reads an excel file from source over the internet", async function () { - const remote_url = - "https://raw.githubusercontent.com/opensource9ja/danfojs/dev/danfojs-node/tests/samples/SampleData.xlsx"; - const df = await read_excel(remote_url); - assert.deepEqual(df.columns, [ - 'Year', - 'Stocks', - 'T.Bills', - 'T.Bonds' - ]); - assert.deepEqual(df.dtypes, [ - 'int32', 'float32', - 'float32', 'float32' - ]); - assert.deepEqual(df.shape, [ 82, 4 ]); - }); - - it("reads an excel file from source from local disk", async function () { - const file_url = path.join(process.cwd(), "tests", "samples", "SampleData.xlsx"); - const df = await read_excel(file_url); - assert(df.columns.length, 4); - }); -}); diff --git a/danfojs-node/tests/preprocessing/encodings.js b/danfojs-node/tests/preprocessing/encodings.js deleted file mode 100644 index ef105848..00000000 --- a/danfojs-node/tests/preprocessing/encodings.js +++ /dev/null @@ -1,97 +0,0 @@ -import { assert } from "chai"; -import { Series, LabelEncoder, OneHotEncoder } from '../../dist'; - - -describe("Encodings", function () { - - describe("LabelEncoder", function () { - - it("test the label encoding on array", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let encode = new LabelEncoder(); - let fit_data = [ - 0, 1, 2, 0, - 1, 2, 2, 1 - ]; - assert.deepEqual(encode.fit(data).values, fit_data); - assert.deepEqual(encode.transform([ "dog", "man" ]).values, [ 0, 2 ]); - }); - it("test the label encoding on Series", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let series = new Series(data); - let encode = new LabelEncoder(); - let fit_data = [ - 0, 1, 2, 0, - 1, 2, 2, 1 - ]; - assert.deepEqual(encode.fit(series).values, fit_data); - assert.deepEqual(encode.transform([ "dog", "man" ]).values, [ 0, 2 ]); - }); - it("label encoding directly from a Series", function () { - let data = new Series([ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]); - let to_label_encode = new Series([ "dog", "man" ]); - let encode = new LabelEncoder(); - let fit_data = [ - 0, 1, 2, 0, - 1, 2, 2, 1 - ]; - assert.deepEqual(encode.fit(data).values, fit_data); - assert.deepEqual(encode.transform(to_label_encode).values, [ 0, 2 ]); - }); - // it("Label encoding on Series", function () { - // let data = ["dog", "cat", "man", "dog", "cat", "man", "man", "cat"] - // let series = new Series(data) - // let encode = new LabelEncoder() - // let fit_data = [ - // 0, 1, 2, 0, - // 1, 2, 2, 1 - // ] - // assert.deepEqual(encode.fit(series).values, fit_data) - // assert.deepEqual(encode.transform(["dog", "man"]).values, [0, 2]) - // }); - - }); - - describe("OneHotEncoder", function () { - - it("test onehotencoding on array", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let encode = new OneHotEncoder(); - let fit_data = [ - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 0, 0, 1 ], - [ 0, 1, 0 ] - ]; - let transform_data = [ [ 0, 0, 1 ], [ 0, 1, 0 ] ]; - - assert.deepEqual(encode.fit(data).values, fit_data); - assert.deepEqual(encode.transform([ "man", "cat" ]).values, transform_data); - }); - it("test onehotencoding on Series", function () { - let data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; - let series = new Series(data); - let encode = new OneHotEncoder(); - let fit_data = [ - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 1, 0, 0 ], - [ 0, 1, 0 ], - [ 0, 0, 1 ], - [ 0, 0, 1 ], - [ 0, 1, 0 ] - ]; - let transform_data = [ [ 0, 0, 1 ], [ 0, 1, 0 ] ]; - - assert.deepEqual(encode.fit(series).values, fit_data); - assert.deepEqual(encode.transform(new Series([ "man", "cat" ])).values, transform_data); - }); - }); - - -}); diff --git a/danfojs-node/tests/preprocessing/scaler.js b/danfojs-node/tests/preprocessing/scaler.js deleted file mode 100644 index 76c8d103..00000000 --- a/danfojs-node/tests/preprocessing/scaler.js +++ /dev/null @@ -1,86 +0,0 @@ -import { assert } from "chai"; -import { Series, DataFrame, MinMaxScaler, StandardScaler } from '../../dist'; - - -describe("Preprocessing", function(){ - - describe("MinMaxscaler", function(){ - - it("Standardize values in a DataFrame", function(){ - let data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; - let scaler = new MinMaxScaler(); - let fit_data = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; - let transform_data = [ [ 1.5, 0. ] ]; - scaler.fit(new DataFrame(data)); - assert.deepEqual(scaler.transform(new DataFrame(data)).values, fit_data); - assert.deepEqual(scaler.transform([ [ 2, 2 ] ]).values, transform_data); - }); - it("Standardize values in a Series", function(){ - let data = [ -1, 2, -0.5, 60, 101, 18 ]; - let scaler = new MinMaxScaler(); - let result = [ 0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677 ]; - let transform_data = [ 0.029411764815449715, 0.029411764815449715 ]; - scaler.fit(new Series(data)); - assert.deepEqual(scaler.transform(new Series(data)).values, result); - assert.deepEqual(scaler.transform([ 2, 2 ]).values, transform_data); - }); - it("should be able to inverse the normalization of a Series", function() { - let data = [ -1, 2, -0.5, 60, 101, 18 ]; - let result = [ 0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677 ]; - let scaler = new MinMaxScaler(); - scaler.fit(new Series(data)); - assert.deepEqual(scaler.inverse_transform(new Series(result)).values, data); - }); - it("should be able to inverse the normalization of a DataFrame", function(){ - let data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; - let result = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; - let scaler = new MinMaxScaler(); - scaler.fit(new DataFrame(data)); - assert.deepEqual(scaler.inverse_transform(new DataFrame(result)).values, data); - }); - }); - - describe("StandardScaler", function(){ - - it("basic test", function(){ - let data = [ [ 0, 0 ], [ 0, 0 ], [ 1, 1 ], [ 1, 1 ] ]; - - let scaler = new StandardScaler(); - let fit_data = [ [ -1, -1 ], [ -1, -1 ], [ 1, 1 ], [ 1, 1 ] ]; - let transform_data = [ [ 3, 3 ] ]; - - assert.deepEqual(scaler.fit(new DataFrame(data)).round().values, fit_data); - assert.deepEqual(scaler.transform([ [ 2, 2 ] ]).round().values, transform_data); - }); - it("should be able to inverse the normalization of a Series", function() { - let data = [ -1, 2, -0.5, 60, 101, 18 ]; - let result = [ 0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677 ]; - let scaler = new MinMaxScaler(); - scaler.fit(new Series(data)); - assert.deepEqual(scaler.inverse_transform(new Series(result)).values, data); - }); - it("should be able to inverse the normalization of a DataFrame", function(){ - let data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; - let result = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; - let scaler = new MinMaxScaler(); - scaler.fit(new DataFrame(data)); - assert.deepEqual(scaler.inverse_transform(new DataFrame(result)).values, data); - }); - }); - - - // describe("RobustScaler", function(){ - // it("basic test", function(){ - - // let data = [[3,1], [7,3], [8,4], [5,6], [12,5], [14,12], [21,23], [15,15], [18,2], [14,15]] - // // let data2 = [[4,100,900],[5,110,800],[21,220,890],[20,300,500]] - // let data2 = [0, 4, 4, 4, 7, 10, 11, 12, 14, 16, 17, 25] - - - // let scaler = new RobustScaler() - - // // console.log(scaler.quantile(data2,true)) - - // }); - // }); -}); diff --git a/danfojs-node/tests/samples/SampleData.xlsx b/danfojs-node/tests/samples/SampleData.xlsx deleted file mode 100644 index 67a11847..00000000 Binary files a/danfojs-node/tests/samples/SampleData.xlsx and /dev/null differ diff --git a/danfojs-node/types/core/concat.d.ts b/danfojs-node/types/core/concat.d.ts deleted file mode 100644 index 269f31e2..00000000 --- a/danfojs-node/types/core/concat.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class Concat { - constructor(kwargs?: any); -} -export function concat(kwargs?: any): DataFrame; -import { DataFrame } from "./frame"; diff --git a/danfojs-node/types/core/date_range.d.ts b/danfojs-node/types/core/date_range.d.ts deleted file mode 100644 index 58f7060a..00000000 --- a/danfojs-node/types/core/date_range.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Generate date range between a specified set of date - * @param {kwargs} kwargs { - * start : string - * end : string - * period: int - * freq : string - * } - * @returns Array - */ -export class date_range { - constructor(kwargs?: any); - offset: number; - start?: any; - end?: any; - period?: any; - freq?: any; - freq_list: string[]; - range(start?: any, end?: any, period?: any, offset?: any): any; - freq_type(date?: any, ftype?: any): any; - offset_count(d_array?: any, offset?: any): any[]; - set_dateProps(date?: any, ftype?: any, val?: any): Date; - toLocalString(d_array?: any): any; - month_end(start_date?: any, end_date?: any): any; - month_range(range?: any): any; - day_end(start_date?: any, end_date?: any): number; -} diff --git a/danfojs-node/types/core/datetime.d.ts b/danfojs-node/types/core/datetime.d.ts deleted file mode 100644 index 77c6d23e..00000000 --- a/danfojs-node/types/core/datetime.d.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -import { ArrayType1D, DateTime } from "../shared/types"; -/** - * Format and handle all datetime operations on Series or Array of date strings - * @param data Series or Array of date strings - */ -export default class TimeSeries implements DateTime { - private $dateObjectArray; - constructor(data: Series | ArrayType1D); - /** - * Processed the data values into internal structure for easy access - * @param dateArray An array of date strings - */ - private processData; - /** - * Returns the month, in local time. - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2019-03-01", - * "2019-04-01", - * ] - * const df = new Dataframe(data) - * const dfNew = df.dt.month() - * console.log(dfNew.values) - * // [1, 2, 3, 4] - * ``` - */ - month(): Series; - /** - * Returns the day of the week, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2019-03-01", - * "2019-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfWeek = df.dt.day() - * console.log(day.values) - * ``` - */ - day(): Series; - /** - * Returns the year, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const year = df.dt.year() - * console.log(year.values) - * // [2019, 2019, 2021, 2020] - * ``` - */ - year(): Series; - /** - * Returns the name of the month, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const monthName = df.dt.month_name().values - * console.log(monthName) - * // ["January", "February", "March", "April"] - * ``` - */ - month_name(): Series; - /** - * Returns the name of the day, of the week, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-01", - * "2021-03-01", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfWeekName = df.dt.weekdays().values - * console.log(dayOfWeekName) - * ``` - */ - weekdays(): Series; - /** - * Returns the day of the month, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const dayOfMonth = df.dt.monthday().values - * console.log(dayOfMonth) - * // [1, 5, 2, 1] - * ``` - */ - monthday(): Series; - /** - * Returns the hour of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const hour = df.dt.hour().values - * console.log(hour) - * // [0, 0, 0, 0] - * ``` - */ - hours(): Series; - /** - * Returns the second of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const second = df.dt.second().values - * console.log(second) - * ``` - */ - seconds(): Series; - /** - * Returns the minute of the day, in local time - * @example - * ``` - * import { Dataframe } from "danfojs-node" - * const data = [ - * "2019-01-01", - * "2019-02-05", - * "2021-03-02", - * "2020-04-01", - * ] - * const df = new Dataframe(data) - * const minute = df.dt.minute().values - * console.log(minute) - * ``` - */ - minutes(): Series; -} -export declare const toDateTime: (data: Series | ArrayType1D) => TimeSeries; diff --git a/danfojs-node/types/core/frame.d.ts b/danfojs-node/types/core/frame.d.ts deleted file mode 100644 index d115dbd4..00000000 --- a/danfojs-node/types/core/frame.d.ts +++ /dev/null @@ -1,555 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { ArrayType1D, ArrayType2D, DataFrameInterface, BaseDataOptionType } from "../shared/types"; -import NDframe from "./generic"; -import Series from './series'; -import { GroupBy } from "./groupby"; - - -/** - * A 2D frame object that stores data in structured tabular format - * @param {data} data, JSON, Array, 2D Tensor - * @param {kwargs} Object {columns: Array of column names, defaults to ordered numbers when not specified - * dtypes: strings of data types, automatically inferred when not specified - * index: row index for subseting array, defaults to ordered numbers when not specified} - * - * @returns DataFrame - */ -export class DataFrame extends NDframe implements DataFrameInterface { - [key: string]: any; - constructor(data: any, options?: BaseDataOptionType); - - /** - * Drop columns or rows with missing values. Missing values are NaN, undefined or null. - * @param options.columns Array of column names to drop - * @param options.index Array of index to drop - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop(options?: { - columns?: string | Array; - index?: Array; - inplace?: boolean; - }): DataFrame | void; - /** - * Access a group of rows and columns by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc({ rows, columns }: { - rows?: Array | Series; - columns?: Array; - }): DataFrame; - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * @param columns Array of column indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc({ rows, columns }: { - rows?: Array | Series; - columns?: Array; - }): DataFrame; - /** - * Prints the first n values in a dataframe - * @param {rows} rows --> int - * @returns DataFrame - */ - head(rows?: number): DataFrame; - /** - * Prints the last n values in a dataframe - * @param {rows} rows --> int - * @returns DataFrame - */ - tail(rows?: number): DataFrame; - /** - * Gets n number of random rows in a dataframe. Sample is reproducible if seed is provided. - * @param num The number of rows to return. Default to 5. - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - sample(num?: number, options?: { - seed?: number; - }): Promise; - - /** - * Return Addition of DataFrame and other, element-wise (binary operator add). - * @param other DataFrame, Series, Array or Scalar number to add - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return substraction between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to substract from DataFrame - * @param options.axis 0 or 1. If 0, compute the subtraction column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return multiplciation between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to multiply with. - * @param options.axis 0 or 1. If 0, compute the multiplication column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return division of DataFrame with other. - * @param other DataFrame, Series, Array or Scalar number to divide with. - * @param options.axis 0 or 1. If 0, compute the division column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return DataFrame raised to the power of other. - * @param other DataFrame, Series, Array or Scalar number to to raise to. - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return modulus between DataFrame and other. - * @param other DataFrame, Series, Array or Scalar number to modulus with. - * @param options.axis 0 or 1. If 0, compute the mod column-wise, if 1, row-wise - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other: DataFrame | Series | number[] | number, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Return mean of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mean column-wise, if 1, row-wise. Defaults to 1 - */ - mean(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return median of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the median column-wise, if 1, row-wise. Defaults to 1 - */ - median(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return mode of DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the mode column-wise, if 1, row-wise. Defaults to 1 - * @param options.keep If there are more than one modes, returns the mode at position [keep]. Defaults to 0 - */ - mode(options?: { - axis?: 0 | 1; - keep?: number; - }): Series; - /** - * Return minimum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the minimum value column-wise, if 1, row-wise. Defaults to 1 - */ - min(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return maximum of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the maximum column-wise, if 1, row-wise. Defaults to 1 - */ - max(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return standard deviation of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the standard deviation column-wise, if 1, row-wise. Defaults to 1 - */ - std(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return variance of values in a DataFrame across specified axis. - * @param options.axis 0 or 1. If 0, compute the variance column-wise, if 1, add row-wise. Defaults to 1 - */ - var(options?: { - axis?: 0 | 1; - }): Series; - /** - * Get Less than of dataframe and other, element-wise (binary operator lt). - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - lt(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "greater than" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - gt(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "equals to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - eq(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "not equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ne(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "less than or equal to" of dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - le(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Returns "greater than or equal to" between dataframe and other. - * @param other DataFrame, Series, Array or Scalar number to compare with - * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise - */ - ge(other: DataFrame | Series | number | Array, options?: { - axis?: 0 | 1; - }): DataFrame; - /** - * Return number of non-null elements in a Series - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - count(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return the sum of values across an axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - */ - sum(options?: { - axis?: 0 | 1; - }): Series; - /** - * Return the absolute value of elements in a DataFrame. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Rounds all element in the DataFrame to specified number of decimal places. - * @param dp Number of decimal places to round to. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp?: number, options?: { - inplace: boolean; - }): DataFrame | void; - /** - * Returns cumulative product accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumprod(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Returns cumulative sum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cumsum(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Returns cumulative minimum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummin(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Returns cumulative maximum accross specified axis. - * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - cummax(options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - - /** - * Generate descriptive statistics for all numeric columns - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - * @returns {Series} - */ - describe(): DataFrame; - /** - * Drops all rows or columns with missing values (NaN) - * @param axis 0 or 1. If 0, drop columns with NaNs, if 1, drop rows with NaNs - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(axis?: 0 | 1, options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Adds a new column to the DataFrame. If column exists, then the column values is replaced. - * @param column The name of the column to add or replace. - * @param values An array of values to be inserted into the DataFrame. Must be the same length as the columns - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - addColumn(options: { - column: string, - values: Series | ArrayType1D, - inplace?: boolean; - }): DataFrame | void; - /** - * Makes a new copy of a DataFrame - */ - copy(): DataFrame; - /** - * Return a boolean same-sized object indicating where elements are empty (NaN, undefined, null). - * NaN, undefined and null values gets mapped to true, and everything else gets mapped to false. - */ - isna(): DataFrame; - /** - * Replace all empty elements with a specified value. Replace params expect columns array to map to values array. - * @param columns The list of column names to be replaced - * @param options.values The list of values to use for replacement. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(values: number | string | boolean | ArrayType1D, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - - /** - * Sorts a Dataframe by a specified column values - * @param options.column Column name to sort by - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options?: { - by: string, - ascending?: boolean; - inplace?: boolean; - }): DataFrame | void; - /** - * Sets the index of the DataFrame to the specified index. - * @param options.index An array of index values to set - * @param options.column A column name to set the index to - * @param options.drop Whether to drop the column whose index was set. Defaults to false - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options: { - index?: Array; - column?: string; - drop?: boolean; - inplace?: boolean; - }): DataFrame | void; - /** - * Resets the index of the DataFrame to the default index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - reset_index(options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Apply a function along an axis of the DataFrame. To apply a function element-wise, use `applyMap`. - * Objects passed to the function are Series values whose - * index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1) - * @param callable Function to apply to each column or row - * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise - */ - apply(callable: any, options?: { - axis?: 0 | 1; - }): DataFrame | Series; - /** - * Apply a function to a Dataframe values element-wise. - * @param callable Function to apply to each column or row - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply_map(callable: any, options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Returns the specified column data as a Series object. - * @param column The name of the column to return - */ - column(column: string): Series; - /** - * Return a subset of the DataFrame’s columns based on the column dtypes. - * @param include An array of dtypes or strings to be included. - */ - select_dtypes(include: Array): DataFrame; - /** - * Returns the transposes the DataFrame. - **/ - transpose(options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Returns the Transpose of the DataFrame. Similar to `transpose`, but does not change the original DataFrame. - **/ - get T(): DataFrame; - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.columns An array of column names you want to replace. If not provided replace accross all columns. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace(oldValue: number | string | boolean, newValue: number | string | boolean, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - /** - * Cast the values of a column to specified data type - * @param column The name of the column to cast - * @param dtype Data type to cast to. One of [float32, int32, string, boolean] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(options?: { - column: string, - dtype: "float32" | "int32" | "string" | "boolean", - inplace?: boolean; - }): DataFrame | void; - /** - * Return the number of unique elements in a across the specified axis. - * To get the values use `.unique()` instead. - * @param axis The axis to count unique elements across. Defaults to 1 - */ - nunique(axis?: 0 | 1): Series; - /** - * Renames a column or index. - * @param mapper An object that maps each column or index in the DataFrame to a new value - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.axis The axis to perform the operation on. Defaults to 1 - */ - rename(options?: { - mapper: any, - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - /** - * Sorts the Dataframe by the index. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @param options.ascending Whether to sort values in ascending order or not. Defaults to true - */ - sort_index(options?: { - inplace?: boolean; - ascending?: boolean; - }): DataFrame | void; - /** - * Add new rows to the end of the DataFrame. - * @param newValues Array, Series or DataFrame to append to the DataFrame - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append(newValues: ArrayType1D | ArrayType2D | Series | DataFrame, index: Array | number | string, options?: { - inplace?: boolean; - }): DataFrame | void; - /** - * Queries the DataFrame for rows that meet the boolean criteria. - * @param condition An array of boolean mask, one for each row in the DataFrame. Rows where the value are true will be returned. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - **/ - query(options: { - column?: string, - is?: string, - to?: any, - condition?: Series | Array, - inplace?: boolean; - }): DataFrame | void; - /** - * Returns the data types for each column as a Series. - */ - get ctypes(): Series; - /** - * One-hot encode specified columns in the DataFrame. If columns are not specified, all columns of dtype string will be encoded. - * @param options Options for the operation. The following options are available: - * - `columns`: A single column name or an array of column names to encode. Defaults to all columns of dtype string. - * - `prefix`: Prefix to add to the column names. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * - `inplace`: Boolean indicating whether to perform the operation inplace or not. Defaults to false - * @returns A DataFrame with the one-hot encoded columns. - * @example - * df.getDummies({ columns: ['a', 'b'] }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-' }) - * df.getDummies({ columns: ['a', 'b'], prefix: 'cat', prefixSeparator: '-', inplace: true }) - * df.getDummies({ columns: ['a', 'b'], prefix: ['col1', 'col2'], prefixSeparator: '-', inplace: true }) - */ - get_dummies(options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string | Array; - inplace?: boolean; - }): DataFrame | void; - - groupby(column: Array): GroupBy; -} \ No newline at end of file diff --git a/danfojs-node/types/core/generic.d.ts b/danfojs-node/types/core/generic.d.ts deleted file mode 100644 index 55edefda..00000000 --- a/danfojs-node/types/core/generic.d.ts +++ /dev/null @@ -1,181 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Configs from "../shared/config"; -import { NDframeInterface, NdframeInputDataType, AxisType, ArrayType1D, ArrayType2D, CsvOutputOptionsNode } from '../shared/types'; -/** - * N-Dimension data structure. Stores multi-dimensional - * data in a size-mutable, labeled data structure. Analogous to the Python Pandas DataFrame. - * - * @param Object - * - * data: 1D or 2D Array, JSON, Tensor, Block of data. - * - * index: Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * - * columns: Array of column names. If not specified, column names are auto generated. - * - * dtypes: Array of data types for each the column. If not specified, dtypes inferred. - * - * config: General configuration object for NDframe - * - * @returns NDframe - */ -export default class NDframe implements NDframeInterface { - $isSeries: boolean; - protected $data: any; - protected $dataIncolumnFormat: ArrayType1D | ArrayType2D; - protected $index: Array; - protected $columns: string[]; - protected $dtypes: Array; - protected $config: Configs; - constructor({ data, index, columns, dtypes, config, isSeries }: NdframeInputDataType); - /** - * Internal function to load array of data into NDFrame - * @param data The array of data to load into NDFrame - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - private loadArrayIntoNdframe; - /** - * Internal function to format and load a Javascript object or object of arrays into NDFrame. - * @param data Object or object of arrays. - * @param type The type of the object. There are two recognized types: - * - * - type 1 object are in JSON format `[{a: 1, b: 2}, {a: 30, b: 20}]`. - * - * - type 2 object are of the form `{a: [1,2,3,4], b: [30,20, 30, 20}]}` - * @param index Array of numeric or string names for subsetting array. - * @param columns Array of column names. - * @param dtypes Array of data types for each the column. - */ - private loadObjectIntoNdframe; - /** - * Converts and returns the data in the NDframe as a Tensorflow.js Tensor. - */ - get tensor(): import("@tensorflow/tfjs-node").Tensor1D | import("@tensorflow/tfjs-node").Tensor2D; - /** - * Returns the dtypes of the columns - */ - get dtypes(): Array; - /** - * Internal function to set the Dtypes of the NDFrame from an array. This function - * performs the necessary checks. - */ - $setDtypes(dtypes: Array | undefined): void; - /** - * Returns the dimension of the data. Series have a dimension of 1, - * while DataFrames have a dimension of 2. - */ - get ndim(): number; - /** - * Returns the axis labels of the NDFrame. - */ - get axis(): AxisType; - /** - * Returns the configuration object of the NDFrame. - */ - get config(): Configs; - /** - * Internal function to set the configuration of the ndframe - */ - $setConfig(config: Configs): void; - /** - * Returns the indices of the NDFrame - */ - get index(): Array; - /** - * Internal function to set the index of the NDFrame with the specified - * array of indices. Performs all necessary checks to ensure that the - * index is valid. - */ - $setIndex(index: Array | undefined): void; - /** - * Internal function to reset the index of the NDFrame using a range of indices. - */ - $resetIndex(): void; - /** - * Returns the column names of the NDFrame - */ - get columns(): string[]; - /** - * Internal function to set the column names for the NDFrame. This function - * performs a check to ensure that the column names are unique, and same length as the - * number of columns in the data. - */ - $setColumnNames(columns?: string[]): void; - /** - * Returns the shape of the NDFrame. Shape is determined by [row lenght, column length] - */ - get shape(): Array; - /** - * Returns the underlying data in Array format. - */ - get values(): ArrayType1D | ArrayType2D; - /** - * Updates the internal $data property to the specified value - * @param values An array of values to set - * @param checkLength Whether to check the length of the new values and the existing row length - * @param checkColumnLength Whether to check the length of the new values and the existing column length - * */ - $setValues(values: ArrayType1D | ArrayType2D, checkLength?: boolean, checkColumnLength?: boolean): void; - /** - * Returns the size of the NDFrame object - * - */ - get size(): number; - /** - * Converts a DataFrame or Series to CSV. - * @param options Configuration object. Supports the following options: - * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - */ - to_csv(options?: CsvOutputOptionsNode): string | void; - /** - * Converts a DataFrame or Series to JSON. - * @param options Configuration object. Supported options: - * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - */ - to_json(options?: { - format?: "row" | "column"; - filePath?: string; - }): object | void; - /** - * Converts a DataFrame or Series to Excel Sheet. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. - */ - to_excel(options?: { - filePath?: string; - sheetName?: string; - }): void; - /** - * Pretty prints a DataFrame or Series to the console - */ - print(): void; -} diff --git a/danfojs-node/types/core/get_dummies.d.ts b/danfojs-node/types/core/get_dummies.d.ts deleted file mode 100644 index b4daef13..00000000 --- a/danfojs-node/types/core/get_dummies.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { DataFrame } from "./frame"; -import Series from "./series"; -/** - * Generate one-hot encoding for categorical columns in an Array, Series or Dataframe. - * @param data Series or Dataframe - * @param columns Columns to encode - * @param prefix Prefix for the new columns - * @param prefixSeparator Separator for the prefix and the column name - * @returns Encoded Dataframe - * @example - * import { DataFrame, DummyEncoder }from 'danfojs'; - * const df = new DataFrame([[1,2,3], [4,5,6]], { columns: ['a', 'b', 'c'] }); - * const df2 = new DummyEncoder({data: df, columns: ['a', 'b'], prefix: 'enc', prefixSeparator: '#'}).encode(); - * df2.print(); - */ -declare function dummyEncode(data: Series | DataFrame, options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string | Array; -}): DataFrame; -export default dummyEncode; diff --git a/danfojs-node/types/core/groupby.d.ts b/danfojs-node/types/core/groupby.d.ts deleted file mode 100644 index c8231934..00000000 --- a/danfojs-node/types/core/groupby.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The class performs all groupby operation on a dataframe - * involveing all aggregate funciton - * @param {col_dict} col_dict Object of unique keys in the group by column - * @param {key_col} key_col Array contains the column names - * @param {data} Array the dataframe data - * @param {column_name} Array of all column name in the dataframe. - */ -export class GroupBy { - constructor(col_dict?: any, key_col?: any, data?: any, column_name?: any); - key_col?: any; - col_dict?: any; - data?: any; - column_name?: any; - data_tensors: {}; - /** - * Group the dataframe by the column by - * creating an object to store the grouping - * @returns Groupby data structure - */ - group(): GroupBy; - /** - * obtain the column for each group - * @param {col_name} col_name [Array]--> array of column names - * @return Groupby data structure - */ - col(col_names?: any): GroupBy; - group_col_name?: any[]; - group_col: {}; - /** - * Basic root of all column arithemetic in groups - * @param {operation} operatioin String - */ - arithemetic(operation?: any): {}; - count(): DataFrame; - sum(): DataFrame; - std(): DataFrame; - var(): DataFrame; - mean(): DataFrame; - cumsum(): DataFrame; - cummax(): DataFrame; - cumprod(): DataFrame; - cummin(): DataFrame; - max(): DataFrame; - min(): DataFrame; - /** - * returns dataframe of a group - * @param {*} key [Array] - */ - get_groups(key?: any): any; - /** - * Map every column to an operaton - * @param {kwargs} kwargs {column name: math operation} - * @example .agg({"A": "mean","B": "sum","C":"count"}) - */ - agg(kwargs?: any): DataFrame; - to_DataFrame(key_col?: any, col?: any, data?: any, ops?: any): DataFrame; -} -import { DataFrame } from "./frame"; diff --git a/danfojs-node/types/core/indexing.d.ts b/danfojs-node/types/core/indexing.d.ts deleted file mode 100644 index c89625e7..00000000 --- a/danfojs-node/types/core/indexing.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -import { DataFrame } from "./frame"; -import { NDframeInterface } from "../shared/types"; -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export declare function _iloc({ ndFrame, rows, columns }: { - ndFrame: NDframeInterface; - rows?: Array | Series; - columns?: Array; -}): Series | DataFrame; -/** -* Slice a Series/DataFrame by specified string location based labels -* @param Object -*/ -export declare function _loc({ ndFrame, rows, columns }: { - ndFrame: NDframeInterface; - rows?: Array | Series; - columns?: Array; -}): Series | DataFrame | void; diff --git a/danfojs-node/types/core/math.ops.d.ts b/danfojs-node/types/core/math.ops.d.ts deleted file mode 100644 index dff9a543..00000000 --- a/danfojs-node/types/core/math.ops.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import Series from "./series"; -/** - * Generic function for performing add, sub, pow, mul and mod operation on a series - * @param object - * - * ndframe ==> The current Series - * - * other ==> The Series or number to perform math operation with - * - * operation ==> The type of operation to perform -*/ -export declare function _genericMathOp({ ndFrame, other, operation }: { - ndFrame: Series; - other: Series | number | Array; - operation: string; -}): number[] | undefined; diff --git a/danfojs-node/types/core/merge.d.ts b/danfojs-node/types/core/merge.d.ts deleted file mode 100644 index 8162a6c9..00000000 --- a/danfojs-node/types/core/merge.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -export class Merge { - constructor(kwargs?: any); - how?: any; - left: DataFrame; - right: DataFrame; - on?: any[]; - left_col_index?: any[]; - right_col_index?: any[]; - left_key_dict: {}; - right_key_dict: {}; - __create_columns(): void; - outer(): any[]; - inner(): any[]; - left_merge(): any[]; - right_merge(): any[]; - basic(keys?: any): any[]; -} -export function merge(kwargs?: any): DataFrame; -import { DataFrame } from "./frame"; diff --git a/danfojs-node/types/core/series.d.ts b/danfojs-node/types/core/series.d.ts deleted file mode 100644 index 440360df..00000000 --- a/danfojs-node/types/core/series.d.ts +++ /dev/null @@ -1,462 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { ArrayType1D, BaseDataOptionType, SeriesInterface } from "../shared/types"; -import NDframe from "./generic"; -import Str from './strings'; -import Dt from './datetime'; -import { DataFrame } from "./frame"; -/** - * One-dimensional ndarray with axis labels. - * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. - * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. - * @param data 2D Array, JSON, Tensor, Block of data. - * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. - * @param options.columns Array of column names. If not specified, column names are auto generated. - * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. - * @param options.config General configuration object for extending or setting NDframe behavior. - */ -export default class Series extends NDframe implements SeriesInterface { - constructor(data?: any, options?: BaseDataOptionType); - /** - * Purely integer-location based indexing for selection by position. - * ``.iloc`` is primarily integer position based (from ``0`` to - * ``length-1`` of the axis), but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are in rows and columns params are: - * - * - An array of single integer, e.g. ``[5]``. - * - A list or array of integers, e.g. ``[4, 3, 0]``. - * - A slice array string with ints, e.g. ``["1:7"]``. - * - A boolean array. - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above). - * This is useful in method chains, when you don't have a reference to the - * calling object, but would like to base your selection on some value. - * - * ``.iloc`` will raise ``IndexError`` if a requested indexer is - * out-of-bounds. - */ - iloc(rows: Array): Series; - /** - * Access a group of rows by label(s) or a boolean array. - * ``loc`` is primarily label based, but may also be used with a boolean array. - * - * @param rows Array of row indexes - * - * Allowed inputs are: - * - * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a - * *label* of the index, and **never** as an integer position along the index). - * - * - A list or array of labels, e.g. ``['a', 'b', 'c']``. - * - * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included - * - * - A boolean array of the same length as the axis being sliced, - * e.g. ``[True, False, True]``. - * - * - A ``callable`` function with one argument (the calling Series or - * DataFrame) and that returns valid output for indexing (one of the above) - */ - loc(rows: Array): Series; - /** - * Returns the first n values in a Series - * @param rows The number of rows to return - */ - head(rows?: number): Series; - /** - * Returns the last n values in a Series - * @param rows The number of rows to return - */ - tail(rows?: number): Series; - /** - * Returns specified number of random rows in a Series - * @param num The number of rows to return - * @param options.seed An integer specifying the random seed that will be used to create the distribution. - */ - sample(num?: number, options?: { - seed?: number; - }): Promise; - /** - * Return Addition of series and other, element-wise (binary operator add). - * Equivalent to series + other - * @param other Series, Array of same length or scalar number to add - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - add(other: Series | Array | number, options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns the subtraction between a series and other, element-wise (binary operator subtraction). - * Equivalent to series - other - * @param other Number to subtract - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sub(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return Multiplication of series and other, element-wise (binary operator mul). - * Equivalent to series * other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mul(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return division of series and other, element-wise (binary operator div). - * Equivalent to series / other - * @param other Series or number to divide with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - div(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return Exponential power of series and other, element-wise (binary operator pow). - * Equivalent to series ** other - * @param other Number to multiply with. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - pow(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return Modulo of series and other, element-wise (binary operator mod). - * Equivalent to series % other - * @param other Number to modulo with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - mod(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - /** - * Checks if the array value passed has a compatible dtype, removes NaN values, and if - * boolean values are present, converts them to integer values. - * */ - private $checkAndCleanValues; - /** - * Returns the mean of elements in Series - */ - mean(): number; - /** - * Returns the median of elements in Series - */ - median(): number; - /** - * Returns the modal value of elements in Series - */ - mode(): any; - /** - * Returns the minimum value in a Series - */ - min(): number; - /** - * Returns the maximum value in a Series - * @returns {Number} - */ - max(): number; - /** - * Return the sum of the values in a series. - */ - sum(): number; - /** - * Return number of non-null elements in a Series - */ - count(): number; - /** - * Return maximum of series and other. - * @param other Series or number to check against - */ - maximum(other: Series | number | Array): Series; - /** - * Return minimum of series and other. - * @param other Series, Numbers to check against - */ - minimum(other: Series | number | Array): Series; - /** - * Round each value in a Series to the specified number of decimals. - * @param dp Number of Decimal places to round to - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - round(dp?: number, options?: { - inplace?: boolean; - }): Series | void; - /** - * Return sample standard deviation of elements in Series - */ - std(): number; - /** - * Return unbiased variance of elements in a Series. - */ - var(): number; - /** - * Return a boolean same-sized object indicating where elements are NaN. - * NaN and undefined values gets mapped to true, and everything else gets mapped to false. - */ - isna(): Series; - /** - * Replace all NaN with a specified value - * @param value The value to replace NaN with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - fillna(options?: { - value: number | string | boolean, - inplace?: boolean; - }): Series | void; - /** - * Sort a Series in ascending or descending order by some criterion. - * @param options Method options - * @param ascending Whether to return sorted values in ascending order or not. Defaults to true - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - sort_values(options?: { - ascending?: boolean, - inplace?: boolean; - }): Series | void; - /** - * Makes a deep copy of a Series - */ - copy(): Series; - /** - * Generate descriptive statistics. - * Descriptive statistics include those that summarize the central tendency, - * dispersion and shape of a dataset’s distribution, excluding NaN values. - */ - describe(): Series; - /** - * Returns Series with the index reset. - * This is useful when index is meaningless and needs to be reset to the default before another operation. - */ - reset_index(options?: { - inplace?: boolean; - }): Series | void; - /** - * Set the Series index (row labels) using an array of the same length. - * @param index Array of new index values, - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - set_index(options?: { - index: Array, - inplace?: boolean; - }): Series | void; - /** - * map all the element in a column to a variable or function - * @param callable callable can either be a funtion or an object - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - map(callable: any, options?: { - inplace?: boolean; - }): Series | void; - /** - * Applies a function to each element of a Series - * @param callable Function to apply to each element of the series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - apply(callable: any, options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns a Series with only the unique value(s) in the original Series - */ - unique(): Series; - /** - * Return the number of unique elements in a Series - */ - nunique(): number; - /** - * Returns unique values and their counts in a Series - */ - value_counts(): Series; - /** - * Returns the absolute values in Series - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - abs(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns the cumulative sum over a Series - */ - cumsum(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns cumulative minimum over a Series - */ - cummin(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns cumulative maximum over a Series - */ - cummax(options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns cumulative product over a Series - */ - cumprod(options?: { - inplace?: boolean; - }): Series | void; - /** - * perform cumulative operation on series data - */ - private cumOps; - /** - * Returns less than of series and other. Supports element wise operations - * @param other Series or number to compare against - */ - lt(other: Series | number): Series; - /** - * Returns Greater than of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - gt(other: Series | number | Array): Series; - /** - * Returns Less than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - le(other: Series | number | Array): Series; - /** - * Returns Greater than or Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ge(other: Series | number | Array): Series; - /** - * Returns Not Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - ne(other: Series | number | Array): Series; - /** - * Returns Equal to of series and other. Supports element wise operations - * @param {other} Series, Scalar - * @return {Series} - */ - eq(other: Series | number | Array): Series; - /** - * Perform boolean operations on bool values - * @param other Other Series or number to compare with - * @param bOps Name of operation to perform [ne, ge, le, gt, lt, eq] - */ - private boolOps; - /** - * Replace all occurence of a value with a new value - * @param oldValue The value you want to replace - * @param newValue The new value you want to replace the old value with - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - replace(options?: { - oldValue: string | number | boolean, - newValue: string | number | boolean, - inplace?: boolean; - }): Series | void; - /** - * Drops all missing values (NaN) from a Series. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - dropna(options?: { - inplace?: boolean; - }): Series | undefined; - /** - * Return the integer indices that would sort the Series. - * @param ascending boolean true: will sort the Series in ascending order, false: will sort in descending order - */ - argsort(ascending?: boolean): Series; - /** - * Return int position of the largest value in the Series. - */ - argmax(): number; - /** - * Return int position of the smallest value in the Series. - */ - argmin(): number; - /** - * Remove duplicate values from a Series - * @param keep "first" | "last", which dupliate value to keep. Defaults to "first". - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - drop_duplicates(options?: { - keep?: "first" | "last"; - inplace?: boolean; - }): Series | void; - /** - * Cast Series to specified data type - * @param dtype Data type to cast to. One of [float32, int32, string, boolean, undefined] - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - astype(dtype: "float32" | "int32" | "string" | "boolean" | "undefined", options?: { - inplace?: boolean; - }): Series | void; - /** - * Add a new value or values to the end of a Series - * @param newValues Single value | Array | Series to append to the Series - * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` - * as they map `1 - 1`. - * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false - */ - append(newValue: string | number | boolean | Series | ArrayType1D, index: Array | number | string, options?: { - inplace?: boolean; - }): Series | void; - /** - * Returns dtype of Series - */ - get dtype(): string; - /** - * Exposes numerous string methods to manipulate Series of type string - */ - get str(): Str; - /** - * Returns time class that exposes different date time method - */ - get dt(): Dt; - /** - * Prints Series to console as a grid of row and columns. - */ - toString(): string; - /** - * Returns the logical AND between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - and(other: any): Series; - /** - * Returns the logical OR between Series and other. Supports element wise operations and broadcasting. - * @param other Series, Scalar, Array of Scalars - */ - or(other: any): Series; - /** - * One-hot encode values in the Series. - * @param options Options for the operation. The following options are available: - * - `prefix`: Prefix to add to the new column. Defaults to unique labels. - * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. - * @returns A DataFrame with the one-hot encoded columns. - * @example - * sf.get_dummies() - * sf.get_dummies({prefix: 'cat' }) - * sf.get_dummies({ prefix: 'cat', prefixSeparator: '-' }) - */ - get_dummies(options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string; - }): DataFrame; -} diff --git a/danfojs-node/types/core/strings.d.ts b/danfojs-node/types/core/strings.d.ts deleted file mode 100644 index 24b31577..00000000 --- a/danfojs-node/types/core/strings.d.ts +++ /dev/null @@ -1,341 +0,0 @@ -import Series from "./series"; -/** - * Exposes numerous String methods. All methods are applied Element-wise - */ -export default class Str { - private series; - private values; - constructor(series: Series); - /** - * Converts all characters to lowercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toLowerCase() - * console.log(newSf.values) - * // ["good", "bad", "crazy"] - * ``` - */ - toLowerCase(options?: { - inplace: boolean; - }): Series | void; - /** - * Converts all characters to uppercase. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["GooD", "Bad", "CrAzy"]) - * const newSf = sf.str.toUpperCase() - * console.log(newSf.values) - * // ["GOOD", "BAD", "CRAZY"] - * ``` - */ - toUpperCase(options?: { - inplace: boolean; - }): Series | void; - /** - * Capitalize first string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.capitalize() - * console.log(newSf.values) - * // ["Good", "Bad", "Crazy"] - * ``` - */ - capitalize(options?: { - inplace: boolean; - }): Series | void; - /** - * Returns the character at the specified index (position) - * @param index position of character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.charAt(1) - * console.log(newSf.values) - * // ["o", "a", "r"] - * ``` - */ - charAt(index?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Joins specified `other` with values in the Series. - * @param other string|values to concatenate with. - * @param position where to concat the string from. O concats from the start, 1 concats from the end. Defaults to 1. - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.concat("_new") - * console.log(newSf.values) - * // ["Good_new", "bad_new", "crazy_new" - * ``` - */ - concat(other: Array | string, position?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Checks whether a string begins with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.startsWith("G") - * console.log(newSf.values) - * // [true, false, false] - * ``` - */ - startsWith(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Checks whether a string ends with specified characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.endsWith("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - endsWith(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Checks whether a string contains the specified string/characters - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.includes("d") - * console.log(newSf.values) - * // [true, true, false] - * ``` - */ - includes(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Returns the position of the first occurrence of a specified value in a string. - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "bad", "crazy"]) - * const newSf = sf.str.indexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - indexOf(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Returns the position of the last found occurrence of a specified value in a string - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.lastIndexOf("d") - * console.log(newSf.values) - * // [3, 2, -1] - * ``` - */ - lastIndexOf(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced - * @param searchValue String | Character value to replace - * @param replaceValue String | Character string to replace with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace("d", 7) - * console.log(newSf.values) - * // ["Goo7", "o77", "crazy"] - * ``` - */ - replace(searchValue?: string, replaceValue?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Returns a new string with a specified number of copies of an existing string - * @param num Number of times to repeat - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.replace(2) - * console.log(newSf.values) - * // ["GoodGood", "oddodd", "crazycrazy"] - * ``` - */ - repeat(num?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Searches a string for a specified value, or regular expression, and returns the position of the match - * @param str String or Character to check against - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.search("d") - * console.log(newSf.values) - * ``` - */ - search(str?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Extracts a part of a string and returns a new string - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "crazy"]) - * const newSf = sf.str.slice(0,1) - * console.log(newSf.values) - * // ["G", "o", "c"] - * ``` - */ - slice(startIndex?: number, endIndex?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Splits a string into an values of substrings - * @param splitVal string or character to split at - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.split(d) - * console.log(newSf.values) - * ``` - */ - split(splitVal?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Extracts the characters from a string, beginning at a specified start position, and through the specified number of character - * @param startIndex index position of start character - * @param num number of characters to return - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substr(d) - * ``` - */ - substr(startIndex?: number, num?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Extracts the characters from a string, between two specified indices - * @param startIndex index position of start character - * @param endIndex index position of last character - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.substring(d) - * ``` - */ - substring(startIndex?: number, endIndex?: number, options?: { - inplace: boolean; - }): Series | void; - /** - * Removes whitespace from both ends of a string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series([" Good", "odd ", " grade "]) - * const newSf = sf.str.trim(d) - * ["Good", "odd", "grade"] - * ``` - */ - trim(options?: { - inplace: boolean; - }): Series | void; - /** - * Joins strings to specified value - * @param valToJoin string value to join to the values - * @param joinChar Character to Join with - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.join("new", "_") - * // ["Good_new", "odd_new", "grade_new"] - * ``` - */ - join(valToJoin?: string, joinChar?: string, options?: { - inplace: boolean; - }): Series | void; - /** - * Counts the number of characters in string - * @param options The following optional parameters are supported: - * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` - * @example - * ``` - * import { Series } from "danfojs-node" - * const sf = new Series(["Good", "odd", "grade"]) - * const newSf = sf.str.len(d) - * // [4,3,5] - * ``` - */ - len(options?: { - inplace: boolean; - }): Series | void; -} diff --git a/danfojs-node/types/index.d.ts b/danfojs-node/types/index.d.ts deleted file mode 100644 index c254dda1..00000000 --- a/danfojs-node/types/index.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import NDframe from "./core/generic"; -import Utils from './shared/utils'; -import Series from "./core/series"; -import { DataFrame } from "./core/frame"; -import { concat } from "./core/concat"; -import { merge } from "./core/merge"; -import { LabelEncoder, OneHotEncoder } from "./preprocessing/encodings"; -import { MinMaxScaler, StandardScaler } from "./preprocessing/scalers"; -import { date_range } from "./core/date_range"; -import get_dummies from "./core/get_dummies"; -import Str from "./core/strings"; -import Dt, { toDateTime } from "./core/datetime"; -import { - readCSV as read_csv, - toCSV as to_csv, - readJSON as read_json, - toJSON as to_json, - readExcel as read_excel, - toExcel as to_excel -} from "./io"; - - -export { - date_range, - toDateTime, - concat, - merge, - NDframe, - Utils, - Str, - Dt, - Series, - DataFrame, - read_csv, - to_csv, - read_json, - to_json, - read_excel, - to_excel, - MinMaxScaler, - StandardScaler, - LabelEncoder, - OneHotEncoder, - get_dummies -}; diff --git a/danfojs-node/types/io/index.d.ts b/danfojs-node/types/io/index.d.ts deleted file mode 100644 index 01ec06a6..00000000 --- a/danfojs-node/types/io/index.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { $readCSV, $streamCSV, $toCSV} from "./io.csv"; -import { $readJSON, $toJSON } from "./io.json"; -import { $readExcel, $toExcel } from "./io.excel"; - -export { - $readCSV as readCSV, - $streamCSV as streamCSV, - $toCSV as toCSV, - $readJSON as readJSON, - $toJSON as toJSON, - $readExcel as readExcel, - $toExcel as toExcel - }; - \ No newline at end of file diff --git a/danfojs-node/types/io/io.csv.d.ts b/danfojs-node/types/io/io.csv.d.ts deleted file mode 100644 index c0f858f2..00000000 --- a/danfojs-node/types/io/io.csv.d.ts +++ /dev/null @@ -1,75 +0,0 @@ -/// -import { DataFrame, NDframe, Series } from '../index'; -import { CsvInputOptions, CsvOutputOptionsNode } from "../shared/types"; -/** - * Reads a CSV file from local or remote location into a DataFrame. - * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, - * hence all PapaParse options are supported. - * @param options Configuration object. Supports all Papaparse parse config options. - * @returns DataFrame containing the parsed CSV file. - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv") - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("https://raw.githubusercontent.com/test.csv", { - * delimiter: ",", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readCSV } from "danfojs-node" - * const df = await readCSV("./data/sample.csv") - * ``` - */ -declare const $readCSV: (filePath: string, options: CsvInputOptions) => Promise; -/** - * Streams a CSV file from local or remote location in chunks. Intermediate chunks is passed as a DataFrame to the callback function. - * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, - * hence all PapaParse options are supported. - * @param options Configuration object. Supports all Papaparse parse config options. - * @param callback Callback function to be called once the specifed rows are parsed into DataFrame. - * @example - * ``` - * import { streamCSV } from "danfojs-node" - * streamCSV("https://raw.githubusercontent.com/test.csv", (dfRow) => { - * const dfModified = dfRow["Names"].map((name) => name.split(",")[0]) - * return dfModified - * }) - * ``` - */ -declare const $streamCSV: (filePath: string, callback: (df: DataFrame) => void, options?: CsvInputOptions | undefined) => Promise; -/** - * Converts a DataFrame or Series to CSV. - * @param df DataFrame or Series to be converted to CSV. - * @param options Configuration object. Supports the following options: - * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. - * - `header`: Boolean indicating whether to include a header row in the CSV file. - * - `sep`: Character to be used as a separator in the CSV file. - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const csv = toCSV(df) - * ``` - * @example - * ``` - * import { toCSV } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toCSV(df, { - * filePath: "./data/sample.csv", - * header: true, - * sep: "+" - * }) - * ``` - */ -declare const $toCSV: (df: NDframe | DataFrame | Series, options?: CsvOutputOptionsNode | undefined) => string | void; - -export { $readCSV, $streamCSV, $toCSV }; diff --git a/danfojs-node/types/io/io.excel.d.ts b/danfojs-node/types/io/io.excel.d.ts deleted file mode 100644 index b91d6c90..00000000 --- a/danfojs-node/types/io/io.excel.d.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { HeadersInit } from "node-fetch"; -import { DataFrame, NDframe, Series } from '../index'; -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param filePath URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx") - * ``` - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx", { - * method: "GET", - * headers: { - * Accept: "text/csv", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readExcel } from "danfojs-node" - * const df = await readExcel("./data/sample.xlsx") - * ``` - */ -declare const $readExcel: (filePath: string, options?: { - sheet?: number | undefined; - method?: string | undefined; - headers?: HeadersInit | undefined; -}) => Promise; -/** - * Converts a DataFrame or Series to Excel Sheet. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. - * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. - * @example - * ``` - * import { toExcel } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toExcel(df, { - * filePath: "./data/sample.xlsx", - * sheetName: "MySheet", - * }) - * ``` - */ -declare const $toExcel: (df: NDframe | DataFrame | Series, options?: { - filePath?: string | undefined; - sheetName?: string | undefined; -} | undefined) => void; -export { $readExcel, $toExcel }; diff --git a/danfojs-node/types/io/io.json.d.ts b/danfojs-node/types/io/io.json.d.ts deleted file mode 100644 index 2b31d411..00000000 --- a/danfojs-node/types/io/io.json.d.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { HeadersInit } from "node-fetch"; -import { DataFrame, NDframe, Series } from '../index'; -/** - * Reads a JSON file from local or remote location into a DataFrame. - * @param filePath URL or local file path to JSON file. - * @param options Configuration object. Supported options: - * - `method`: The HTTP method to use. Defaults to `'GET'`. - * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json") - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("https://raw.githubusercontent.com/test.json", { - * headers: { - * Accept: "text/json", - * Authorization: "Bearer YWRtaW46YWRtaW4=" - * } - * }) - * ``` - * @example - * ``` - * import { readJSON } from "danfojs-node" - * const df = await readJSON("./data/sample.json") - * ``` - */ -declare const $readJSON: (filePath: string, options?: { - method?: string | undefined; - headers?: HeadersInit | undefined; -}) => Promise; - -/** - * Converts a DataFrame or Series to JSON. - * @param df DataFrame or Series to be converted to JSON. - * @param options Configuration object. Supported options: - * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. - * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: - * ``` - * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, - * { "a": 5, "b": 6, "c": 7, "d": 8 }] - * ``` - * and `row` format: - * ``` - * { "a": [1, 5, 9], - * "b": [2, 6, 10] - * } - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * const json = toJSON(df) - * ``` - * @example - * ``` - * import { toJSON } from "danfojs-node" - * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) - * toJSON(df, { - * filePath: "./data/sample.json", - * format: "row" - * }) - * ``` - */ -declare const $toJSON: (df: NDframe | DataFrame | Series, options?: { - format?: "row" | "column" | undefined; - filePath?: string | undefined; -} | undefined) => object | void; -export { $readJSON, $toJSON }; diff --git a/danfojs-node/types/plotting/plot.d.ts b/danfojs-node/types/plotting/plot.d.ts deleted file mode 100644 index a59b0a74..00000000 --- a/danfojs-node/types/plotting/plot.d.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Plotting methods and Functions performed on Series and DataFrames - */ - export class Plot { - constructor(ndframe?: any, div?: any); - div?: any; - ndframe?: any; - /** - * Plot Series or DataFrame as lines. This function is useful to plot lines using DataFrame’s values as coordinates. - * Make plots of Series or DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - line(config?: any): void; - /** - * Plot Series or DataFrame as Bars. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - bar(config?: any): void; - /** - * Plot two or more columns in a DataFrame as scatter points. If Series, plot against its index - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - scatter(config?: any): void; - /** - * Plot columns in a Series/DataFrame as Histograms. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - hist(config?: any): void; - /** - * Makes Pie Plots from two Columns in a DataFrame. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {string} div Name of the div to show the plot - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - pie(config?: any): void; - /** - * Plot Box plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - box(config?: any): void; - /** - * Plot Violin plots from Series or DataFrame as lines. - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - violin(config?: any): void; - /** - * Display DataFrame in a div using D3.js format - * Uses the Plotly as backend, so supoorts Plotly's configuration parameters - * @param {Object} config configuration options for making Plots, supports Plotly parameters - */ - table(config?: any): void; - __get_plot_params(config?: any): (string[] | { - layout: {}; - })[]; - ____check_if_cols_exist(cols?: any): any; -} diff --git a/danfojs-node/types/preprocessing/encodings.d.ts b/danfojs-node/types/preprocessing/encodings.d.ts deleted file mode 100644 index 77cb5771..00000000 --- a/danfojs-node/types/preprocessing/encodings.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import Series from "../core/series"; -import { DataFrame } from "../core/frame"; - -export class LabelEncoder { - /** - * - * @param {data} data [Array|Series] - * @returns Array. - */ - fit(data?: any): Series; - label?: any; - /** - * Transform data using the label generated from fitting - * @param {data} data [Array|Series] - * @returns Array - */ - transform(data?: any): Series; -} -export class OneHotEncoder { - fit(data?: any): DataFrame; - label?: any; - transform(data?: any): DataFrame; -} diff --git a/danfojs-node/types/preprocessing/scalers.d.ts b/danfojs-node/types/preprocessing/scalers.d.ts deleted file mode 100644 index 73e97a7f..00000000 --- a/danfojs-node/types/preprocessing/scalers.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -import Series from "../core/series"; -import { DataFrame } from "../core/frame"; -export class MinMaxScaler { - /** - * Fit minmax scaler on data, to obtain their min and max value - * @param {data} data [DataRame | Series | Array] - * @returns Array - */ - fit(data?: any): Series | DataFrame; - max?: any; - min?: any; - /** - * Transform an array using the min and max generated from the fitting on data - * @param {data} data [Array] - * @returns array - */ - transform(data?: any): Series | DataFrame; - - /** - * Restore a transformed array to their original values, - * using the min and max generated from the fitting on data - * @param {Series|Array|DataFrame} data - * @returns Series|DataFrame - */ - inverse_transform(data?: any): Series | DataFrame; -} -export class StandardScaler { - /** - * - * @param {data} data [DataRame | Series | Array] - * @returns Array - */ - fit(data?: any): Series | DataFrame; - std?: any; - mean?: any; - transform(data?: any): Series | DataFrame; - inverse_transform(data?: any): Series | DataFrame; -} - diff --git a/danfojs-node/types/shared/config.d.ts b/danfojs-node/types/shared/config.d.ts deleted file mode 100644 index 3aac789b..00000000 --- a/danfojs-node/types/shared/config.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { BaseUserConfig, TableUserConfig } from 'table'; -import { ConfigsType } from './types'; -/** - * Package wide configuration class - */ -export default class Configs { - tableDisplayConfig: BaseUserConfig & TableUserConfig; - tableMaxRow: number; - tableMaxColInConsole: number; - dtypeTestLim: number; - lowMemoryMode: boolean; - constructor(options: ConfigsType); - setTableDisplayConfig(config: BaseUserConfig & TableUserConfig): void; - get getTableDisplayConfig(): BaseUserConfig & TableUserConfig; - setTableMaxColInConsole(val: number): void; - get getTableMaxColInConsole(): number; - setMaxRow(val: number): void; - get getMaxRow(): number; - get getDtypeTestLim(): number; - setDtypeTestLim(val: number): void; - get isLowMemoryMode(): boolean; - setIsLowMemoryMode(val: boolean): void; -} diff --git a/danfojs-node/types/shared/errors.d.ts b/danfojs-node/types/shared/errors.d.ts deleted file mode 100644 index d7bd325c..00000000 --- a/danfojs-node/types/shared/errors.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { DataFrame } from "../core/frame"; -import NDframe from "../core/generic"; -/** - * Package wide error throwing class - */ -declare class ErrorThrower { - throwColumnNamesLengthError: (ndframe: NDframe, columns: Array) => void; - throwIndexLengthError: (ndframe: NDframe, index: Array) => void; - throwIndexDuplicateError: () => void; - throwColumnDuplicateError: () => void; - throwDtypesLengthError: (ndframe: NDframe, dtypes: Array) => void; - throwDtypeNotSupportedError: (dtype: string) => void; - throwColumnLengthError: (ndframe: NDframe | DataFrame, arrLen: number) => void; - throwRowLengthError: (ndframe: NDframe, arrLen: number) => void; - throwColumnNotFoundError: (ndframe: DataFrame | NDframe) => void; - throwNotImplementedError: () => void; - throwIlocRowIndexError: () => void; - throwIlocColumnsIndexError: () => void; - throwStringDtypeOperationError: (operation: string) => void; - throwSeriesMathOpLengthError: (ndframe: NDframe, other: NDframe) => void; -} -declare const _default: ErrorThrower; -export default _default; diff --git a/danfojs-node/types/shared/types.d.ts b/danfojs-node/types/shared/types.d.ts deleted file mode 100644 index d45d37ee..00000000 --- a/danfojs-node/types/shared/types.d.ts +++ /dev/null @@ -1,418 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { DataFrame } from '../core/frame'; -import { Tensor } from '@tensorflow/tfjs-node'; -import Series from '../core/series'; -import { BaseUserConfig, TableUserConfig } from "table"; -import Str from '../core/strings'; -import Dt from '../core/datetime'; -import { ParseConfig } from 'papaparse'; -import { GroupBy } from '../core/groupby'; -export declare type DTYPES = "float32" | "int32" | "string" | "boolean" | "undefined"; -export declare type ArrayType2D = Array; -export declare type ArrayType1D = Array; -export declare type ConfigsType = { - tableDisplayConfig?: BaseUserConfig & TableUserConfig; - tableMaxRow?: number; - tableMaxColInConsole?: number; - dtypeTestLim?: number; - lowMemoryMode?: boolean; - tfInstance?: any; -}; -export interface BaseDataOptionType { - type?: number; - index?: Array; - columns?: string[]; - dtypes?: Array; - config?: ConfigsType; -} -export interface NdframeInputDataType { - data: any; - type?: number; - index?: Array; - columns?: string[]; - dtypes?: Array; - config?: ConfigsType; - isSeries: boolean; -} -export interface LoadArrayDataType { - data: ArrayType1D | ArrayType2D; - index?: Array; - columns?: string[]; - dtypes?: Array; -} -export interface LoadObjectDataType { - data: object | Array; - type?: number; - index?: Array; - columns?: string[]; - dtypes?: Array; -} -export declare type AxisType = { - index: Array; - columns: Array; -}; -export interface NDframeInterface { - config?: ConfigsType; - $setDtypes(dtypes: Array, infer: boolean): void; - $setIndex(index: Array): void; - $resetIndex(): void; - $setColumnNames(columns: string[]): void; - get dtypes(): Array; - get ndim(): number; - get axis(): AxisType; - get index(): Array; - get columns(): string[]; - get shape(): Array; - get values(): ArrayType1D | ArrayType2D; - get tensor(): Tensor; - get size(): number; - to_csv(options?: CsvOutputOptionsNode): string | void; - to_json(options?: { - format?: "row" | "column"; - filePath?: string; - }): object | void; - to_excel(options?: { - filePath?: string; - sheetName?: string; - }): void; - print(): void; -} -export declare type CsvOutputOptionsNode = { - filePath?: string; - sep?: string; - header?: boolean; -}; -export interface CsvInputOptions extends ParseConfig { -} -export interface SeriesInterface extends NDframeInterface { - iloc(rows: Array): Series; - head(rows: number): Series; - tail(rows: number): Series; - sample(num: number, options?: { - seed?: number; - }): Promise; - add(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - sub(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - mul(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - div(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - pow(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - mod(other: Series | number | Array, options?: { - inplace?: boolean; - }): Series | void; - mean(): number; - median(): number; - mode(): any; - min(): number; - max(): number; - sum(): number; - count(): number; - maximum(other: Series | number | Array): Series; - minimum(other: Series | number | Array): Series; - round(dp: number, options?: { - inplace?: boolean; - }): Series | void; - std(): number; - var(): number; - isna(): Series; - fillna(options?: { - value: number | string | boolean, - inplace?: boolean; - }): Series | void; - sort_values(options?: { - ascending?: boolean, - inplace?: boolean; - }): Series | void; - copy(): Series; - describe(): Series; - reset_index(options?: { - inplace?: boolean; - }): Series | void; - set_index(options?: { - index: Array, - inplace?: boolean; - }): Series | void; - map(callable: any, options?: { - inplace?: boolean; - }): Series | void; - apply(callable: any, options?: { - inplace?: boolean; - }): Series | void; - unique(): Series; - nunique(): number; - value_counts(): Series; - abs(options?: { - inplace?: boolean; - }): Series | void; - cumsum(options?: { - inplace?: boolean; - }): Series | void; - cummin(options?: { - inplace?: boolean; - }): Series | void; - cummax(options?: { - inplace?: boolean; - }): Series | void; - cumprod(options?: { - inplace?: boolean; - }): Series | void; - lt(other: Series | number | Array): Series; - gt(other: Series | number | Array): Series; - le(other: Series | number | Array): Series; - ge(other: Series | number | Array): Series; - ne(other: Series | number | Array): Series; - eq(other: Series | number | Array): Series; - replace(options?: { - oldValue: string | number | boolean, - newValue: string | number | boolean, - inplace?: boolean; - }): Series | void; - dropna(options?: { - inplace?: boolean; - }): Series | void; - argsort(): Series; - argmax(): number; - argmin(): number; - get dtype(): string; - drop_duplicates(options?: { - keep?: "first" | "last"; - inplace?: boolean; - }): Series | void; - astype(dtype: "float32" | "int32" | "string" | "boolean", options?: { - inplace?: boolean; - }): Series | void; - get str(): Str; - get dt(): Dt; - append(values: string | number | boolean | Series | ArrayType1D, index: Array | number | string, options?: { - inplace?: boolean; - }): Series | void; - toString(): string; - and(other: any): Series; - or(other: any): Series; - get_dummies(options?: { - prefix?: string | Array; - prefixSeparator?: string | Array; - inplace?: boolean; - }): DataFrame; -} -export interface DataFrameInterface extends NDframeInterface { - [key: string]: any; - drop(options: { - columns?: string | Array; - index?: Array; - inplace?: boolean; - }): DataFrame | void; - loc(options: { - rows?: Array; - columns?: Array; - }): DataFrame; - iloc(options: { - rows?: Array; - columns?: Array; - }): DataFrame; - head(rows?: number): DataFrame; - tail(rows?: number): DataFrame; - sample(num: number, options?: { - seed?: number; - }): Promise; - add(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - sub(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - mul(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - div(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - pow(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - mod(other: DataFrame | Series | number | number[], options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - mean(options?: { - axis?: 0 | 1; - }): Series; - median(options?: { - axis?: 0 | 1; - }): Series; - mode(options?: { - axis?: 0 | 1; - keep?: number; - }): Series; - min(options?: { - axis?: 0 | 1; - }): Series; - max(options?: { - axis?: 0 | 1; - }): Series; - std(options?: { - axis?: 0 | 1; - }): Series; - var(options?: { - axis?: 0 | 1; - }): Series; - sum(options?: { - axis?: 0 | 1; - }): Series; - count(options?: { - axis?: 0 | 1; - }): Series; - round(dp?: number, options?: { - inplace: boolean; - }): DataFrame | void; - cumsum(options?: { - axis?: 0 | 1; - }): DataFrame | void; - cummin(options?: { - axis?: 0 | 1; - }): DataFrame | void; - cummax(options?: { - axis?: 0 | 1; - }): DataFrame | void; - cumprod(options?: { - axis?: 0 | 1; - }): DataFrame | void; - copy(): DataFrame; - reset_index(options: { - inplace?: boolean; - }): DataFrame | void; - set_index(options: { - index: Array; - column?: string; - drop?: boolean; - inplace?: boolean; - }): DataFrame | void; - describe(): DataFrame; - select_dtypes(include: Array): DataFrame; - abs(options?: { - inplace?: boolean; - }): DataFrame | void; - query(options: { - column?: string, - is?: string, - to?: any, - condition?: Series | Array, - inplace?: boolean - }): DataFrame | void - addColumn(options: { - column: string, - values: Series | ArrayType1D, - inplace?: boolean; - }): DataFrame | void; - column(column: string): Series; - fillna(value: ArrayType1D, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - isna(): DataFrame; - dropna(axis?: 0 | 1, options?: { - inplace?: boolean; - }): DataFrame | void; - apply(callable: any, options?: { - axis?: 0 | 1; - }): DataFrame | Series; - apply_map(callable: any, options?: { - inplace?: boolean; - }): DataFrame | void; - lt(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - gt(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - le(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - ge(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - ne(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - eq(other: DataFrame | Series | number, options?: { - axis?: 0 | 1; - }): DataFrame; - replace(oldValue: number | string | boolean, newValue: number | string | boolean, options?: { - columns?: Array; - inplace?: boolean; - }): DataFrame | void; - transpose(options?: { - inplace?: boolean; - }): DataFrame | void; - get T(): DataFrame; - get ctypes(): Series; - astype(options?: { - column: string, - dtype: "float32" | "int32" | "string" | "boolean", - inplace?: boolean; - }): DataFrame | void; - nunique(axis: 0 | 1): Series; - rename(mapper: object, options?: { - axis?: 0 | 1; - inplace?: boolean; - }): DataFrame | void; - sort_index(options?: { - inplace?: boolean; - ascending?: boolean; - }): DataFrame | void; - sort_values(options?: { - by: string, - ascending?: boolean; - inplace?: boolean; - }): DataFrame | void; - append(newValues: ArrayType1D | ArrayType2D | Series | DataFrame, index: Array | number | string, options?: { - inplace?: boolean; - }): DataFrame | void; - toString(): string; - get_dummies(options?: { - columns?: string | Array; - prefix?: string | Array; - prefixSeparator?: string | Array; - inplace?: boolean; - }): DataFrame | void; - groupby(column: string): GroupBy; - -} -export interface DateTime { - month(): Series; - day(): Series; - year(): Series; - month_name(): Series; - monthday(): Series; - weekdays(): Series; - hours(): Series; - seconds(): Series; - minutes(): Series; -} diff --git a/danfojs-node/types/shared/utils.d.ts b/danfojs-node/types/shared/utils.d.ts deleted file mode 100644 index 5556d505..00000000 --- a/danfojs-node/types/shared/utils.d.ts +++ /dev/null @@ -1,259 +0,0 @@ -/** -* @license -* Copyright 2021, JsData. All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. - -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ========================================================================== -*/ -import { ArrayType1D, ArrayType2D } from './types'; -import { Series } from '../'; -import { DataFrame } from '../'; -/** - * Utility class for working with Frames and Series - */ -export default class Utils { - /** - * Removes an element from a 1D array - * - * ```js - * - * ``` - * @param arr The array to filter. - * @param index The index to filter by. - */ - removeElementFromArray(arr: ArrayType1D, index: number): ArrayType1D; - /** - * Check if value is a string. - * @param value The value to check. - * @returns - */ - isString(value: T): boolean; - /** - * Checks if value is a number. - * @param value The value to check. - * @returns - */ - isNumber(value: T): boolean; - /** - * Checks if value is an object. - * @param value The value to check. - * @returns - */ - isObject(value: any): boolean; - /** - * Checks if a value is null - * @param value The value to check. - * @returns - */ - isNull(value: T): boolean; - /** - * Checks if a value is undefined - * @param value The value to check. - * @returns - */ - isUndefined(value: T): boolean; - /** - * Checks if a value is empty. Empty means it's either null, undefined or NaN - * @param value The value to check. - * @returns - */ - isEmpty(value: T): boolean; - /** - * Generates an array of integers between specified range - * @param start The starting number. - * @param end The ending number. - */ - range(start: number, end: number): Array; - /** - * Checks if object has the specified key - * @param obj The object to check. - * @param key The key to find. - */ - keyInObject(obj: object, key: number | string): boolean; - /** - * Transposes an array of array - * @param obj The object to check. - * @param key The key to find. - */ - transposeArray(arr: ArrayType1D | ArrayType2D): ArrayType1D | ArrayType2D; - /** - * Retrieve row array and column names from an object of the form {a: [1,2,3,4], b: [30,20, 30, 20]} - * @param obj The object to retrieve rows and column names from. - */ - getRowAndColValues(obj: object): [ArrayType1D | ArrayType2D, string[]]; - /** - * Converts a 2D array of array to 1D array for Series Class - * @param arr The array to convert. - */ - convert2DArrayToSeriesArray(arr: ArrayType2D): Array; - /** - * Replaces all missing values with NaN. Missing values are undefined, Null and Infinity - * @param arr The array - * @param isSeries Whether the arr is a series or not - */ - replaceUndefinedWithNaN(arr: ArrayType1D | ArrayType2D, isSeries: boolean): ArrayType1D | ArrayType2D; - /** - * Infer data type from an array or array of arrays - * @param arr An array or array of arrays - */ - inferDtype(arr: ArrayType1D | ArrayType2D): string[]; - /** - * Private type checker used by inferDtype function - * @param arr The array - */ - private $typeChecker; - /** - * Returns the unique values in an 1D array - * @param arr The array - */ - unique(arr: ArrayType1D): ArrayType1D; - /** - * Checks if array is 1D - * @param arr The array - */ - is1DArray(arr: ArrayType1D | ArrayType2D): boolean; - /** - * Converts an array to an object using array index as object keys - * @param arr The array - */ - convertArrayToObject(arr: ArrayType1D | ArrayType2D): any; - /** - * Count the NaN and non-NaN values present in an array - * @param arr Array object - * @param val whether to return the value count instead of the null count - * @param isSeries Whether the array is of type series or not - */ - countNaNs(arr: ArrayType1D | ArrayType2D, returnVal: boolean | undefined, isSeries: boolean): number | Array; - /** - * Round elements of an array or array of arrays to specified dp - * @param arr The Array to round - * @param dp The number of dp to round to - * @param isSeries Whether the array is of type Series or not - */ - round(arr: Array, dp: number | undefined, isSeries: boolean): ArrayType1D | ArrayType2D; - /** - * Checks if a func is a function - * @param func - */ - isFunction(func: object): boolean; - /** - * Generates n random numbers between start and end. - * @param start - * @param end - * @param size - */ - randNumberGenerator(start: number, end: number, size: number): number[]; - /** - * Throws error when a required parameter is missing. - * @param paramsObject The parameters passed to the function - * @param paramsNeeded The required parameters in the function - */ - throwErrorOnWrongParams(paramsObject: object, paramsNeeded: Array): void; - /** - * Maps integer values (0, 1) to boolean (false, true) - * @param arr The array of integers - * @param dim The dimension of the array - */ - mapIntegersToBooleans(arr: Array, dim: number): Array; - /** - * Maps boolean values (false, true) to integer equivalent (0, 1) - * @param arr The array of booleans - * @param dim The dimension of the array - */ - mapBooleansToIntegers(arr: Array, dim: number): Array; - /** - * Generates an array of dim (row x column) with inner values set to zero - * @param row - * @param column - */ - zeros(row: number, column: number): ArrayType1D | ArrayType2D; - /** - * Shuffles and returns a random slice of an array - * @param num - * @param array - */ - shuffle(array: ArrayType1D | ArrayType2D, num: number): ArrayType1D | ArrayType2D; - /** - * Sorts an array in specified order - * @param arr - * @param ascending - * @returns - */ - sort(arr: Array, ascending?: boolean): Array; - /** - * Checks if current environment is Browser - */ - isBrowserEnv(): any; - /** - * Checks if current environment is Node - */ - isNodeEnv(): any; - /** - * Remove NaN values from 1D array - * @param arr - */ - removeMissingValuesFromArray(arr: Array | ArrayType1D): (string | number | boolean)[]; - /** - * Replace NaN with null before tensor operations - * @param arr - */ - replaceNanWithNull(arr: ArrayType1D | ArrayType2D): (string | number | boolean | (string | number | boolean)[] | null)[]; - /** - * Get duplicate values in a array - * @param arr - */ - getDuplicate(arr: Array): any; - /** - * Returns the index of a sorted array - * @param arr1 The first array - * @param arr2 The second array - * @param dtype The data type of the arrays - * - * @returns sorted index - */ - sortArrayByIndex(arr1: ArrayType1D | ArrayType2D, arr2: ArrayType1D | ArrayType2D, dtype: string): number[]; - /** - * Returns a new series with properties of the old series - * - * @param series The series to copy - */ - createNdframeFromNewDataWithOldProps({ ndFrame, newData, isSeries }: { - ndFrame: Series; - newData: any; - isSeries: boolean; - }): Series | DataFrame; - /** - * Checks if two series are compatible for a mathematical operation - * @param object - * - * firstSeries ==> First Series object - * - * secondSeries ==> Second Series object to comapre with - * - * operation ==> The mathematical operation - */ - checkSeriesOpCompactibility({ firstSeries, secondSeries, operation }: { - firstSeries: Series; - secondSeries: Series; - operation: string; - }): void; - /** - * Custom sort for an array of index and values - * @param arr The array of objects to sort - * @param ascending Whether to sort in ascending order or not - */ - sortObj(arr: Array<{ - index: number | string; - value: number | string | boolean; - }>, ascending: boolean): { - index: number | string; - value: number | string | boolean; - }[]; -} diff --git a/package.json b/package.json index 25247d3a..65ca731b 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,21 @@ { "name": "danfo", + "version": "1.2.0", "private": true, "workspaces": [ "danfojs-node/**", "danfojs-browser/**" ], "scripts": { - "build": "cd danfojs-node && yarn build:clean && cd ../danfojs-browser && yarn build:clean", - "test": "cd danfojs-node && yarn && yarn test:clean && cd ../danfojs-browser && yarn && yarn test:clean" + "install": "cd src/danfojs-base && yarn && cd ../danfojs-browser && yarn && cd ../danfojs-node && yarn", + "build": "yarn build:browser && yarn build:node", + "build:browser": "cd src/danfojs-browser && yarn build:clean", + "build:node": "cd src/danfojs-node && yarn build:clean", + "pretest": "cd src/danfojs-base && yarn", + "test": "yarn test:browser && yarn test:node", + "pretest:browser": "yarn pretest", + "test:browser": "cd src/danfojs-browser && yarn && yarn test:clean", + "pretest:node": "yarn pretest", + "test:node": "cd src/danfojs-node && yarn && yarn test:clean" } -} \ No newline at end of file +} diff --git a/src/danfojs-base/README.md b/src/danfojs-base/README.md new file mode 100644 index 00000000..69ec125c --- /dev/null +++ b/src/danfojs-base/README.md @@ -0,0 +1,46 @@ +## danfojs-base + +**danfojs-base** is the core module of Danfo.js. Danfojs-node and Danfojs-browser folders simply extends/export this functions and classes from this module. + +## Folders and Files + + - __aggregators__: All files that contain functions that aggregate data. + - __core__: Holds the core classes of Danfo.js. + - `daterange`: Class that represents a date range. + - `datetime`: Class that represents a date and time. + - `frame`: Class that represents a frame. + - `series`: Class that represents a series. + - `generic`: Class that represents a generic object. + - `indexing`: Class that represents an indexing. + - `math.ops`: Class that represents a math operation. + - `strings`: Class that represents a string. + - __io__: Holds the IO classes of Danfo.js. + - __browser__: Holds the browser IO classes. + - `io.csv`: Holds the CSV IO classes. + - `io.json`: Holds the JSON IO classes. + - `io.excel`: Holds the excel IO classes. + - __node__: Holds the node IO classes for Node.js + - `io.csv`: Holds the CSV IO classes for Node.js + - `io.json`: Holds the JSON IO classes for Node.js + - `io.excel`: Holds the excel IO classes for Node.js + - __plotting__: Holds the plotting classes + - __plotly__: Holds the plotting class for Plotly charts. + - __vega__: (Stub) Holds the plotting class for Vega charts. + - __shared__ + - `config`: Holds the configuration class. + - `defaults`: Holds the default values for the configuration class. + - `errors`: Holds the error classes. + - `tensorflowlib`: Autogenerated tensorflow library export. + - `utils`: Holds the utility classes. + - `types`: Holds the type classes. + - __transformers__: Holds the transformers files + - __encoders__: Holds the encoder classes. + - `dummy.encoder`: Holds the dummy encoder class + - `one.hot.encoder`: Holds the onehot encoder class + - `label.encoder`: Holds the label encoder class + - __scalers__ + - `min.max.scalers`: Holds the min max scaler class + - `standard.scalers`: Holds the standard scaler class + - `concat`: Holds the concatenation class + - `merge`: Holds the merge class + - `index.ts`: Entry point for the module. \ No newline at end of file diff --git a/src/danfojs-base/aggregators/groupby.ts b/src/danfojs-base/aggregators/groupby.ts new file mode 100644 index 00000000..63671914 --- /dev/null +++ b/src/danfojs-base/aggregators/groupby.ts @@ -0,0 +1,661 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import DataFrame from "../core/frame" +import { ArrayType1D, ArrayType2D } from "../shared/types" +import { variance, std, median, mode } from 'mathjs'; +import concat from "../transformers/concat" +import Series from "../core/series"; + + + +/** + * The class performs all groupby operation on a dataframe + * involving all aggregate funciton + * @param {colDict} colDict Object of unique keys in the group by column + * @param {keyCol} keyCol Array contains the column names + * @param {data} Array the dataframe data + * @param {columnName} Array of all column name in the dataframe. + * @param {colDtype} Array columns dtype + */ +export default class Groupby { + colDict: { [key: string ]: {} } = {} + keyCol: ArrayType1D + data?: ArrayType2D | null + columnName: ArrayType1D + colDtype: ArrayType1D + colIndex: ArrayType1D + groupDict?: any + groupColNames?: Array + keyToValue: { + [key: string] : ArrayType1D + } = {} + + constructor(keyCol: ArrayType1D, data: ArrayType2D | null, columnName: ArrayType1D, colDtype:ArrayType1D, colIndex: ArrayType1D) { + + this.keyCol = keyCol; + this.data = data; + this.columnName = columnName; + //this.dataTensors = {}; //store the tensor version of the groupby data + this.colDtype = colDtype; + this.colIndex = colIndex + + } + /** + * Generate group object data needed for group operations + * let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + * let cols = [ "A", "B", "C" ]; + * let df = new dfd.DataFrame(data, { columns: cols }); + * let groupDf = df.groupby([ "A" ]); + * The following internal object is generated and save to this.colDict + * { + * '1': { A: [ 1 ], B: [ 2 ], C: [ 3 ] }, + * '4': { A: [ 4 ], B: [ 5 ], C: [ 6 ] }, + * '20': { A: [ 20 ], B: [ 30 ], C: [ 40 ] }, + * '39': { A: [ 39 ], B: [ 89 ], C: [ 78 ] } + * } + * Since for groupby using more than one columns is index via '-' + * e.g for df.groupby(['A','B']) + * the result will look like this + * { + * '1-2': {A: [ 1 ], B: [ 2 ], C: [ 3 ]}, + * '4-5': {A: [ 4 ], B: [ 5 ], C: [ 6 ]} + * } + * but in doing analysis on a specific column like this + * df.groupby(['A','B']).col(['C']) + * will have the following set of internal result + * { + * '1-2': { C: [ 3 ]}, + * '4-5': {C: [ 6 ]} + * } + * In building our multindex type of DataFrame for this data, + * we've somehow loose track of value for column A and B. + * This could actually be generated by using split('-') on the object keys + * e.g '1-2'.split('-') will give us the value for A and B. + * But we might have weird case scenerio where A and B value has '-` + * e.g + * { + * '1--2-': { C: [ 3 ]}, + * '4--5-': {C: [ 6 ]} + * } + * using `.split('-') might not work well + * Hence we create a key-value `keyToValue` object to store index and their + * associated value + * NOTE: In the previous implementation we made use of Graph representation + * for the group by data and Depth First search (DFS). But we decided to use key-value + * object in javascript as an hashmap to reduce search time compared to using Grpah and DFS + */ + group(): Groupby{ + const self = this + let keyToValue:{ + [key: string] : ArrayType1D + } = {} + const group = this.data?.reduce((prev: any, current)=>{ + let indexes= [] + for(let i in self.colIndex) { + let index = self.colIndex[i] as number + indexes.push(current[index]) + } + let index = indexes.join('-') + + if(!keyToValue[index]) { + keyToValue[index] = indexes + } + + if(prev[index]) { + let data = prev[index] + for (let i in self.columnName) { + let colName = self.columnName[i] as string + data[colName].push(current[i]) + } + } else { + prev[index] = {} + for (let i in self.columnName) { + let colName = self.columnName[i] as string + prev[index][colName] = [current[i]] + } + } + return prev + + }, {}) + this.colDict = group + this.keyToValue = keyToValue + return this + } + + /** + * Generate new internal groupby data + * group = df.groupby(['A', 'B']).col('C') + * This filter the colDict property as generated by `.group()` + * it filter each group to contain only column `C` in their internal object + * e.g + * { + * '1-2': {A: [ 1 ], B: [ 2 ], C: [ 3 ]}, + * '4-5': {A: [ 4 ], B: [ 5 ], C: [ 6 ]} + * } + * to + * { + * '1-2': { C: [ 3 ]}, + * '4-5': {C: [ 6 ]} + * } + * @param colNames column names + * @return Groupby + */ + col(colNames: ArrayType1D | undefined): Groupby { + + if (typeof colNames === "undefined") { + colNames = this.columnName.filter((_, index)=>{ + return !this.colIndex.includes(index) + }) + } + let self = this + colNames.forEach((val) => { + if (!self.columnName.includes(val)) + throw new Error(`Column ${val} does not exist in groups`) + }) + let colDict: { [key: string ]: {} } = {...this.colDict} + for(let [key, values] of Object.entries(colDict)) { + let c: { [key: string ]: [] } = {} + let keyVal: any = {...values} + for(let colKey in colNames) { + let colName = colNames[colKey] as string + c[colName] = keyVal[colName] + } + colDict[key] = c + } + const gp = new Groupby( + this.keyCol, + null, + this.columnName, + this.colDtype, + this.colIndex + ) + gp.colDict = colDict + gp.groupColNames = colNames as Array + gp.keyToValue = this.keyToValue + + return gp + } + + /** + * Perform all groupby arithmetic operations + * In the previous implementation all groups data are + * stord as DataFrame, which involve lot of memory usage + * Hence each groups are just pure javascrit object + * and all arithmetic operation is done directly on javascript + * arrays. + * e.g + * using this internal data + * { + * '1-2': {A: [ 1,3 ], B: [ 2,5 ], C: [ 3, 5 ]}, + * '4-5': {A: [ 4,1 ], B: [ 5,0 ], C: [ 6, 12 ]} + * } + * 1) using groupby(['A', 'B']).arithmetic("mean") + * result: * { + * '1-2': {A_mean: [ 2 ], B_mean: [ 3.5 ], C_mean: [ 4 ]}, + * '4-5': {A_mean: [ 2.5 ], B: [ 2.5 ], C_mean: [ 9 ]} + * } + * 2) .arithmetic({ + * A: 'mean', + * B: 'sum', + * C: 'min' + * }) + * result: + * { + * '1-2': {A_mean: [ 2 ], B_sum: [ 7 ], C_min: [ 3 ]}, + * '4-5': {A_mean: [ 2.5 ], B_sum: [ 5 ], C_min: [ 6 ]} + * } + * 3) .arithmetic({ + * A: 'mean', + * B: 'sum', + * C: ['min', 'max'] + * }) + * result: + * { + * '1-2': {A_mean: [ 2 ], B_sum: [ 7 ], C_min: [ 3 ], C_max: [5]}, + * '4-5': {A_mean: [ 2.5 ], B_sum: [ 5 ], C_min: [ 6 ], C_max: [12]} + * } + * @param operation + */ + private arithemetic(operation: {[key: string] : Array | string} | string): { [key: string ]: {} } { + + const opsName = [ "mean", "sum", "count", "mode", "std", "var", "cumsum", "cumprod", + "cummax", "cummin", "median" , "min", "max"]; + if (typeof operation === "string" ) { + if (!opsName.includes(operation)) { + throw new Error(`group operation: ${operation} is not valid`) + } + } else { + Object.keys(operation).forEach((key)=>{ + let ops = operation[key] + if(Array.isArray(ops)) { + for(let op of ops) { + if (!opsName.includes(op)) { + throw new Error(`group operation: ${op} for column ${key} is not valid`) + } + } + } else { + if (!opsName.includes(ops)) { + throw new Error(`group operation: ${ops} for column ${key} is not valid`) + } + } + + }) + } + let colDict: { [key: string ]: {} } = {...this.colDict} + for(const [key, values] of Object.entries(colDict)) { + let colVal: { [key: string ]: Array } = {} + let keyVal: any = {...values} + let groupColNames: Array = this.groupColNames as Array + for(let colKey=0; colKey < groupColNames.length; colKey++) { + let colName = groupColNames[colKey] + let colIndex = this.columnName.indexOf(colName) + let colDtype = this.colDtype[colIndex] + let operationVal = (typeof operation === "string") ? operation : operation[colName] + if (colDtype === "string" && operationVal !== "count") throw new Error(`Can't perform math operation on column ${colName}`) + + if (typeof operation === "string") { + let colName2 = `${colName}_${operation}` + colVal[colName2] = this.groupMathLog(keyVal[colName], operation) + } + else { + if(Array.isArray(operation[colName])) { + for(let ops of operation[colName]) { + let colName2 = `${colName}_${ops}` + colVal[colName2] = this.groupMathLog(keyVal[colName],ops) + } + } else { + let ops: string = operation[colName] as string + let colName2 = `${colName}_${ops}` + colVal[colName2] = this.groupMathLog(keyVal[colName], ops) + } + + } + } + colDict[key] = colVal + } + return colDict + } + + /** + * Peform all arithmetic logic + * @param colVal + * @param ops + */ + private groupMathLog(colVal: Array, ops: string): Array{ + let data = [] + switch(ops) { + case "max": + let max = colVal.reduce((prev, curr)=> { + if (prev > curr) { + return prev + } + return curr + }) + data.push(max) + break; + case "min": + let min = colVal.reduce((prev, curr)=> { + if (prev < curr) { + return prev + } + return curr + }) + data.push(min) + break; + case "sum": + let sum = colVal.reduce((prev, curr)=> { + return prev + curr + }) + data.push(sum) + break; + case "count": + data.push(colVal.length) + break; + case "mean": + let sumMean = colVal.reduce((prev, curr)=> { + return prev + curr + }) + data.push(sumMean / colVal.length) + break; + case "std": + data.push(std(colVal)) + break; + case "var": + data.push(variance(colVal)) + break; + case "median": + data.push(median(colVal)) + break; + case "mode": + data.push(mode(colVal)) + break; + case "cumsum": + colVal.reduce((prev, curr) => { + let sum = prev + curr + data.push(sum) + return sum + }, 0) + break; + case "cummin": + data = [colVal[0]] + colVal.slice(1,).reduce((prev, curr)=>{ + if (prev < curr) { + data.push(prev) + return prev + } + data.push(curr) + return curr + }, data[0]) + break; + case "cummax": + data = [colVal[0]] + colVal.slice(1,).reduce((prev, curr)=> { + if (prev > curr) { + data.push(prev) + return prev + } + data.push(curr) + return curr + }, data[0]) + break; + case "cumprod": + colVal.reduce((prev, curr) => { + let sum = prev * curr + data.push(sum) + return sum + }, 1) + break; + } + return data + } + + /** + * Takes in internal groupby internal data and convert + * them to a single data frame. + * @param colDict + */ + private toDataFrame(colDict: { [key: string ]: {} }): DataFrame { + let data: { [key: string ]: ArrayType1D } = {} + + for(let key of this.colKeyDict(colDict)) { + let value = colDict[key] + let keyDict: { [key: string ]: ArrayType1D } = {} + let oneValue = Object.values(value)[0] as ArrayType1D + let valueLen = oneValue.length + for(let key1 in this.keyCol) { + let keyName = this.keyCol[key1] as string + let keyValue = this.keyToValue[key][key1] + keyDict[keyName] = Array(valueLen).fill(keyValue) + } + let combine: { [key: string ]: ArrayType1D } = {...keyDict, ...value} + if(Object.keys(data).length < 1) { + data = combine + } else { + for(let dataKey of Object.keys(data)) { + let dataValue = combine[dataKey] as ArrayType1D + data[dataKey] = [...data[dataKey], ...dataValue] + } + } + } + return new DataFrame(data) + } + + private operations(ops: string): DataFrame { + if (!this.groupColNames) { + let colGroup = this.col(undefined) + let colDict = colGroup.arithemetic(ops) + let df = colGroup.toDataFrame(colDict) + return df + } + let colDict = this.arithemetic(ops) + let df = this.toDataFrame(colDict) + return df + } + + /** + * Obtain the count for each group + * @returns DataFrame + * + */ + count(): DataFrame { + return this.operations("count") + } + + /** + * Obtain the sum of columns for each group + * @returns DataFrame + * + */ + sum(): DataFrame{ + return this.operations("sum") + } + + /** + * Obtain the standard deviation of columns for each group + * @returns DataFrame + */ + std(): DataFrame{ + return this.operations("std") + } + + /** + * Obtain the variance of columns for each group + * @returns DataFrame + */ + var(): DataFrame{ + return this.operations("var") + } + + /** + * Obtain the mean of columns for each group + * @returns DataFrame + */ + mean(): DataFrame{ + return this.operations("mean") + } + + /** + * Obtain the cumsum of columns for each group + * @returns DataFrame + * + */ + cumSum(): DataFrame{ + return this.operations("cumsum") + } + + /** + * Obtain the cummax of columns for each group + * @returns DataFrame + */ + cumMax(): DataFrame{ + return this.operations("cummax") + } + + /** + * Obtain the cumprod of columns for each group + * @returns DataFrame + */ + cumProd(): DataFrame{ + return this.operations("cumprod") + } + + /** + * Obtain the cummin of columns for each group + * @returns DataFrame + */ + cumMin(): DataFrame{ + return this.operations("cummin") + } + + /** + * Obtain the max value of columns for each group + * @returns DataFrame + * + */ + max(): DataFrame{ + return this.operations("max") + } + + /** + * Obtain the min of columns for each group + * @returns DataFrame + */ + min(): DataFrame{ + return this.operations("min") + } + + /** + * Obtain a specific group + * @param keys Array + * @returns DataFrame + */ + getGroup(keys: Array): DataFrame { + let dictKey = keys.join("-") + let colDict: { [key: string ]: {} } = {} + colDict[dictKey] = {...this.colDict[dictKey]} + return this.toDataFrame(colDict) + } + + /** + * Perform aggregation on all groups + * @param ops + * @returns DataFrame + */ + agg(ops: { [key: string ]: Array | string }): DataFrame { + let columns = Object.keys(ops); + let col_gp = this.col(columns); + let data = col_gp.arithemetic(ops); + let df = col_gp.toDataFrame(data); + return df; + } + + /** + * Apply custom aggregator function + * to each group + * @param callable + * @returns DataFrame + * @example + * let grp = df.groupby(['A']) + * grp.apply((x) => x.count()) + */ + apply(callable: (x: DataFrame)=> DataFrame | Series ): DataFrame { + let colDict: { [key: string ]: DataFrame | Series } = {} + for(const key of this.colKeyDict(this.colDict)) { + let valDataframe = new DataFrame(this.colDict[key]) + colDict[key] = callable(valDataframe) + } + return this.concatGroups(colDict) + } + + private concatGroups(colDict: {[key: string]: DataFrame | Series}): DataFrame { + let data: Array = [] + for(const [key, values] of Object.entries(colDict)) { + let copyDf: DataFrame; + if (values instanceof DataFrame) { + copyDf = values.copy() + } + else { + let columns = values.index as string[] + columns = columns.length > 1 ? columns : ['applyOps'] + copyDf = new DataFrame([values.values], {columns: columns }) + } + let len = copyDf.shape[0] + let key1: any; + for(key1 in this.keyCol){ + + let keyName = this.keyCol[key1] as string + let keyValue = this.keyToValue[key][key1] + let dfValue = Array(len).fill(keyValue) + let atIndex: number = parseInt(key1) + if (this.groupColNames) { + copyDf.addColumn(keyName, dfValue, {inplace: true, atIndex: atIndex }) + } + else { + copyDf.addColumn(`${keyName}_Group`, dfValue, {inplace: true, atIndex: atIndex }) + } + + } + data.push(copyDf) + } + return concat({dfList: data, axis:0}) as DataFrame + } + + /** + * obtain the total number of groups + * @returns number + */ + get ngroups(): number{ + let keys = Object.keys(this.colDict) + return keys.length + } + + /** + * obtaind the internal group data + * @returns {[keys: string]: {}} + */ + get groups(): {[keys: string]: {}}{ + return this.colDict + } + + /** + * Obtain the first row of each group + * @returns DataFrame + */ + first(): DataFrame{ + return this.apply((x)=>{ + return x.head(1) + }) + } + + /** + * Obtain the last row of each group + * @returns DataFrame + */ + last(): DataFrame { + return this.apply((x)=>{ + return x.tail(1) + }) + } + + /** + * Obtains the dataframe se of each groups + * @returns DataFrame + */ + size(): DataFrame { + return this.apply((x)=>{ + return new Series([x.shape[0]]) + }) + } + + private colKeyDict(colDict: { [key: string ]: {} }): string[]{ + let keyDict :{ [key: string ]: string[] } = {} + + for(let key of Object.keys(colDict)) { + let firstKey = key.split("-")[0] + if (firstKey in keyDict) { + keyDict[firstKey].push(key) + } + else { + keyDict[firstKey] = [key] + } + } + let keys = [] + for(let key of Object.keys(keyDict)) { + keys.push(...keyDict[key]) + } + return keys + } + +} \ No newline at end of file diff --git a/src/danfojs-base/core/daterange.ts b/src/danfojs-base/core/daterange.ts new file mode 100644 index 00000000..7d342645 --- /dev/null +++ b/src/danfojs-base/core/daterange.ts @@ -0,0 +1,271 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Utils from "../shared/utils"; + +const utils = new Utils(); + +interface Params { + start?: string; + offset?: number; + end?: string; + freq?: string; + period?: number +} +class DateRange { + private offset?: number + private start?: string + private end?: string + private freq: string + private period?: number + private freqList: string[] + + constructor({start, end, offset, freq, period}: Params){ + this.start = start + this.end = end + this.offset = offset + this.freq = freq ? freq : "D" + this.period = period + this.freqList = [ "M", "D", "s", "H", "m", "Y" ] + + if (this.freq.length == 1){ + if (!this.freqList.includes(this.freq)){ + throw new Error(`invalid freq ${this.freq}`); + } + } else { + this.offset = parseInt(this.freq.slice(0, -1)); + if (!Number.isFinite(this.offset)){ + throw new Error(`invalid freq offset ${this.freq.slice(0, -1)}`); + } + this.freq = this.freq.slice(-1); + if (!this.freqList.includes(this.freq)){ + throw new Error(`invalid freq ${this.freq}`); + } + } + + } + + range(): string[] { + let start = this.start + let period = this.period + let end = this.end + let offset = this.offset + let startDate: Date + let endDate: Date + let startRange: number + let endRange: number + if (start && end) { + startDate = new Date(start) + startRange = this.freqType(startDate, this.freq) + endDate = new Date(end) + endRange = this.freqType(endDate, this.freq) + + let startYear = startDate.getFullYear() + let endYear = endDate.getFullYear() + if ((startYear <= endYear) && (startDate.getMonth() !== endDate.getMonth())){ + if (this.freq == "M") { + endRange = this.monthEnd(startDate, endDate) + } + else if (this.freq === "D") { + endRange = this.dayEnd(startDate, endDate) - startRange + } + } + let rangeArray = utils.range(startRange, endRange) + if ( offset ) { + rangeArray = this.offsetCount(rangeArray, offset) + } + let dateRange = rangeArray.map((x) => { + return this.setDateProps(startDate, this.freq, x) + }) + dateRange[dateRange.length -1] = endDate + let dateString = this.toLocalString(dateRange) + return dateString + } + else if ( start && !(end) ) { + startDate = new Date(start) + startRange = this.freqType(startDate, this.freq) + period = period as number + endRange = offset ? ((period * offset) - 1) : period -1; + + if ( startRange > endRange ) { + endRange = endRange + startRange + } + let rangeArray = utils.range(startRange, endRange) + + if ( offset ) { + rangeArray = this.offsetCount(rangeArray, offset) + } + let dateRange = rangeArray.map((x) => { + return this.setDateProps(startDate, this.freq, x) + }) + + let dateString = this.toLocalString(dateRange) + return dateString + } + // if end and not start given + endDate = new Date(end as string) + endRange = this.freqType(endDate, this.freq) + period = period as number + startRange = (endRange - period) + 1 + let rangeArray = utils.range(startRange, endRange) + + if ( offset ) { + rangeArray = this.offsetCount(rangeArray, offset) + } + let dateRange = rangeArray.map((x) => { + return this.setDateProps(endDate, this.freq, x) + }) + let dateString = this.toLocalString(dateRange) + return dateString + } + + /** + * @param date Date + * @param ftype string: frequency type, month, Year, day etc + * @param number + */ + private freqType(date: Date, ftype: string): number{ + let rslt: number = 0; + switch (ftype){ + + case "M": + rslt = date.getMonth(); + break; + case "Y": + rslt = date.getFullYear(); + break; + case "s": + rslt = date.getSeconds(); + break; + case "D": + rslt = date.getDate(); + break; + case "H": + rslt = date.getHours(); + break; + case "m": + rslt = date.getMinutes(); + break; + } + return rslt; + } + + + private offsetCount(dArray: number[], offset: number) :number[] { + let rArray: number[] = [] + for (let i = 0; i < dArray.length; i += offset){ + rArray.push(dArray[i]); + } + return rArray; + } + + private setDateProps(date: Date, ftype: string, val: number[] | number): Date { + let newDate = new Date(date.valueOf()) + switch (ftype){ + case "M": + if (Array.isArray(val)){ + + newDate.setFullYear(newDate.getFullYear() + val[0]); + newDate.setMonth(val[1]); + } else { + newDate.setMonth(val); + } + break; + case "Y": + newDate.setFullYear(val as number); + break; + case "s": + newDate.setSeconds(val as number); + break; + case "D": + newDate.setDate(val as number); + break; + case "H": + newDate.setHours(val as number); + break; + case "m": + newDate.setMinutes(val as number); + break; + } + return newDate; + } + + + private toLocalString(dArray: Date[]) { + let r_array = dArray.map((x) => { + return x.toLocaleString(); + }); + return r_array; + } + + private monthEnd(startDate: Date, endDate: Date) { + let endMonth = endDate.getMonth() + let diffYear = endDate.getFullYear() - startDate.getFullYear() + let endRange = (12 * diffYear) + endMonth + return endRange + } + + private monthRange(range: number[]): number[][] { + let minus: number; + let yVal = 0 + let dateRange: number[][] = range.map((x) => { + if (x > 11) { + if ( x % 12 == 0) { + minus = x + yVal = x / 12 + return [yVal, (x - minus)] + } + else { + return [yVal, (x -minus)] + } + } + return [yVal, x] + }) + return dateRange + } + + private dayEnd(startDate: Date, endDate: Date): number{ + let monthEnd = this.monthEnd(startDate, endDate) + let range = utils.range(startDate.getMonth(), monthEnd) + let mRange = this.monthRange(range) + + let sum = 0 + for (let i=0; i < mRange.length; i++) { + let val = mRange[i] + let dDate: number + if (i === mRange.length - 1) { + dDate = new Date(startDate.getUTCFullYear() + val[0], val[1], endDate.getDate()).getDate() + } + else { + dDate = new Date(startDate.getUTCFullYear() + val[0], val[1], 0).getDate() + } + sum += dDate + } + return sum + } +} + +/** + * Generate sequence of Dates + * @param start : signify the date to start with + * @param end : signify the date to end with + * @param period : the total number of date to generate + * @param offset : set the date range offset + * @param freq: set the date range frequency and offset + * @return string[] + */ +export default function dateRange(param: Params): string[] { + const dateRange = new DateRange(param) + return dateRange.range() +} \ No newline at end of file diff --git a/danfojs-browser/src/core/datetime.js b/src/danfojs-base/core/datetime.ts similarity index 50% rename from danfojs-browser/src/core/datetime.js rename to src/danfojs-base/core/datetime.ts index 8d7e68ba..accbc7f3 100644 --- a/danfojs-browser/src/core/datetime.js +++ b/src/danfojs-base/core/datetime.ts @@ -1,6 +1,6 @@ /** * @license -* Copyright 2021, JsData. All rights reserved. +* Copyright 2022 JsData. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,230 +12,254 @@ * limitations under the License. * ========================================================================== */ +import { ArrayType1D, DateTime } from "../shared/types"; import Series from "./series"; -const MONTH_NAME = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; -const WEEK_NAME = ["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"]; +const WEEK_NAME = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; +const MONTH_NAME = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; /** * Format and handle all datetime operations on Series or Array of date strings * @param data Series or Array of date strings */ -export default class TimeSeries { +export default class TimeSeries implements DateTime { + private $dateObjectArray: Array - constructor(data) { - if (data instanceof Series) { - this.$dateObjectArray = this.processData(data.values); - } else { - this.$dateObjectArray = this.processData(data); + constructor(data: Series | ArrayType1D) { + if (data instanceof Series) { + this.$dateObjectArray = this.processData(data.values as ArrayType1D) + } else { + this.$dateObjectArray = this.processData(data) + } } - } - /** + /** * Processed the data values into internal structure for easy access * @param dateArray An array of date strings */ - processData(dateArray) { - const values = dateArray.map((dateString) => new Date(`${dateString}`)); - return values; - } + private processData(dateArray: ArrayType1D): Array { + const values = dateArray.map(dateString => new Date(`${dateString}`)) + return values + } - /** + /** * Returns the month, in local time. * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-01", * "2019-03-01", * "2019-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const dfNew = df.dt.month() * console.log(dfNew.values) * // [1, 2, 3, 4] * ``` */ - month() { - const newValues = this.$dateObjectArray.map((date) => date.getMonth()); - return new Series(newValues); - } + month(): Series { + const newValues = this.$dateObjectArray.map(date => date.getMonth()) + return new Series(newValues); + } - /** + /** * Returns the day of the week, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-01", * "2019-03-01", * "2019-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const dayOfWeek = df.dt.dayOfWeek() * console.log(dayOfWeek.values) * ``` */ - day() { - const newValues = this.$dateObjectArray.map((date) => date.getDay()); - return new Series(newValues); - } + dayOfWeek() { + const newValues = this.$dateObjectArray.map(date => date.getDay()) + return new Series(newValues); + } - /** + /** * Returns the year, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-01", * "2021-03-01", * "2020-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const year = df.dt.year() * console.log(year.values) * // [2019, 2019, 2021, 2020] * ``` */ - year() { - const newValues = this.$dateObjectArray.map((date) => date.getFullYear()); - return new Series(newValues); - } + year() { + const newValues = this.$dateObjectArray.map(date => date.getFullYear()) + return new Series(newValues); + } - /** + /** * Returns the name of the month, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-01", * "2021-03-01", * "2020-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const monthName = df.dt.monthName().values * console.log(monthName) * // ["January", "February", "March", "April"] * ``` */ - month_name() { - const newValues = this.$dateObjectArray.map((date) => MONTH_NAME[date.getMonth()]); - return new Series(newValues); - } + monthName() { + const newValues = this.$dateObjectArray.map(date => MONTH_NAME[date.getMonth()]) + return new Series(newValues); + } - /** + /** * Returns the name of the day, of the week, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-01", * "2021-03-01", * "2020-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const dayOfWeekName = df.dt.dayOfWeekName().values * console.log(dayOfWeekName) * ``` */ - weekdays() { - const newValues = this.$dateObjectArray.map((date) => WEEK_NAME[date.getDay()]); - return new Series(newValues); - } + dayOfWeekName() { + const newValues = this.$dateObjectArray.map(date => WEEK_NAME[date.getDay()]) + return new Series(newValues); + } - /** + /** * Returns the day of the month, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-05", * "2021-03-02", * "2020-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const dayOfMonth = df.dt.dayOfMonth().values * console.log(dayOfMonth) * // [1, 5, 2, 1] * ``` */ - monthday() { - const newValues = this.$dateObjectArray.map((date) => date.getDate()); - return new Series(newValues); - } + dayOfMonth() { + const newValues = this.$dateObjectArray.map(date => date.getDate()) + return new Series(newValues); + } - /** + /** * Returns the hour of the day, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-05", * "2021-03-02", * "2020-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const hour = df.dt.hour().values * console.log(hour) * // [0, 0, 0, 0] * ``` */ - hours() { - const newValues = this.$dateObjectArray.map((date) => date.getHours()); - return new Series(newValues); - } + hours() { + const newValues = this.$dateObjectArray.map(date => date.getHours()) + return new Series(newValues); + } - /** + /** * Returns the second of the day, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-05", * "2021-03-02", * "2020-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const second = df.dt.second().values * console.log(second) * ``` */ - seconds() { - const newValues = this.$dateObjectArray.map((date) => date.getSeconds()); - return new Series(newValues); - } + seconds() { + const newValues = this.$dateObjectArray.map(date => date.getSeconds()) + return new Series(newValues); + } - /** + /** * Returns the minute of the day, in local time * @example * ``` - * import { Dataframe } from "danfojs-node" + * import { Series } from "danfojs-node" * const data = [ * "2019-01-01", * "2019-02-05", * "2021-03-02", * "2020-04-01", * ] - * const df = new Dataframe(data) + * const df = new Series(data) * const minute = df.dt.minute().values * console.log(minute) * ``` */ - minutes() { - const newValues = this.$dateObjectArray.map((date) => date.getMinutes()); - return new Series(newValues); - } + minutes() { + const newValues = this.$dateObjectArray.map(date => date.getMinutes()) + return new Series(newValues); + } + + /** + * Returns the Date as JavaScript standard Date object + * @example + * ``` + * import { Series } from "danfojs-node" + * const data = [ + * "2019-01-01", + * "2019-02-05", + * "2021-03-02", + * "2020-04-01", + * ] + * + * const df = new Series(data) + * const date = df.dt.toDate().values + * console.log(date) + * ``` + */ + date() { + const newValues = this.$dateObjectArray.map(date => date.toLocaleString()) + return new Series(newValues); + } } -export const toDateTime = (data) => { - return new TimeSeries(data); +export const toDateTime = (data: Series | ArrayType1D) => { + return new TimeSeries(data); }; diff --git a/src/danfojs-base/core/frame.ts b/src/danfojs-base/core/frame.ts new file mode 100644 index 00000000..2f35c3d5 --- /dev/null +++ b/src/danfojs-base/core/frame.ts @@ -0,0 +1,3425 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import dummyEncode from "../transformers/encoders/dummy.encoder"; +import { variance, std, median, mode, mean } from 'mathjs'; +import tensorflow from '../shared/tensorflowlib' +import { DATA_TYPES } from '../shared/defaults'; +import { _genericMathOp } from "./math.ops"; +import Groupby from '../aggregators/groupby'; +import ErrorThrower from "../shared/errors" +import { _iloc, _loc } from "./indexing"; +import Utils from "../shared/utils" +import NDframe from "./generic"; +import { table } from "table"; +import Series from './series'; +import { + ArrayType1D, + ArrayType2D, + DataFrameInterface, + BaseDataOptionType, + IPlotlyLib, +} from "../shared/types"; +import { PlotlyLib } from "../../danfojs-base/plotting"; + +const utils = new Utils(); + +/** + * Two-dimensional ndarray with axis labels. + * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. + * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. + * @param data 2D Array, JSON, Tensor, Block of data. + * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. + * @param options.columns Array of column names. If not specified, column names are auto generated. + * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. + * @param options.config General configuration object for extending or setting NDframe behavior. + */ +export default class DataFrame extends NDframe implements DataFrameInterface { + [key: string]: any + constructor(data: any, options: BaseDataOptionType = {}) { + const { index, columns, dtypes, config } = options; + super({ data, index, columns, dtypes, config, isSeries: false }); + this.$setInternalColumnDataProperty(); + } + + /** + * Maps all column names to their corresponding data, and return them as Series objects. + * This makes column subsetting works. E.g this can work ==> `df["col1"]` + * @param column Optional, a single column name to map + */ + private $setInternalColumnDataProperty(column?: string) { + const self = this; + if (column && typeof column === "string") { + Object.defineProperty(self, column, { + get() { + return self.$getColumnData(column) + }, + set(arr: ArrayType1D | Series) { + self.$setColumnData(column, arr); + } + }) + } else { + const columns = this.columns; + for (let i = 0; i < columns.length; i++) { + const column = columns[i]; + Object.defineProperty(this, column, { + get() { + return self.$getColumnData(column) + }, + set(arr: ArrayType1D | Series) { + self.$setColumnData(column, arr); + } + }) + } + } + + } + + /** + * Returns the column data from the DataFrame by column name. + * @param column column name to get the column data + * @param returnSeries Whether to return the data in series format or not. Defaults to true + */ + private $getColumnData(column: string, returnSeries: boolean = true) { + const columnIndex = this.columns.indexOf(column) + + if (columnIndex == -1) { + ErrorThrower.throwColumnNotFoundError(this) + } + + const dtypes = [this.$dtypes[columnIndex]] + const index = [...this.$index] + const columns = [column] + const config = { ...this.$config } + + if (this.$config.isLowMemoryMode) { + const data: ArrayType1D = [] + for (let i = 0; i < this.values.length; i++) { + const row: any = this.values[i]; + data.push(row[columnIndex]) + } + if (returnSeries) { + return new Series(data, { + dtypes, + index, + columns, + config + }) + } else { + return data + } + + } else { + const data = this.$dataIncolumnFormat[columnIndex] + if (returnSeries) { + return new Series(data, { + dtypes, + index, + columns, + config + }) + } else { + return data + } + } + + } + + + /** + * Updates the internal column data via column name. + * @param column The name of the column to update. + * @param arr The new column data + */ + private $setColumnData(column: string, arr: ArrayType1D | Series): void { + + const columnIndex = this.$columns.indexOf(column) + + if (columnIndex == -1) { + throw new Error(`ParamError: column ${column} not found in ${this.$columns}. If you need to add a new column, use the df.addColumn method. `) + } + + let colunmValuesToAdd: ArrayType1D + + if (arr instanceof Series) { + colunmValuesToAdd = arr.values as ArrayType1D + } else if (Array.isArray(arr)) { + colunmValuesToAdd = arr; + } else { + throw new Error("ParamError: specified value not supported. It must either be an Array or a Series of the same length") + } + + if (colunmValuesToAdd.length !== this.shape[0]) { + ErrorThrower.throwColumnLengthError(this, colunmValuesToAdd.length) + } + + if (this.$config.isLowMemoryMode) { + //Update row ($data) array + for (let i = 0; i < this.$data.length; i++) { + (this.$data as any)[i][columnIndex] = colunmValuesToAdd[i] + } + //Update the dtypes + this.$dtypes[columnIndex] = utils.inferDtype(colunmValuesToAdd)[0] + } else { + //Update row ($data) array + for (let i = 0; i < this.values.length; i++) { + (this.$data as any)[i][columnIndex] = colunmValuesToAdd[i] + } + //Update column ($dataIncolumnFormat) array since it's available in object + (this.$dataIncolumnFormat as any)[columnIndex] = arr + + //Update the dtypes + this.$dtypes[columnIndex] = utils.inferDtype(colunmValuesToAdd)[0] + } + + } + + /** + * Return data with missing values removed from a specified axis + * @param axis 0 or 1. If 0, column-wise, if 1, row-wise + */ + private $getDataByAxisWithMissingValuesRemoved(axis: number): Array { + const oldValues = this.$getDataArraysByAxis(axis); + const cleanValues = []; + for (let i = 0; i < oldValues.length; i++) { + const values = oldValues[i] as number[] + cleanValues.push(utils.removeMissingValuesFromArray(values) as number[]); + } + return cleanValues; + } + + /** + * Return data aligned to the specified axis. Transposes the array if needed. + * @param axis 0 or 1. If 0, column-wise, if 1, row-wise + */ + private $getDataArraysByAxis(axis: number): ArrayType2D { + if (axis === 1) { + return this.values as ArrayType2D + } else { + let dfValues; + if (this.config.isLowMemoryMode) { + dfValues = utils.transposeArray(this.values) as ArrayType2D + } else { + dfValues = this.$dataIncolumnFormat as ArrayType2D + } + return dfValues + } + } + + /* + * checks if DataFrame is compactible for arithmetic operation + * compatible Dataframe must have only numerical dtypes + **/ + private $frameIsNotCompactibleForArithmeticOperation() { + const dtypes = this.dtypes; + const str = (element: any) => element == "string"; + return dtypes.some(str) + } + + /** + * Return Tensors in the right axis for math operations. + * @param other DataFrame or Series or number or array + * @param axis 0 or 1. If 0, column-wise, if 1, row-wise + * */ + private $getTensorsForArithmeticOperationByAxis( + other: DataFrame | Series | number | Array, + axis: number + ) { + if (typeof other === "number") { + return [this.tensor, tensorflow.scalar(other)]; + } else if (other instanceof DataFrame) { + return [this.tensor, other.tensor]; + } else if (other instanceof Series) { + if (axis === 0) { + return [this.tensor, tensorflow.tensor2d(other.values as Array, [other.shape[0], 1])]; + } else { + return [this.tensor, tensorflow.tensor2d(other.values as Array, [other.shape[0], 1]).transpose()]; + } + } else if (Array.isArray(other)) { + if (axis === 0) { + return [this.tensor, tensorflow.tensor2d(other, [other.length, 1])]; + } else { + return [this.tensor, tensorflow.tensor2d(other, [other.length, 1]).transpose()]; + } + } else { + throw new Error("ParamError: Invalid type for other parameter. other must be one of Series, DataFrame or number.") + } + + } + + /** + * Returns the dtype for a given column name + * @param column + */ + private $getColumnDtype(column: string): string { + const columnIndex = this.columns.indexOf(column) + if (columnIndex === -1) { + throw Error(`ColumnNameError: Column "${column}" does not exist`) + } + return this.dtypes[columnIndex] + } + + private $logicalOps(tensors: typeof tensorflow.Tensor[], operation: string) { + let newValues: number[] = [] + + switch (operation) { + case 'gt': + newValues = tensors[0].greater(tensors[1]).arraySync() as number[] + break; + case 'lt': + newValues = tensors[0].less(tensors[1]).arraySync() as number[] + break; + case 'ge': + newValues = tensors[0].greaterEqual(tensors[1]).arraySync() as number[] + break; + case 'le': + newValues = tensors[0].lessEqual(tensors[1]).arraySync() as number[] + break; + case 'eq': + newValues = tensors[0].equal(tensors[1]).arraySync() as number[] + break; + case 'ne': + newValues = tensors[0].notEqual(tensors[1]).arraySync() as number[] + break; + + } + + const newData = utils.mapIntegersToBooleans(newValues, 2) + return new DataFrame( + newData, + { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + + private $MathOps(tensors: typeof tensorflow.Tensor[], operation: string, inplace: boolean) { + let tensorResult + + switch (operation) { + case 'add': + tensorResult = tensors[0].add(tensors[1]) + break; + case 'sub': + tensorResult = tensors[0].sub(tensors[1]) + break; + case 'pow': + tensorResult = tensors[0].pow(tensors[1]) + break; + case 'div': + tensorResult = tensors[0].div(tensors[1]) + break; + case 'divNoNan': + tensorResult = tensors[0].divNoNan(tensors[1]) + break; + case 'mul': + tensorResult = tensors[0].mul(tensors[1]) + break; + case 'mod': + tensorResult = tensors[0].mod(tensors[1]) + break; + } + + if (inplace) { + const newData = tensorResult?.arraySync() as ArrayType2D + this.$setValues(newData) + } else { + return new DataFrame( + tensorResult, + { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + + } + } + + /** + * Purely integer-location based indexing for selection by position. + * ``.iloc`` is primarily integer position based (from ``0`` to + * ``length-1`` of the axis), but may also be used with a boolean array. + * + * @param rows Array of row indexes + * @param columns Array of column indexes + * + * Allowed inputs are in rows and columns params are: + * + * - An array of single integer, e.g. ``[5]``. + * - A list or array of integers, e.g. ``[4, 3, 0]``. + * - A slice array string with ints, e.g. ``["1:7"]``. + * - A boolean array. + * - A ``callable`` function with one argument (the calling Series or + * DataFrame) and that returns valid output for indexing (one of the above). + * This is useful in method chains, when you don't have a reference to the + * calling object, but would like to base your selection on some value. + * + * ``.iloc`` will raise ``IndexError`` if a requested indexer is + * out-of-bounds. + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.iloc({ rows: [1], columns: ["A"] }) + * ``` + */ + iloc({ rows, columns }: { + rows?: Array | Series, + columns?: Array + }): DataFrame { + return _iloc({ ndFrame: this, rows, columns }) as DataFrame; + } + + + /** + * Access a group of rows and columns by label(s) or a boolean array. + * ``loc`` is primarily label based, but may also be used with a boolean array. + * + * @param rows Array of row indexes + * @param columns Array of column indexes + * + * Allowed inputs are: + * + * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a + * *label* of the index, and **never** as an integer position along the index). + * + * - A list or array of labels, e.g. ``['a', 'b', 'c']``. + * + * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included + * + * - A boolean array of the same length as the axis being sliced, + * e.g. ``[True, False, True]``. + * + * - A ``callable`` function with one argument (the calling Series or + * DataFrame) and that returns valid output for indexing (one of the above) + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.loc({ rows: [1], columns: ["A"] }) + * ``` + */ + loc({ rows, columns }: { + rows?: Array | Series, + columns?: Array + }): DataFrame { + return _loc({ ndFrame: this, rows, columns }) as DataFrame + } + + /** + * Prints DataFrame to console as a formatted grid of row and columns. + */ + toString(): string { + const maxRow = this.config.getMaxRow; + const maxColToDisplayInConsole = this.config.getTableMaxColInConsole; + + // let data; + const dataArr: ArrayType2D = []; + const colLen = this.columns.length; + + let header = []; + + if (colLen > maxColToDisplayInConsole) { + //truncate displayed columns to fit in the console + let firstFourcolNames = this.columns.slice(0, 4); + let lastThreecolNames = this.columns.slice(colLen - 3); + //join columns with truncate ellipse in the middle + header = ["", ...firstFourcolNames, "...", ...lastThreecolNames]; + + let subIdx: Array + let firstHalfValues: ArrayType2D + let lastHalfValueS: ArrayType2D + + if (this.values.length > maxRow) { + //slice Object to show [max_rows] + let dfSubset1 = this.iloc({ + rows: [`0:${maxRow}`], + columns: ["0:4"] + }); + + let dfSubset2 = this.iloc({ + rows: [`0:${maxRow}`], + columns: [`${colLen - 3}:`] + }); + + subIdx = this.index.slice(0, maxRow); + firstHalfValues = dfSubset1.values as ArrayType2D + lastHalfValueS = dfSubset2.values as ArrayType2D + + } else { + let dfSubset1 = this.iloc({ columns: ["0:4"] }); + let dfSubset2 = this.iloc({ columns: [`${colLen - 3}:`] }); + + subIdx = this.index.slice(0, maxRow); + firstHalfValues = dfSubset1.values as ArrayType2D + lastHalfValueS = dfSubset2.values as ArrayType2D + } + + // merge subset + for (let i = 0; i < subIdx.length; i++) { + const idx = subIdx[i]; + const row = [idx, ...firstHalfValues[i], "...", ...lastHalfValueS[i]] + dataArr.push(row); + } + + } else { + //display all columns + header = ["", ...this.columns] + let subIdx + let values: ArrayType2D + if (this.values.length > maxRow) { + //slice Object to show a max of [max_rows] + let data = this.iloc({ rows: [`0:${maxRow}`] }); + subIdx = data.index; + values = data.values as ArrayType2D + } else { + values = this.values as ArrayType2D + subIdx = this.index; + } + + // merge subset + for (let i = 0; i < subIdx.length; i++) { + const idx = subIdx[i]; + const row = [idx, ...values[i]]; + dataArr.push(row); + } + } + + + const columnsConfig: any = {}; + columnsConfig[0] = { width: 10 }; //set column width for index column + + for (let index = 1; index < header.length; index++) { + columnsConfig[index] = { width: 17, truncate: 16 }; + } + + const tableData: any = [header, ...dataArr]; //Adds the column names to values before printing + + return table(tableData, { columns: columnsConfig, ...this.config.getTableDisplayConfig }); + } + + /** + * Returns the first n values in a DataFrame + * @param rows The number of rows to return + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.head(1) + * ``` + */ + head(rows: number = 5): DataFrame { + + if (rows <= 0) { + throw new Error("ParamError: Number of rows cannot be less than 1") + } + if (this.shape[0] <= rows) { + return this.copy() + } + if (this.shape[0] - rows < 0) { + throw new Error("ParamError: Number of rows cannot be greater than available rows in data") + } + + return this.iloc({ rows: [`0:${rows}`] }) + } + + /** + * Returns the last n values in a DataFrame + * @param rows The number of rows to return + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.tail(1) + * ``` + */ + tail(rows: number = 5): any { + + if (rows <= 0) { + throw new Error("ParamError: Number of rows cannot be less than 1") + } + if (this.shape[0] <= rows) { + return this.copy() + } + if (this.shape[0] - rows < 0) { + throw new Error("ParamError: Number of rows cannot be greater than available rows in data") + } + + rows = this.shape[0] - rows + return this.iloc({ rows: [`${rows}:`] }) + } + + /** + * Gets n number of random rows in a dataframe. Sample is reproducible if seed is provided. + * @param num The number of rows to return. Default to 5. + * @param options.seed An integer specifying the random seed that will be used to create the distribution. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = await df.sample(1) + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = await df.sample(1, { seed: 1 }) + * ``` + */ + async sample(num = 5, options?: { seed?: number }): Promise { + const { seed } = { seed: 1, ...options } + + if (num > this.shape[0]) { + throw new Error("ParamError: Sample size cannot be bigger than number of rows"); + } + if (num <= 0) { + throw new Error("ParamError: Sample size cannot be less than 1"); + } + + const shuffledIndex = await tensorflow.data.array(this.index).shuffle(num, `${seed}`).take(num).toArray(); + const df = this.iloc({ rows: shuffledIndex }); + return df; + } + + /** + * Return Addition of DataFrame and other, element-wise (binary operator add). + * @param other DataFrame, Series, Array or Scalar number to add + * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.add(1) + * df2.print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * df.add([1, 2], { axis: 0, inplace: true}) + * df.print() + * ``` + */ + add(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + add(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: add operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "add", inplace) + } + + /** + * Return substraction between DataFrame and other. + * @param other DataFrame, Series, Array or Scalar number to substract from DataFrame + * @param options.axis 0 or 1. If 0, compute the subtraction column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.sub(1) + * df2.print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * df.sub([1, 2], { axis: 0, inplace: true}) + * df.print() + * ``` + */ + sub(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + sub(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: sub operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "sub", inplace) + + + } + /** + * Return multiplciation between DataFrame and other. + * @param other DataFrame, Series, Array or Scalar number to multiply with. + * @param options.axis 0 or 1. If 0, compute the multiplication column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.mul(2) + * df2.print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * df.mul([1, 2], { axis: 0, inplace: true}) + * df.print() + * ``` + */ + mul(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + mul(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: mul operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "mul", inplace) + + + } + + /** + * Return division of DataFrame with other. + * @param other DataFrame, Series, Array or Scalar number to divide with. + * @param options.axis 0 or 1. If 0, compute the division column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.div(2) + * df2.print() + * ``` + */ + div(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + div(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: div operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "div", inplace) + + + } + + /** + * Return division of DataFrame with other, returns 0 if denominator is 0. + * @param other DataFrame, Series, Array or Scalar number to divide with. + * @param options.axis 0 or 1. If 0, compute the division column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.divNoNan(2) + * df2.print() + * ``` + */ + divNoNan(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + divNoNan(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: div operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "divNoNan", inplace) + + + } + + /** + * Return DataFrame raised to the power of other. + * @param other DataFrame, Series, Array or Scalar number to to raise to. + * @param options.axis 0 or 1. If 0, compute the power column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.pow(2) + * df2.print() + * ``` + */ + pow(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + pow(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: pow operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "pow", inplace) + + + } + + /** + * Return modulus between DataFrame and other. + * @param other DataFrame, Series, Array or Scalar number to modulus with. + * @param options.axis 0 or 1. If 0, compute the mod column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * const df2 = df.mod(2) + * df2.print() + * ``` + */ + mod(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + mod(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: mod operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "mod", inplace) + + } + + /** + * Return mean of DataFrame across specified axis. + * @param options.axis 0 or 1. If 0, compute the mean column-wise, if 1, row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * df.mean().print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B'] }) + * df.mean({ axis: 0 }).print() + * ``` + */ + mean(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: mean operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + const resultArr = newData.map(arr => arr.reduce((a, b) => a + b, 0) / arr.length) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + } + + /** + * Return median of DataFrame across specified axis. + * @param options.axis 0 or 1. If 0, compute the median column-wise, if 1, row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2, 4], [3, 4, 5], [6, 7, 8]], { columns: ['A', 'B', 'C'] }); + * df.median().print() + * ``` + */ + median(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: median operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + const resultArr = newData.map(arr => median(arr)) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + + } + + /** + * Return mode of DataFrame across specified axis. + * @param options.axis 0 or 1. If 0, compute the mode column-wise, if 1, row-wise. Defaults to 1 + * @param options.keep If there are more than one modes, returns the mode at position [keep]. Defaults to 0 + * @example + * ``` + * const df = new DataFrame([[1, 2, 4], [3, 4, 5], [6, 7, 8]], { columns: ['A', 'B', 'C'] }); + * df.mode().print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2, 4], [3, 4, 5], [6, 7, 8]], { columns: ['A', 'B', 'C'] }); + * df.mode({ keep: 1 }).print() + * ``` + */ + mode(options?: { axis?: 0 | 1, keep?: number }): Series { + const { axis, keep } = { axis: 1, keep: 0, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: mode operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + const resultArr = newData.map(arr => { + const tempMode = mode(arr) + if (tempMode.length === 1) { + return tempMode[0] + } else { + return tempMode[keep] + } + }) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + + } + + /** + * Return minimum of values in a DataFrame across specified axis. + * @param options.axis 0 or 1. If 0, compute the minimum value column-wise, if 1, row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.min().print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.min({ axis: 0 }).print() + * ``` + */ + min(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: min operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + + const resultArr = newData.map(arr => { + let smallestValue = arr[0] + for (let i = 0; i < arr.length; i++) { + smallestValue = smallestValue < arr[i] ? smallestValue : arr[i] + } + return smallestValue + }) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + } + + /** + * Return maximum of values in a DataFrame across specified axis. + * @param options.axis 0 or 1. If 0, compute the maximum column-wise, if 1, row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.max().print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.max({ axis: 0 }).print() + * ``` + */ + max(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: max operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + + const resultArr = newData.map(arr => { + let biggestValue = arr[0] + for (let i = 0; i < arr.length; i++) { + biggestValue = biggestValue > arr[i] ? biggestValue : arr[i] + } + return biggestValue + }) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + + } + + /** + * Return standard deviation of values in a DataFrame across specified axis. + * @param options.axis 0 or 1. If 0, compute the standard deviation column-wise, if 1, row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.std().print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.std({ axis: 0 }).print() + * ``` + */ + std(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: std operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + const resultArr = newData.map(arr => std(arr)) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + + } + + /** + * Return variance of values in a DataFrame across specified axis. + * @param options.axis 0 or 1. If 0, compute the variance column-wise, if 1, add row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.var().print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.var({ axis: 0 }).print() + * ``` + */ + var(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: var operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + const resultArr = newData.map(arr => variance(arr)) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + + } + + /** + * Get Less than of dataframe and other, element-wise (binary operator lt). + * @param other DataFrame, Series, Array or Scalar number to compare with + * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.lt(2).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.lt([2, 3], { axis: 0 }).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const sf = new Series([2, 3]) + * df.lt(sf, { axis: 1 }).print() + * ``` + */ + lt(other: DataFrame | Series | number | Array, options?: { axis?: 0 | 1 }): DataFrame { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: lt operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$logicalOps(tensors, "lt") + } + + /** + * Returns "greater than" of dataframe and other. + * @param other DataFrame, Series, Array or Scalar number to compare with + * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.gt(2).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.gt([2, 3], { axis: 0 }).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const sf = new Series([2, 3]) + * df.gt(sf, { axis: 1 }).print() + * ``` + */ + gt(other: DataFrame | Series | number | Array, options?: { axis?: 0 | 1 }): DataFrame { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: gt operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$logicalOps(tensors, "gt") + } + + /** + * Returns "equals to" of dataframe and other. + * @param other DataFrame, Series, Array or Scalar number to compare with + * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.eq(2).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.eq([2, 3], { axis: 0 }).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const sf = new Series([2, 3]) + * df.eq(sf, { axis: 1 }).print() + * ``` + */ + eq(other: DataFrame | Series | number | Array, options?: { axis?: 0 | 1 }): DataFrame { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: eq operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$logicalOps(tensors, "eq") + } + + /** + * Returns "not equal to" of dataframe and other. + * @param other DataFrame, Series, Array or Scalar number to compare with + * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.ne(2).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.ne([2, 3], { axis: 0 }).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const sf = new Series([2, 3]) + * df.ne(sf, { axis: 1 }).print() + * ``` + */ + ne(other: DataFrame | Series | number | Array, options?: { axis?: 0 | 1 }): DataFrame { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: ne operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$logicalOps(tensors, "ne") + } + + /** + * Returns "less than or equal to" of dataframe and other. + * @param other DataFrame, Series, Array or Scalar number to compare with + * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.le(2).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.le([2, 3], { axis: 0 }).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const sf = new Series([2, 3]) + * df.le(sf, { axis: 1 }).print() + * ``` + */ + le(other: DataFrame | Series | number | Array, options?: { axis?: 0 | 1 }): DataFrame { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: le operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$logicalOps(tensors, "le") + } + + /** + * Returns "greater than or equal to" between dataframe and other. + * @param other DataFrame, Series, Array or Scalar number to compare with + * @param options.axis 0 or 1. If 0, add column-wise, if 1, add row-wise + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.ge(2).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.ge([2, 3], { axis: 0 }).print() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const sf = new Series([2, 3]) + * df.ge(sf, { axis: 1 }).print() + * ``` + */ + ge(other: DataFrame | Series | number | Array, options?: { axis?: 0 | 1 }): DataFrame { + const { axis } = { axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: ge operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$logicalOps(tensors, "ge") + } + + /** + * Return number of non-null elements in a Series + * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.count().print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.count({ axis: 0 }).print() + * ``` + */ + count(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newData = this.$getDataByAxisWithMissingValuesRemoved(axis) + const resultArr = newData.map(arr => arr.length) + if (axis === 0) { + return new Series(resultArr, { index: this.columns }); + } else { + return new Series(resultArr, { index: this.index }); + } + + } + + /** + * Return the sum of values across an axis. + * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.sum().print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.sum({ axis: 0 }).print() + * ``` + */ + sum(options?: { axis?: 0 | 1 }): Series { + const { axis } = { axis: 1, ...options } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const result = this.$getDataByAxisWithMissingValuesRemoved(axis) + const sumArr = result.map((innerArr) => { + return innerArr.reduce((a, b) => Number(a) + Number(b), 0) + }) + if (axis === 0) { + return new Series(sumArr, { + index: [...this.columns] + }) + } else { + return new Series(sumArr, { + index: [...this.index] + }) + } + + } + + /** + * Return percentage difference of DataFrame with other. + * @param other DataFrame, Series, Array or Scalar number (positive numbers are preceding rows, negative are following rows) to compare difference with. + * @param options.axis 0 or 1. If 0, compute the difference column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2, 3, 4, 5, 6], [1, 1, 2, 3, 5, 8], [1, 4, 9, 16, 25, 36]], { columns: ['A', 'B', 'C'] }) + * + * // Percentage difference with previous row + * const df0 = df.pctChange(1) + * console.log(df0) + * + * // Percentage difference with previous column + * const df1 = df.pctChange(1, {axis: 0}) + * console.log(df1) + * + * // Percentage difference with previous 3rd previous row + * const df2 = df.pctChange(3) + * console.log(df2) + * + * // Percentage difference with following row + * const df3 = df.pctChange(-1) + * console.log(df3) + * + * // Percentage difference with another DataFrame + * const df4 = df.pctChange(df3) + * console.log(df4) + * ``` + */ + pctChange(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + pctChange(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: pctChange operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + if (other === 0) { + return this; + } + + if (typeof other === "number") { + let origDF = this.copy() as DataFrame; + if (axis === 0) { + origDF = origDF.T; + } + const originalTensor = origDF.tensor.clone(); + const unit = new Array(originalTensor.shape[originalTensor.rank - 1]).fill(NaN); + let pctArray: any[] = originalTensor.arraySync(); + if (other > 0) { + for (let i = 0; i < other; i++) { + pctArray.unshift(unit); + pctArray.pop(); + } + } + else if (other < 0) { + for (let i = 0; i > other; i--) { + pctArray.push(unit); + pctArray.shift(); + } + } + const pctTensor = tensorflow.tensor2d(pctArray, originalTensor.shape); + const pctDF = (this.$MathOps([originalTensor, pctTensor], "divNoNan", inplace) as DataFrame).sub(1); + if (axis === 0) { + return pctDF.T; + } + return pctDF; + } + + if (other instanceof DataFrame || other instanceof Series) { + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + const pctDF = (this.$MathOps(tensors, "divNoNan", inplace) as DataFrame).sub(1); + return pctDF; + } + } + + /** + * Return difference of DataFrame with other. + * @param other DataFrame, Series, Array or Scalar number (positive numbers are preceding rows, negative are following rows) to compare difference with. + * @param options.axis 0 or 1. If 0, compute the difference column-wise, if 1, row-wise + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2, 3, 4, 5, 6], [1, 1, 2, 3, 5, 8], [1, 4, 9, 16, 25, 36]], { columns: ['A', 'B', 'C'] }) + * + * // Difference with previous row + * const df0 = df.diff(1) + * console.log(df0) + * + * // Difference with previous column + * const df1 = df.diff(1, {axis: 0}) + * console.log(df1) + * + * // Difference with previous 3rd previous row + * const df2 = df.diff(3) + * console.log(df2) + * + * // Difference with following row + * const df3 = df.diff(-1) + * console.log(df3) + * + * // Difference with another DataFrame + * const df4 = df.diff(df3) + * console.log(df4) + * ``` + */ + diff(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + diff(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { inplace, axis } = { inplace: false, axis: 1, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: diff operation is not supported for string dtypes"); + } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + if (other === 0) { + return this; + } + + if (typeof other === "number") { + let origDF = this.copy() as DataFrame; + if (axis === 0) { + origDF = origDF.T; + } + const originalTensor = origDF.tensor.clone(); + const unit = new Array(originalTensor.shape[originalTensor.rank - 1]).fill(NaN); + let diffArray: any[] = originalTensor.arraySync(); + if (other > 0) { + for (let i = 0; i < other; i++) { + diffArray.unshift(unit); + diffArray.pop(); + } + } + else if (other < 0) { + for (let i = 0; i > other; i--) { + diffArray.push(unit); + diffArray.shift(); + } + } + const diffTensor = tensorflow.tensor2d(diffArray, originalTensor.shape); + const diffDF = this.$MathOps([originalTensor, diffTensor], "sub", inplace) as DataFrame; + if (axis === 0) { + return diffDF.T; + } + return diffDF; + } + + if (other instanceof DataFrame || other instanceof Series) { + const tensors = this.$getTensorsForArithmeticOperationByAxis(other, axis); + return this.$MathOps(tensors, "sub", inplace); + } + } + + /** + * Return the absolute value of elements in a DataFrame. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1.0, 2.1], [3.1, 4]], { columns: ['A', 'B']}) + * df.abs().print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1.0, 2], [3.3, 4]], { columns: ['A', 'B']}) + * df.abs({ inplace: true }).print() + * ``` + */ + abs(options?: { inplace?: boolean }): DataFrame + abs(options?: { inplace?: boolean }): DataFrame | void { + const { inplace } = { inplace: false, ...options } + + const newData = (this.values as number[][]).map(arr => arr.map(val => Math.abs(val))) + if (inplace) { + this.$setValues(newData) + } else { + return new DataFrame(newData, { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + } + + /** + * Rounds all element in the DataFrame to specified number of decimal places. + * @param dp Number of decimal places to round to. Defaults to 1 + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1.12, 2.34], [3.43, 4.0]], { columns: ['A', 'B']}) + * const df2 = df.round(2) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1.12, 2.34], [3.43, 4.0]], { columns: ['A', 'B']}) + * df.round(2, { inplace: true }).print() + * ``` + */ + round(dp: number, options?: { inplace: boolean }): DataFrame + round(dp: number = 1, options?: { inplace: boolean }): DataFrame | void { + const { inplace } = { inplace: false, ...options } + + if (this.$frameIsNotCompactibleForArithmeticOperation()) { + throw Error("TypeError: round operation is not supported for string dtypes"); + } + + if (typeof dp !== "number") { + throw Error("ParamError: dp must be a number"); + } + + const newData = utils.round(this.values as number[], dp, false); + + if (inplace) { + this.$setValues(newData) + } else { + return new DataFrame( + newData, + { + index: [...this.index], + columns: [...this.columns], + config: { ...this.config } + }) + } + } + + /** + * Returns cumulative product accross specified axis. + * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumprod() + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumprod({ axis: 0 }) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.cumprod({ axis: 0, inplace: true }).print() + * ``` + */ + cumProd(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + cumProd(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { axis, inplace } = { axis: 1, inplace: false, ...options } + return this.cumOps("prod", axis, inplace); + } + + /** + * Returns cumulative sum accross specified axis. + * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumSum() + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumSum({ axis: 0 }) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.cumSum({ axis: 0, inplace: true }).print() + * ``` + */ + cumSum(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + cumSum(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { axis, inplace } = { axis: 1, inplace: false, ...options } + return this.cumOps("sum", axis, inplace); + } + + /** + * Returns cumulative minimum accross specified axis. + * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumMin() + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumMin({ axis: 0 }) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.cumMin({ axis: 0, inplace: true }).print() + * ``` + */ + cumMin(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + cumMin(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { axis, inplace } = { axis: 1, inplace: false, ...options } + return this.cumOps("min", axis, inplace); + } + + /** + * Returns cumulative maximum accross specified axis. + * @param options.axis 0 or 1. If 0, count column-wise, if 1, add row-wise. Defaults to 1 + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumMax() + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.cumMax({ axis: 0 }) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.cumMax({ axis: 0, inplace: true }).print() + * ``` + */ + cumMax(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame + cumMax(options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void { + const { axis, inplace } = { axis: 1, inplace: false, ...options } + return this.cumOps("max", axis, inplace); + } + + /** + * Internal helper function for cumulative operation on DataFrame + */ + private cumOps(ops: string, axis: number, inplace: boolean): DataFrame + private cumOps(ops: string, axis: number, inplace: boolean): DataFrame | void { + if (this.dtypes.includes("string")) ErrorThrower.throwStringDtypeOperationError(ops) + + const result = this.$getDataByAxisWithMissingValuesRemoved(axis) + + let newData: ArrayType2D = result.map((sData) => { + let tempval = sData[0]; + const data = [tempval]; + + for (let i = 1; i < sData.length; i++) { + let currVal = sData[i]; + switch (ops) { + case "max": + if (currVal > tempval) { + data.push(currVal); + tempval = currVal; + } else { + data.push(tempval); + } + break; + case "min": + if (currVal < tempval) { + data.push(currVal); + tempval = currVal; + } else { + data.push(tempval); + } + break; + case "sum": + tempval = (tempval as number) + (currVal as number) + data.push(tempval); + break; + case "prod": + tempval = (tempval as number) * (currVal as number) + data.push(tempval); + break; + + } + } + return data; + }) + + if (axis === 0) { + newData = utils.transposeArray(newData) as ArrayType2D + } + + if (inplace) { + this.$setValues(newData) + } else { + return new DataFrame(newData, { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + } + + /** + * Generate descriptive statistics for all numeric columns. + * Descriptive statistics include those that summarize the central tendency, + * dispersion and shape of a dataset’s distribution, excluding NaN values. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.describe().print() + * ``` + */ + describe(): DataFrame { + const numericColumnNames = this.columns.filter(name => this.$getColumnDtype(name) !== "string") + const index = ["count", "mean", "std", "min", "median", "max", "variance"]; + const statsObject: any = {}; + for (let i = 0; i < numericColumnNames.length; i++) { + const colName = numericColumnNames[i]; + const $count = (this.$getColumnData(colName) as Series).count(); + const $mean = mean(this.$getColumnData(colName, false) as number[]); + const $std = std(this.$getColumnData(colName, false) as number[]); + const $min = (this.$getColumnData(colName) as Series).min(); + const $median = median(this.$getColumnData(colName, false) as number[]); + const $max = (this.$getColumnData(colName) as Series).max(); + const $variance = variance(this.$getColumnData(colName, false) as number[]); + + const stats = [$count, $mean, $std, $min, $median, $max, $variance]; + statsObject[colName] = stats; + + } + + const df = new DataFrame(statsObject, { index }); + return df + } + + /** + * Drops all rows or columns with missing values (NaN) + * @param axis 0 or 1. If 0, drop columns with NaNs, if 1, drop rows with NaNs + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [NaN, NaN]], { columns: ['A', 'B']}) + * const df2 = df.dropna() + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [NaN, NaN]], { columns: ['A', 'B']}) + * df.dropna({ axis: 0, inplace: true }).print() + * ``` + */ + dropNa(options?: { axis: 0 | 1, inplace?: boolean }): DataFrame + dropNa(options?: { axis: 0 | 1, inplace?: boolean }): DataFrame | void { + const { axis, inplace } = { axis: 1, inplace: false, ...options } + + if ([0, 1].indexOf(axis) === -1) { + throw Error("ParamError: Axis must be 0 or 1"); + } + + const newIndex: Array = []; + + if (axis == 1) { + const newData = []; + + const dfValues = this.values as ArrayType2D; + for (let i = 0; i < dfValues.length; i++) { + const values: ArrayType1D = dfValues[i]; + //@ts-ignore + if (!values.includes(NaN) && !values.includes(undefined) && !values.includes(null)) { + newData.push(values); + newIndex.push(this.index[i]) + } + } + + if (inplace) { + this.$setValues(newData, false) + this.$setIndex(newIndex) + } else { + return new DataFrame( + newData, + { + index: newIndex, + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + + } else { + const newColumnNames = [] + const newDtypes = [] + let dfValues: ArrayType2D = [] + + if (this.config.isLowMemoryMode) { + dfValues = utils.transposeArray(this.values) as ArrayType2D + } else { + dfValues = this.$dataIncolumnFormat as ArrayType2D + } + const tempColArr = [] + + for (let i = 0; i < dfValues.length; i++) { + const values: ArrayType1D = dfValues[i]; + if (!values.includes(NaN)) { + tempColArr.push(values); + newColumnNames.push(this.columns[i]) + newDtypes.push(this.dtypes[i]) + } + } + + const newData = utils.transposeArray(tempColArr) as ArrayType2D + + if (inplace) { + this.$setValues(newData, false, false) + this.$setColumnNames(newColumnNames) + this.$setDtypes(newDtypes) + } else { + return new DataFrame( + newData, + { + index: [...this.index], + columns: newColumnNames, + dtypes: newDtypes, + config: { ...this.config } + }) + } + } + + } + + /** + * Adds a new column to the DataFrame. If column exists, then the column values is replaced. + * @param column The name of the column to add or replace. + * @param values An array of values to be inserted into the DataFrame. Must be the same length as the columns + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @param options.atIndex Column index to insert after. Defaults to the end of the columns. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.addColumn('C', [5, 6]) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.addColumn('C', [5, 6], { inplace: true }).print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.addColumn('C', [5, 6], { inplace: true, atIndex: 0 }).print() + * ``` + */ + addColumn( + column: string, + values: Series | ArrayType1D, + options?: { inplace?: boolean, atIndex?: number | string } + ): DataFrame + addColumn( + column: string, + values: Series | ArrayType1D, + options?: { inplace?: boolean, atIndex?: number | string } + ): DataFrame | void { + let { inplace, atIndex } = { inplace: false, atIndex: this.columns.length, ...options }; + if (typeof atIndex === "string") { + if (!(this.columns.includes(atIndex))) { + throw new Error(`${atIndex} not a column`) + } + atIndex = this.columns.indexOf(atIndex) + } + + if (!column) { + throw new Error("ParamError: column must be specified") + } + + if (!values) { + throw new Error("ParamError: values must be specified") + } + + const columnIndex = this.$columns.indexOf(column) + + if (columnIndex === -1) { + let colunmValuesToAdd: ArrayType1D + + if (values instanceof Series) { + colunmValuesToAdd = values.values as ArrayType1D + } else if (Array.isArray(values)) { + colunmValuesToAdd = values; + } else { + throw new Error("ParamError: specified value not supported. It must either be an Array or a Series of the same length") + } + + if (colunmValuesToAdd.length !== this.shape[0]) { + ErrorThrower.throwColumnLengthError(this, colunmValuesToAdd.length) + } + + const newData = [] + const oldValues = this.$data + for (let i = 0; i < oldValues.length; i++) { + const innerArr = [...oldValues[i]] as ArrayType1D + innerArr.splice(atIndex, 0, colunmValuesToAdd[i]) + newData.push(innerArr) + } + + if (inplace) { + this.$setValues(newData, true, false) + let columns = [...this.columns] + columns.splice(atIndex, 0, column) + this.$setColumnNames(columns) + this.$setInternalColumnDataProperty(column); + + } else { + let columns = [...this.columns] + columns.splice(atIndex, 0, column) + + const df = new DataFrame(newData, { + index: [...this.index], + columns: columns, + dtypes: [...this.dtypes, utils.inferDtype(colunmValuesToAdd)[0]], + config: { ...this.$config } + }) + return df + } + } else { + this.$setColumnData(column, values); + } + + } + + /** + * Makes a deep copy of a DataFrame. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.copy() + * df2.print() + * ``` + */ + copy(): DataFrame { + let df = new DataFrame([...this.$data], { + columns: [...this.columns], + index: [...this.index], + dtypes: [...this.dtypes], + config: { ...this.$config } + }); + return df; + } + + /** + * Return a boolean, same-sized object indicating where elements are empty (NaN, undefined, null). + * NaN, undefined and null values gets mapped to true, and everything else gets mapped to false. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.isNa().print() + * ``` + */ + isNa(): DataFrame { + const newData = [] + for (let i = 0; i < this.values.length; i++) { + const valueArr = this.values[i] as ArrayType1D + const tempData = valueArr.map((value) => { + if (utils.isEmpty(value)) { + return true; + } else { + return false; + } + }) + newData.push(tempData) + } + + const df = new DataFrame(newData, + { + index: [...this.index], + columns: [...this.columns], + config: { ...this.config } + }); + return df; + } + + /** + * Replace all empty elements with a specified value. Replace params expect columns array to map to values array. + * @param values The list of values to use for replacement. + * @param options.columns The list of column names to be replaced. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [NaN, NaN]], { columns: ['A', 'B']}) + * const df2 = df.fillNa(-99) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [NaN, NaN]], { columns: ['A', 'B']}) + * df.fillNa(-99, { inplace: true }).print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [NaN, NaN]], { columns: ['A', 'B']}) + * df.fillNa(-99, { columns: ["A"], inplace: true }).print() + * ``` + * + */ + fillNa( + values: number | string | boolean | ArrayType1D, + options?: + { + columns?: Array, + inplace?: boolean + } + ): DataFrame + fillNa( + values: number | string | boolean | ArrayType1D, + options?: + { + columns?: Array, + inplace?: boolean + } + ): DataFrame | void { + let { columns, inplace } = { inplace: false, ...options } + + if (!values && typeof values !== "boolean" && typeof values !== "number" && typeof values !== "string") { + throw Error('ParamError: value must be specified'); + } + + if (Array.isArray(values)) { + if (!Array.isArray(columns)) { + throw Error('ParamError: value is an array, hence columns must also be an array of same length'); + } + + if (values.length !== columns.length) { + throw Error('ParamError: specified column and values must have the same length'); + } + + columns.forEach((col) => { + if (!this.columns.includes(col)) { + throw Error( + `ValueError: Specified column "${col}" must be one of ${this.columns}` + ); + } + }); + } + + const newData = [] + const oldValues = [...this.values] + + if (!columns) { + //Fill all columns + for (let i = 0; i < oldValues.length; i++) { + const valueArr = [...oldValues[i] as ArrayType1D] + + const tempArr = valueArr.map((innerVal) => { + if (utils.isEmpty(innerVal)) { + const replaceWith = Array.isArray(values) ? values[i] : values + return replaceWith + } else { + return innerVal + } + }) + newData.push(tempArr) + } + + } else { + //Fill specific columns + const tempData = [...this.values] + + for (let i = 0; i < tempData.length; i++) { + const valueArr = tempData[i] as ArrayType1D + + for (let i = 0; i < columns.length; i++) { //B + const columnIndex = this.columns.indexOf(columns[i]) + const replaceWith = Array.isArray(values) ? values[i] : values + valueArr[columnIndex] = utils.isEmpty(valueArr[columnIndex]) ? replaceWith : valueArr[columnIndex] + } + newData.push(valueArr) + } + } + + if (inplace) { + this.$setValues(newData as ArrayType2D) + } else { + const df = new DataFrame(newData, + { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }); + return df; + } + } + + /** + * Drop specified columns or rows. + * @param options.columns Array of column names to drop. + * @param options.index Array of index to drop. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.drop({ columns: ['A'] }) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.drop({ index: [0], inplace: true }).print() + * ``` + */ + drop(options?: + { + columns?: string | Array, + index?: Array, + inplace?: boolean + } + ): DataFrame + drop(options?: + { + columns?: string | Array, + index?: Array, + inplace?: boolean + } + ): DataFrame | void { + let { columns, index, inplace } = { inplace: false, ...options } + + if (!columns && !index) { + throw Error('ParamError: Must specify one of columns or index'); + } + + if (columns && index) { + throw Error('ParamError: Can only specify one of columns or index'); + } + + if (columns) { + const columnIndices: Array = [] + + if (typeof columns === "string") { + columnIndices.push(this.columns.indexOf(columns)) + } else if (Array.isArray(columns)) { + for (let column of columns) { + if (this.columns.indexOf(column) === -1) { + throw Error(`ParamError: specified column "${column}" not found in columns`); + } + columnIndices.push(this.columns.indexOf(column)) + } + + } else { + throw Error('ParamError: columns must be an array of column names or a string of column name'); + } + + let newRowData: ArrayType2D = [] + let newColumnNames = [] + let newDtypes = [] + + for (let i = 0; i < this.values.length; i++) { + const tempInnerArr = [] + const innerArr = this.values[i] as ArrayType1D + for (let j = 0; j < innerArr.length; j++) { + if (!(columnIndices.includes(j))) { + tempInnerArr.push(innerArr[j]) + } + } + newRowData.push(tempInnerArr) + } + + for (let i = 0; i < this.columns.length; i++) { + const element = this.columns[i] + if (!(columns.includes(element))) { + newColumnNames.push(element) + newDtypes.push(this.dtypes[i]) + } + } + + if (inplace) { + this.$setValues(newRowData, true, false) + this.$setColumnNames(newColumnNames) + } else { + const df = new DataFrame(newRowData, + { + index: [...this.index], + columns: newColumnNames, + dtypes: newDtypes, + config: { ...this.config } + }); + return df; + } + + } + + if (index) { + const rowIndices: Array = [] + + if (typeof index === "string" || typeof index === "number" || typeof index === "boolean") { + rowIndices.push(this.index.indexOf(index)) + } else if (Array.isArray(index)) { + for (let indx of index) { + if (this.index.indexOf(indx) === -1) { + throw Error(`ParamError: specified index "${indx}" not found in indices`); + } + rowIndices.push(this.index.indexOf(indx)); + } + } else { + throw Error('ParamError: index must be an array of indices or a scalar index'); + } + + let newRowData: ArrayType2D = [] + let newIndex = [] + + for (let i = 0; i < this.values.length; i++) { + const innerArr = this.values[i] as ArrayType1D + if (!(rowIndices.includes(i))) { + newRowData.push(innerArr) + } + } + + for (let i = 0; i < this.index.length; i++) { + const indx = this.index[i] + if (!(index.includes(indx))) { + newIndex.push(indx) + } + } + + if (inplace) { + this.$setValues(newRowData, false) + this.$setIndex(newIndex) + } else { + const df = new DataFrame(newRowData, + { + index: newIndex, + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }); + return df; + } + } + + } + + /** + * Sorts a Dataframe by a specified column values + * @param column Column name to sort by. + * @param options.ascending Whether to sort values in ascending order or not. Defaults to true. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.sortBy('A') + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.sortBy('A', { ascending: false, inplace: true }).print() + * ``` + */ + sortValues( + column: string, + options?: + { + ascending?: boolean + inplace?: boolean + } + ): DataFrame + sortValues( + column: string, + options?: + { + ascending?: boolean + inplace?: boolean + } + ): DataFrame | void { + const { ascending, inplace } = { ascending: true, inplace: false, ...options } + + if (!column) { + throw Error(`ParamError: must specify a column to sort by`); + } + + if (this.columns.indexOf(column) === -1) { + throw Error(`ParamError: specified column "${column}" not found in columns`); + } + + const columnValues = this.$getColumnData(column, false) as ArrayType1D + const index = [...this.index] + + const objToSort = columnValues.map((value, i) => { + return { index: index[i], value } + }) + + const sortedObjectArr = utils.sortObj(objToSort, ascending) + const sortedIndex = sortedObjectArr.map(obj => obj.index) + + const newDf = _loc({ ndFrame: this, rows: sortedIndex }) as DataFrame + + if (inplace) { + this.$setValues(newDf.values) + this.$setIndex(newDf.index) + } else { + return newDf + } + + } + + /** + * Sets the index of the DataFrame to the specified value. + * @param options.index An array of index values to set + * @param options.column A column name whose values set in place of the index + * @param options.drop Whether to drop the column whose index was set. Defaults to false + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.setIndex({ index: ['a', 'b'] }) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.setIndex({ column: "A", inplace: true }) + * df.print() + * ``` + */ + setIndex( + options: + { + index?: Array, + column?: string, + drop?: boolean, + inplace?: boolean + } + ): DataFrame + setIndex( + options: + { + index?: Array, + column?: string, + drop?: boolean, + inplace?: boolean + } + ): DataFrame | void { + const { index, column, drop, inplace } = { drop: false, inplace: false, ...options } + + if (!index && !column) { + throw new Error("ParamError: must specify either index or column") + } + + let newIndex: Array = []; + + if (index) { + if (!Array.isArray(index)) { + throw Error(`ParamError: index must be an array`); + } + + if (index.length !== this.values.length) { + throw Error(`ParamError: index must be the same length as the number of rows`); + } + newIndex = index; + } + + if (column) { + if (this.columns.indexOf(column) === -1) { + throw Error(`ParamError: column not found in column names`); + } + + newIndex = this.$getColumnData(column, false) as Array + } + + if (drop) { + const dfDropped = this.drop({ columns: [column as string] }) + + const newData = dfDropped?.values as ArrayType2D + const newColumns = dfDropped?.columns + const newDtypes = dfDropped?.dtypes + + if (inplace) { + this.$setValues(newData, true, false) + this.$setIndex(newIndex) + this.$setColumnNames(newColumns) + } else { + const df = new DataFrame(newData, + { + index: newIndex, + columns: newColumns, + dtypes: newDtypes, + config: { ...this.config } + }); + return df; + } + } else { + if (inplace) { + this.$setIndex(newIndex) + } else { + const df = new DataFrame(this.values, + { + index: newIndex, + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }); + return df; + } + } + + } + + /** + * Resets the index of the DataFrame to default. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.resetIndex({ inplace: true }) + * df.print() + * ``` + */ + resetIndex(options?: { inplace?: boolean }): DataFrame + resetIndex(options?: { inplace?: boolean }): DataFrame | void { + const { inplace } = { inplace: false, ...options } + + if (inplace) { + this.$resetIndex() + } else { + const df = new DataFrame(this.values, + { + index: this.index.map((_, i) => i), + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }); + return df; + } + + } + + /** + * Apply a function along an axis of the DataFrame. To apply a function element-wise, use `applyMap`. + * Objects passed to the function are Series values whose + * index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1) + * @param callable Function to apply to each column or row. + * @param options.axis 0 or 1. If 0, apply "callable" column-wise, else apply row-wise + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.apply(Math.sqrt, { axis: 0 }) + * df2.print() + * ``` + */ + apply(callable: any, options?: { axis?: 0 | 1 }): DataFrame | Series { + const { axis } = { axis: 1, ...options } + + if ([0, 1].indexOf(axis) === -1) { + throw Error(`ParamError: axis must be 0 or 1`); + } + + const valuesForFunc = this.$getDataByAxisWithMissingValuesRemoved(axis) + + const result = valuesForFunc.map(row => { + return callable(row) + }) + + if (axis === 0) { + if (utils.is1DArray(result)) { + return new Series(result, { + index: [...this.columns] + }) + } else { + return new DataFrame(result, { + index: [...this.columns], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + } else { + if (utils.is1DArray(result)) { + return new Series(result, { + index: [...this.index] + }) + } else { + return new DataFrame(result, { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + } + + } + + /** + * Apply a function to a Dataframe values element-wise. + * @param callable Function to apply to each column or row + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * function square(x) { return x * x } + * const df2 = df.applyMap(square) + * df2.print() + * ``` + */ + applyMap(callable: any, options?: { inplace?: boolean }): DataFrame + applyMap(callable: any, options?: { inplace?: boolean }): DataFrame | void { + const { inplace } = { inplace: false, ...options } + + const newData = (this.values as ArrayType2D).map((row) => { + const tempData = row.map((val) => { + return callable(val); + }); + return tempData; + }); + + if (inplace) { + this.$setValues(newData); + } else { + return new DataFrame(newData, + { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }); + } + } + + /** + * Returns the specified column data as a Series object. + * @param column The name of the column to return + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const sf = df.column('A') + * sf.print() + * ``` + * + */ + column(column: string): Series { + return this.$getColumnData(column) as Series + } + + /** + * Return a subset of the DataFrame based on the column dtypes. + * @param include An array of dtypes or strings to be included. + * @example + * ``` + * const df = new DataFrame([[1, 2.1, "Dog"], [3, 4.3, "Cat"]], { columns: ['A', 'B', 'C']}) + * const df2 = df.selectDtypes(['float32']) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2.1, "Dog"], [3, 4.3, "Cat"]], { columns: ['A', 'B', 'C']}) + * const df2 = df.selectDtypes(['float32', 'int32']) + * df2.print() + * ``` + * + */ + selectDtypes(include: Array): DataFrame { + const supportedDtypes = ["float32", "int32", "string", "boolean", 'undefined'] + + if (Array.isArray(include) === false) { + throw Error(`ParamError: include must be an array`); + } + + include.forEach(dtype => { + if (supportedDtypes.indexOf(dtype) === -1) { + throw Error(`ParamError: include must be an array of valid dtypes`); + } + }) + const newColumnNames = [] + + for (let i = 0; i < this.dtypes.length; i++) { + if (include.includes(this.dtypes[i])) { + newColumnNames.push(this.columns[i]) + } + } + return this.loc({ columns: newColumnNames }) + + } + + /** + * Returns the transpose of the DataFrame. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.transpose() + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.transpose({ inplace: true }) + * df.print() + * ``` + **/ + transpose(options?: { inplace?: boolean }): DataFrame + transpose(options?: { inplace?: boolean }): DataFrame | void { + const { inplace } = { inplace: false, ...options } + const newData = utils.transposeArray(this.values) + const newColNames = [...this.index.map(i => i.toString())] + + if (inplace) { + this.$setValues(newData, false, false) + this.$setIndex([...this.columns]) + this.$setColumnNames(newColNames) + } else { + return new DataFrame(newData, { + index: [...this.columns], + columns: newColNames, + config: { ...this.config } + }) + } + } + + /** + * Returns the Transpose of the DataFrame. Similar to `transpose`. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.T() + * df2.print() + * ``` + **/ + get T(): DataFrame { + const newData = utils.transposeArray(this.values) + return new DataFrame(newData, { + index: [...this.columns], + columns: [...this.index.map(i => i.toString())], + config: { ...this.config } + }) + } + + /** + * Replace all occurence of a value with a new value. + * @param oldValue The value you want to replace + * @param newValue The new value you want to replace the old value with + * @param options.columns An array of column names you want to replace. If not provided replace accross all columns. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.replace(2, 5) + * df.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [2, 20]], { columns: ['A', 'B']}) + * const df2 = df.replace(2, 5, { columns: ['A'] }) + * df2.print() + * ``` + */ + replace( + oldValue: number | string | boolean, + newValue: number | string | boolean, + options?: { + columns?: Array + inplace?: boolean + } + ): DataFrame + replace( + oldValue: number | string | boolean, + newValue: number | string | boolean, + options?: { + columns?: Array + inplace?: boolean + } + ): DataFrame | void { + const { columns, inplace } = { inplace: false, ...options } + + if (typeof oldValue === 'number' && isNaN(oldValue)) { + throw Error(`Params Error: Param 'oldValue' does not support NaN. Use DataFrame.fillNa() instead.`); + } + + if (!oldValue && typeof oldValue !== 'boolean' && typeof oldValue !== 'number' && typeof oldValue !== 'string') { + throw Error(`Params Error: Must specify param 'oldValue' to replace`); + } + + if (!newValue && typeof newValue !== 'boolean' && typeof newValue !== 'number' && typeof newValue !== 'string') { + throw Error(`Params Error: Must specify param 'newValue' to replace with`); + } + + let newData: ArrayType2D = [] + + if (columns) { + if (!Array.isArray(columns)) { + throw Error(`Params Error: column must be an array of column(s)`); + } + const columnIndex: Array = [] + + columns.forEach(column => { + const _indx = this.columns.indexOf(column) + if (_indx === -1) { + throw Error(`Params Error: column not found in columns`); + } + columnIndex.push(_indx) + }) + + newData = (this.values as ArrayType2D).map(([...row]) => { + for (const colIndx of columnIndex) { + if (row[colIndx] === oldValue) { + row[colIndx] = newValue; + } + } + return row; + }) + } else { + newData = (this.values as ArrayType2D).map(([...row]) => { + return row.map((cell => { + if (cell === oldValue) { + return newValue + } else { + return cell + } + })) + }) + } + + if (inplace) { + this.$setValues(newData) + } else { + return new DataFrame(newData, { + index: [...this.index], + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + } + + + + /** + * Cast the values of a column to specified data type + * @param column The name of the column to cast + * @param dtype Data type to cast to. One of [float32, int32, string, boolean] + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const df = new DataFrame([[1, 2.2], [3, 4.3]], { columns: ['A', 'B']}) + * const df2 = df.asType('B', 'int32') + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2.2], [3, 4.3]], { columns: ['A', 'B']}) + * df.asType('B', 'int32', { inplace: true }) + * df.print() + * ``` + */ + asType( + column: string, + dtype: "float32" | "int32" | "string" | "boolean", + options?: { inplace?: boolean } + ): DataFrame + asType( + column: string, + dtype: "float32" | "int32" | "string" | "boolean", + options?: { inplace?: boolean } + ): DataFrame | void { + const { inplace } = { inplace: false, ...options } + const columnIndex = this.columns.indexOf(column) + + if (columnIndex === -1) { + throw Error(`Params Error: column not found in columns`); + } + + if (!(DATA_TYPES.includes(dtype))) { + throw Error(`dtype ${dtype} not supported. dtype must be one of ${DATA_TYPES}`); + } + + const data = this.values as ArrayType2D + + const newData = data.map((row) => { + if (dtype === "float32") { + row[columnIndex] = Number(row[columnIndex]) + return row + } else if (dtype === "int32") { + row[columnIndex] = parseInt(row[columnIndex] as any) + return row + } else if (dtype === "string") { + row[columnIndex] = row[columnIndex].toString() + return row + } else if (dtype === "boolean") { + row[columnIndex] = Boolean(row[columnIndex]) + return row + } + }) + + if (inplace) { + this.$setValues(newData as any) + } else { + const newDtypes = [...this.dtypes] + newDtypes[columnIndex] = dtype + + return new DataFrame(newData, { + index: [...this.index], + columns: [...this.columns], + dtypes: newDtypes, + config: { ...this.config } + }) + } + } + + /** + * Return the number of unique elements in a column, across the specified axis. + * To get the values use `.unique()` instead. + * @param axis The axis to count unique elements across. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * df.nunique().print() + * ``` + * + */ + nUnique(axis: 0 | 1 = 1): Series { + if ([0, 1].indexOf(axis) === -1) { + throw Error(`ParamError: axis must be 0 or 1`); + } + const data = this.$getDataArraysByAxis(axis) + const newData = data.map(row => new Set(row).size) + + if (axis === 0) { + return new Series(newData, { + index: [...this.columns], + dtypes: ["int32"] + }) + } else { + return new Series(newData, { + index: [...this.index], + dtypes: ["int32"] + }) + } + } + + /** + * Renames a column or index to specified value. + * @param mapper An object that maps each column or index in the DataFrame to a new value + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @param options.axis The axis to perform the operation on. Defaults to 1 + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const df2 = df.rename({ A: 'a', B: 'b' }) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * df.rename({ A: 'a', B: 'b' }, { inplace: true }) + * df.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * df.rename({ 0: 'a', 1: 'b' }, { axis: 0, inplace: true}) + * df.print() + * ``` + * + */ + rename( + mapper: { + [index: string | number]: string | number + }, + options?: { + axis?: 0 | 1 + inplace?: boolean + } + ): DataFrame + rename( + mapper: { + [index: string | number]: string | number + }, + options?: { + axis?: 0 | 1 + inplace?: boolean + } + ): DataFrame | void { + const { axis, inplace } = { axis: 1, inplace: false, ...options } + + if ([0, 1].indexOf(axis) === -1) { + throw Error(`ParamError: axis must be 0 or 1`); + } + + if (axis === 1) { + const colsAdded: string[] = []; + const newColumns = this.columns.map(col => { + if (mapper[col] !== undefined) { + const newCol = `${mapper[col]}`; + colsAdded.push(newCol); + return newCol; + } else { + return col + } + }) + + if (inplace) { + this.$setColumnNames(newColumns) + for (const col of colsAdded) { + this.$setInternalColumnDataProperty(col); + } + } else { + return new DataFrame([...this.values], { + index: [...this.index], + columns: newColumns, + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + } else { + const newIndex = this.index.map(col => { + if (mapper[col] !== undefined) { + return mapper[col] + } else { + return col + } + }) + + if (inplace) { + this.$setIndex(newIndex) + } else { + return new DataFrame([...this.values], { + index: newIndex, + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + } + + } + + /** + * Sorts the Dataframe by the index. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @param options.ascending Whether to sort values in ascending order or not. Defaults to true + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const df2 = df.sortIndex() + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * df.sortIndex({ inplace: true }) + * df.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * df.sortIndex({ ascending: false, inplace: true }) + * df.print() + * ``` + */ + sortIndex(options?: + { + inplace?: boolean + ascending?: boolean + } + ): DataFrame + sortIndex(options?: + { + inplace?: boolean + ascending?: boolean + } + ): DataFrame | void { + const { ascending, inplace } = { ascending: true, inplace: false, ...options } + + const indexPosition = utils.range(0, this.index.length - 1) + const index = [...this.index] + + const objToSort = index.map((idx, i) => { + return { index: indexPosition[i], value: idx } + }) + + const sortedObjectArr = utils.sortObj(objToSort, ascending) + let sortedIndex = sortedObjectArr.map((obj) => obj.index); + const newData = sortedIndex.map(i => (this.values as ArrayType2D)[i as number]) + sortedIndex = sortedIndex.map((i) => index[i as number]); + + if (inplace) { + this.$setValues(newData) + this.$setIndex(sortedIndex) + } else { + return new DataFrame(newData, { + index: sortedIndex, + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + + } + + /** + * Add new rows at the end of the DataFrame. + * @param newValues Array, Series or DataFrame to append to the DataFrame + * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` + * as they map `1 - 1`. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const values = [7, 8] + * const index = ['a', 'b'] + * const df2 = df.append(values, index) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const values = new Series([7, 8, 9, 10]) + * const index = ['a', 'b', 'c', 'd'] + * const df2 = df.append(values, index) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const values = new DataFrame([[7, 8], [9, 10]], { columns: ['C', 'D'] }) + * const index = ['a', 'b'] + * const df2 = df.append(values, index) + * df2.print() + * ``` + */ + append( + newValues: ArrayType1D | ArrayType2D | Series | DataFrame, + index: Array | number | string, + options?: { + inplace?: boolean, + } + ): DataFrame + append( + newValues: ArrayType1D | ArrayType2D | Series | DataFrame, + index: Array | number | string, + options?: { + inplace?: boolean, + } + ): DataFrame | void { + const { inplace } = { inplace: false, ...options } + + if (!newValues) { + throw Error(`ParamError: newValues must be a Series, DataFrame or Array`); + } + + if (!index) { + throw Error(`ParamError: index must be specified`); + } + + let rowsToAdd = [] + if (newValues instanceof Series) { + + if (newValues.values.length !== this.shape[1]) { + throw Error(`ValueError: length of newValues must be the same as the number of columns.`); + } + rowsToAdd = [newValues.values] + + } else if (newValues instanceof DataFrame) { + + if (newValues.shape[1] !== this.shape[1]) { + throw Error(`ValueError: length of newValues must be the same as the number of columns.`); + } + rowsToAdd = newValues.values + + } else if (Array.isArray(newValues)) { + + if (utils.is1DArray(newValues)) { + rowsToAdd = [newValues] + } else { + rowsToAdd = newValues + } + + if ((rowsToAdd[0] as any).length !== this.shape[1]) { + throw Error(`ValueError: length of newValues must be the same as the number of columns.`); + } + + } else { + throw Error(`ValueError: newValues must be a Series, DataFrame or Array`); + } + + + let indexInArrFormat: Array = [] + if (!Array.isArray(index)) { + indexInArrFormat = [index] + } else { + indexInArrFormat = index + } + + if (rowsToAdd.length !== indexInArrFormat.length) { + throw Error(`ParamError: index must contain the same number of values as newValues`); + } + + const newData = [...this.values] as ArrayType2D + const newIndex = [...this.index] + + rowsToAdd.forEach((row, i) => { + newData.push(row as ArrayType1D) + newIndex.push(indexInArrFormat[i]) + }) + + if (inplace) { + this.$setValues(newData) + this.$setIndex(newIndex) + } else { + return new DataFrame(newData, { + index: newIndex, + columns: [...this.columns], + dtypes: [...this.dtypes], + config: { ...this.config } + }) + } + + } + + /** + * Queries the DataFrame for rows that meet the boolean criteria. This is just a wrapper for the `iloc` method. + * @param condition An array of boolean mask, one for each row in the DataFrame. Rows where the value are true will be returned. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const df2 = df.query([true, false, true, true]) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const df2 = df.query(df["A"].gt(2)) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * const df2 = df.query(df["A"].gt(2).and(df["B"].lt(5))) + * df2.print() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4], [1, 2], [5, 6]], { columns: ['A', 'B'] }) + * df.query(df["A"].gt(2), { inplace: true }) + * df.print() + * ``` + **/ + query(condition: Series | Array, options?: { inplace?: boolean }): DataFrame + query(condition: Series | Array, options?: { inplace?: boolean }): DataFrame | void { + const { inplace } = { inplace: false, ...options } + + if (!condition) { + throw new Error("ParamError: condition must be specified"); + } + + const result = _iloc({ + ndFrame: this, + rows: condition, + }) as DataFrame + + if (inplace) { + this.$setValues(result.values, false, false) + this.$setIndex(result.index) + } else { + return result + } + + } + + /** + * Returns the data types for each column as a Series. + * @example + * ``` + * const df = new DataFrame([[1, 2.1, "Dog"], [3, 4.3, "Cat"]], { columns: ['A', 'B', 'C'] }) + * df.ctypes().print() + * ``` + */ + get ctypes(): Series { + return new Series(this.dtypes, { index: this.columns }) + } + + /** + * One-hot encode specified columns in the DataFrame. If columns are not specified, all columns of string dtype will be encoded. + * @param options Options for the operation. The following options are available: + * - `columns`: A single column name or an array of column names to encode. Defaults to all columns of dtype string. + * - `prefix`: Prefix to add to the column names. Defaults to unique labels. + * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. + * - `inplace`: Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.getDummies() + * ``` + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.getDummies({ columns: ['A'] }) + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.getDummies({ prefix: 'cat' }) + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.getDummies({ prefix: 'cat', prefixSeparator: '_' }) + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const df2 = df.getDummies({ inplace: true }) + * ``` + */ + getDummies(options?: { + columns?: string | Array, + prefix?: string | Array, + prefixSeparator?: string | Array, + inplace?: boolean + }): DataFrame + getDummies(options?: { + columns?: string | Array, + prefix?: string | Array, + prefixSeparator?: string | Array, + inplace?: boolean + }): DataFrame | void { + const { inplace } = { inplace: false, ...options } + + const encodedDF = dummyEncode(this, options) + if (inplace) { + this.$setValues(encodedDF.values, false, false) + this.$setColumnNames(encodedDF.columns) + } else { + return encodedDF + } + + } + + /** + * Groupby + * @params col a list of column + * @returns Groupby + * @example + * let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + * let cols = [ "A", "B", "C" ]; + * let df = new dfd.DataFrame(data, { columns: cols }); + * let groupDf = df.groupby([ "A" ]); + */ + groupby(col: Array): Groupby { + const columns = this.columns + const colIndex = col.map((val) => columns.indexOf(val)) + const colDtype = this.dtypes + + return new Groupby( + col, + this.values as ArrayType2D, + columns, + colDtype, + colIndex + ).group() + + } + + /** + * Access a single value for a row/column pair by integer position. + * Similar to {@link iloc}, in that both provide integer-based lookups. + * Use iat if you only need to get or set a single value in a DataFrame. + * @param row Row index of the value to access. + * @param column Column index of the value to access. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.iat(0, 0) // 1 + * df.iat(0, 1) // 2 + * df.iat(1, 0) // 3 + * ``` + */ + iat(row: number, column: number): string | number | boolean | undefined { + if (typeof row === 'string' || typeof column === 'string') { + throw new Error('ParamError: row and column index must be an integer. Use .at to get a row or column by label.') + } + + return (this.values as ArrayType2D)[row][column] + } + + /** + * Access a single value for a row/column label pair. + * Similar to {@link loc}, in that both provide label-based lookups. + * Use at if you only need to get or set a single value in a DataFrame. + * @param row Row index of the value to access. + * @param column Column label of the value to access. + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.at(0,'A') // 1 + * df.at(1, 'A') // 3 + * df.at(1, 'B') // 4 + * ``` + */ + at(row: string | number, column: string): string | number | boolean | undefined { + if (typeof column !== 'string') { + throw new Error('ParamError: column index must be a string. Use .iat to get a row or column by index.') + } + return (this.values as ArrayType2D)[this.index.indexOf(row)][this.columns.indexOf(column)] + } + + /** + * Exposes functions for creating charts from a DataFrame. + * Charts are created using the Plotly.js library, so all Plotly's configuration parameters are available. + * @param divId name of the HTML Div to render the chart in. + */ + plot(divId: string): IPlotlyLib { + //TODO: Add support for check plot library to use. So we can support other plot library like d3, vega, etc + if (utils.isBrowserEnv()) { + const plt = new PlotlyLib(this, divId); + return plt; + } else { + throw new Error("Not supported in NodeJS"); + } + } +} diff --git a/src/danfojs-base/core/generic.ts b/src/danfojs-base/core/generic.ts new file mode 100644 index 00000000..d374aecf --- /dev/null +++ b/src/danfojs-base/core/generic.ts @@ -0,0 +1,510 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import Utils from "../shared/utils"; +import Configs from "../shared/config"; +import { _iloc } from "./indexing" +import { + NDframeInterface, + NdframeInputDataType, + LoadArrayDataType, + LoadObjectDataType, + AxisType, + ArrayType1D, + ArrayType2D +} from '../shared/types' +import ErrorThrower from '../shared/errors'; +import { BASE_CONFIG, DATA_TYPES } from '../shared/defaults'; +import tensorflow from '../shared/tensorflowlib' + + +const utils = new Utils(); + +/** + * N-Dimension data structure. Stores multi-dimensional + * data in a size-mutable, labeled data structure. Analogous to the Python Pandas DataFrame. + * + * @param Object + * + * data: 1D or 2D Array, JSON, Tensor, Block of data. + * + * index: Array of numeric or string names for subseting array. If not specified, indexes are auto generated. + * + * columns: Array of column names. If not specified, column names are auto generated. + * + * dtypes: Array of data types for each the column. If not specified, dtypes inferred. + * + * config: General configuration object for NDframe + * + * @returns NDframe + */ +export default class NDframe implements NDframeInterface { + $isSeries: boolean; + protected $data: any + protected $dataIncolumnFormat: ArrayType1D | ArrayType2D = [] + protected $index: Array = [] + protected $columns: string[] = [] + protected $dtypes: Array = [] + protected $config: Configs + + constructor({ data, index, columns, dtypes, config, isSeries }: NdframeInputDataType) { + this.$isSeries = isSeries + if (config) { + this.$config = new Configs({ ...BASE_CONFIG, ...config }); + } else { + this.$config = new Configs(BASE_CONFIG); + } + + if (data instanceof tensorflow.Tensor) { + data = data.arraySync(); + } + + if (data === undefined || (Array.isArray(data) && data.length === 0)) { + if (columns === undefined) columns = []; + if (dtypes === undefined) dtypes = []; + if (columns.length === 0 && dtypes.length !== 0) ErrorThrower.throwDtypeWithoutColumnError(); + this.loadArrayIntoNdframe({ data: [], index: [], columns: columns, dtypes: dtypes }); + } else if (utils.is1DArray(data)) { + this.loadArrayIntoNdframe({ data, index, columns, dtypes }); + } else { + if (Array.isArray(data) && utils.isObject(data[0])) { + this.loadObjectIntoNdframe({ data, type: 1, index, columns, dtypes }); + + } else if (utils.isObject(data)) { + this.loadObjectIntoNdframe({ data, type: 2, index, columns, dtypes }); + + } else if ( + Array.isArray((data)[0]) || + utils.isNumber((data)[0]) || + utils.isString((data)[0]) + ) { + this.loadArrayIntoNdframe({ data, index, columns, dtypes }); + } else if (Array.isArray(data) && data.length > 0 && utils.isDate(data[0])) { + this.loadArrayIntoNdframe({ data, index, columns, dtypes }); + } else { + throw new Error("File format not supported!"); + } + } + } + + /** + * Internal function to load array of data into NDFrame + * @param data The array of data to load into NDFrame + * @param index Array of numeric or string names for subsetting array. + * @param columns Array of column names. + * @param dtypes Array of data types for each the column. + */ + private loadArrayIntoNdframe({ data, index, columns, dtypes }: LoadArrayDataType): void { + // this.$data = utils.replaceUndefinedWithNaN(data, this.$isSeries); + this.$data = data + if (!this.$config.isLowMemoryMode) { + //In NOT low memory mode, we transpose the array and save in column format. + //This makes column data retrieval run in constant time + this.$dataIncolumnFormat = utils.transposeArray(data) + } + this.$setIndex(index); + this.$setDtypes(dtypes); + this.$setColumnNames(columns); + } + + /** + * Internal function to format and load a Javascript object or object of arrays into NDFrame. + * @param data Object or object of arrays. + * @param type The type of the object. There are two recognized types: + * + * - type 1 object are in JSON format `[{a: 1, b: 2}, {a: 30, b: 20}]`. + * + * - type 2 object are of the form `{a: [1,2,3,4], b: [30,20, 30, 20}]}` + * @param index Array of numeric or string names for subsetting array. + * @param columns Array of column names. + * @param dtypes Array of data types for each the column. + */ + private loadObjectIntoNdframe({ data, type, index, columns, dtypes }: LoadObjectDataType): void { + if (type === 1 && Array.isArray(data)) { + const _data = (data).map((item) => { + return Object.values(item); + }); + + let _columnNames; + + if (columns) { + _columnNames = columns + } else { + _columnNames = Object.keys((data)[0]); + } + + this.loadArrayIntoNdframe({ data: _data, index, columns: _columnNames, dtypes }); + + } else { + const [_data, _colNames] = utils.getRowAndColValues(data); + let _columnNames; + + if (columns) { + _columnNames = columns + } else { + _columnNames = _colNames + } + this.loadArrayIntoNdframe({ data: _data, index, columns: _columnNames, dtypes }); + } + } + + /** + * Converts and returns the data in the NDframe as a Tensorflow.js Tensor. + */ + get tensor() { + if (this.$isSeries) { + return tensorflow.tensor1d(this.$data, this.$dtypes[0]); + } else { + return tensorflow.tensor2d(this.$data, this.shape, "float32") + } + } + + /** + * Returns the dtypes of the columns + */ + get dtypes(): Array { + return this.$dtypes + } + + /** + * Internal function to set the Dtypes of the NDFrame from an array. This function + * performs the necessary checks. + */ + $setDtypes(dtypes: Array | undefined): void { + if (this.$isSeries) { + if (dtypes) { + if (this.$data.length != 0 && dtypes.length != 1) { + ErrorThrower.throwDtypesLengthError(this, dtypes) + } + + if (!(DATA_TYPES.includes(`${dtypes[0]}`))) { + ErrorThrower.throwDtypeNotSupportedError(dtypes[0]) + } + + this.$dtypes = dtypes + } else { + this.$dtypes = utils.inferDtype(this.$data) + } + + } else { + if (dtypes) { + if (this.$data.length != 0 && dtypes.length != this.shape[1]) { + ErrorThrower.throwDtypesLengthError(this, dtypes) + } + + if (this.$data.length == 0 && dtypes.length == 0) { + this.$dtypes = dtypes + } else { + dtypes.forEach((dtype) => { + if (!(DATA_TYPES.includes(dtype))) { + ErrorThrower.throwDtypeNotSupportedError(dtype) + } + }) + + this.$dtypes = dtypes + + } + + } else { + this.$dtypes = utils.inferDtype(this.$data) + } + } + } + + /** + * Returns the dimension of the data. Series have a dimension of 1, + * while DataFrames have a dimension of 2. + */ + get ndim(): number { + if (this.$isSeries) { + return 1; + } else { + return 2 + } + } + + /** + * Returns the axis labels of the NDFrame. + */ + get axis(): AxisType { + return { + index: this.$index, + columns: this.$columns + }; + } + + /** + * Returns the configuration object of the NDFrame. + */ + get config(): Configs { + return this.$config + + } + + /** + * Internal function to set the configuration of the ndframe + */ + $setConfig(config: Configs): void { + this.$config = config + } + + /** + * Returns the indices of the NDFrame + */ + get index(): Array { + return this.$index + + } + + /** + * Internal function to set the index of the NDFrame with the specified + * array of indices. Performs all necessary checks to ensure that the + * index is valid. + */ + $setIndex(index: Array | undefined): void { + if (index) { + + if (this.$data.length != 0 && index.length != this.shape[0]) { + ErrorThrower.throwIndexLengthError(this, index) + } + if (Array.from(new Set(index)).length !== this.shape[0]) { + ErrorThrower.throwIndexDuplicateError() + } + + this.$index = index + } else { + this.$index = utils.range(0, this.shape[0] - 1) //generate index + } + } + + /** + * Internal function to reset the index of the NDFrame using a range of indices. + */ + $resetIndex(): void { + this.$index = utils.range(0, this.shape[0] - 1) + } + + /** + * Returns the column names of the NDFrame + */ + get columns(): string[] { + return this.$columns + } + + /** + * Internal function to set the column names for the NDFrame. This function + * performs a check to ensure that the column names are unique, and same length as the + * number of columns in the data. + */ + $setColumnNames(columns?: string[]) { + + // console.log(columns); + if (this.$isSeries) { + if (columns) { + if (this.$data.length != 0 && columns.length != 1 && typeof columns != 'string') { + ErrorThrower.throwColumnNamesLengthError(this, columns) + } + this.$columns = columns + } else { + this.$columns = ["0"] + } + } else { + if (columns) { + + if (this.$data.length != 0 && columns.length != this.shape[1]) { + + ErrorThrower.throwColumnNamesLengthError(this, columns) + } + if (Array.from(new Set(columns)).length !== columns.length) { + ErrorThrower.throwColumnDuplicateError() + } + + this.$columns = columns + } else { + this.$columns = (utils.range(0, this.shape[1] - 1)).map((val) => `${val}`) //generate columns + } + } + } + + /** + * Returns the shape of the NDFrame. Shape is determined by [row length, column length] + */ + get shape(): Array { + if (this.$data.length === 0) { + if (this.$columns.length === 0) return [0, 0]; + else return [0, this.$columns.length]; + } + if (this.$isSeries) { + return [this.$data.length, 1]; + } else { + const rowLen = (this.$data).length + const colLen = (this.$data[0] as []).length + return [rowLen, colLen] + } + + } + + /** + * Returns the underlying data in Array format. + */ + get values(): ArrayType1D | ArrayType2D { + return this.$data; + } + + /** + * Updates the internal $data property to the specified value + * @param values An array of values to set + * @param checkLength Whether to check the length of the new values and the existing row length + * @param checkColumnLength Whether to check the length of the new values and the existing column length + * */ + $setValues(values: ArrayType1D | ArrayType2D, checkLength: boolean = true, checkColumnLength: boolean = true): void { + if (this.$isSeries) { + if (checkLength && values.length != this.shape[0]) { + ErrorThrower.throwRowLengthError(this, values.length) + } + + this.$data = values + this.$dtypes = utils.inferDtype(values) //Dtype may change depeneding on the value set + + if (!this.$config.isLowMemoryMode) { + this.$dataIncolumnFormat = values + } + + } else { + if (checkLength && values.length != this.shape[0]) { + ErrorThrower.throwRowLengthError(this, values.length) + } + + if (checkColumnLength) { + values.forEach(value => { + if ((value as ArrayType1D).length != this.shape[1]) { + ErrorThrower.throwColumnLengthError(this, values.length) + } + }) + } + + this.$data = values + this.$dtypes = utils.inferDtype(values) + + if (!this.$config.isLowMemoryMode) { + this.$dataIncolumnFormat = utils.transposeArray(values) + } + + } + + } + + /** + * Returns the underlying data in Array column format. + * Similar to this.values, but in column format. + */ + get getColumnData() { + if (this.config.isLowMemoryMode) { + return utils.transposeArray(this.values); + } else { + return this.$dataIncolumnFormat; + } + } + + /** + * Returns the size of the NDFrame object + * + */ + get size(): number { + return this.shape[0] * this.shape[1] + } + + /** + * Converts a DataFrame or Series to CSV. + * @deprecated Use `toCSV` function directly instead. + * @example + * ``` + * import * as dfd from "danfojs" + * const df = new dfd.DataFrame([[1, 2, 3], [4, 5, 6]]) + * const csv = dfd.toCSV(df) + * ``` + * @example + * ``` + * import { toCSV } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toCSV(df, { + * filePath: "./data/sample.csv", + * header: true, + * sep: "+" + * }) + */ + toCSV(options?: any): string + toCSV(options?: any): string | void { + throw new Error("`toCSV` function is deprecated. Use `toCSV` function directly instead. e.g. `dfd.toCSV(df)`") + } + + /** + * Converts a DataFrame or Series to JSON. + * @deprecated Use `toJSON` function directly instead. + * @example + * ``` + * import * as dfd from "danfojs-node" + * const df = new dfd.DataFrame([[1, 2, 3], [4, 5, 6]]) + * const json = dfd.toJSON(df) + * ``` + * @example + * ``` + * import { toJSON } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toJSON(df, { + * filePath: "./data/sample.json", + * format: "row" + * }) + * ``` + */ + toJSON(options?: any): object + toJSON(options?: any): object | void { + throw new Error("`toJSON` function is deprecated. Use `toJSON` function directly instead. e.g. `dfd.toJSON(df, { format: 'row' })`") + } + + /** + * Converts a DataFrame or Series to Excel. + * @deprecated Use `toExcel` function directly instead. + * @example + * ``` + * import * as dfd from "danfojs" + * const df = new dfd.DataFrame([[1, 2, 3], [4, 5, 6]]) + * dfd.toExcel(df, { + * filePath: "./data/sample.xlsx", + * sheetName: "MySheet", + * }) + * ``` + * + * @example + * ``` + * import { toExcel } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toExcel(df, { + * filePath: "./data/sample.xlsx", + * sheetName: "MySheet", + * }) + * ``` + */ + toExcel(options?: any): void { + throw new Error("Deprecated. Use `toExcel` function directly instead. e.g. `dfd.toExcel(df, {filePath: 'path/to/file.xlsx'})`") + } + + /** + * Pretty prints a DataFrame or Series to the console + */ + print() { + console.log(this + ""); + } +} diff --git a/src/danfojs-base/core/indexing.ts b/src/danfojs-base/core/indexing.ts new file mode 100644 index 00000000..5c2b668b --- /dev/null +++ b/src/danfojs-base/core/indexing.ts @@ -0,0 +1,420 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import Series from "./series"; +import Utils from "../shared/utils" +import DataFrame from "./frame"; +import { NDframeInterface } from "../shared/types"; + +const utils = new Utils(); + +/** +* Internal function to slice a Series/DataFrame by index based labels +* @param Object +*/ +export function _iloc({ ndFrame, rows, columns }: { + ndFrame: NDframeInterface + rows?: Array | Series + columns?: Array +}): Series | DataFrame { + + let _rowIndexes: Array + let _columnIndexes: Array + + const _data = ndFrame.values; + const _index = ndFrame.index; + + if (rows instanceof Series) { + rows = rows.values as Array + } + + if (rows !== undefined && !Array.isArray(rows)) { + throw new Error(`rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`) + } + + if (columns !== undefined && !Array.isArray(columns)) { + throw new Error(`columns parameter must be an Array. For example: columns: [1,2] or columns: ["0:10"]`) + } + + if (!rows) { + _rowIndexes = utils.range(0, ndFrame.shape[0] - 1) + + } else if (rows.length == 1 && typeof rows[0] == "string") { + const rowSplit = rows[0].split(":") + + if (rowSplit.length != 2) { + throw new Error(`Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + } + if (isNaN(parseInt(rowSplit[0])) && rowSplit[0] != "") { + throw new Error(`Invalid row split parameter. Split parameter must be a number`); + } + + if (isNaN(parseInt(rowSplit[1])) && rowSplit[1] != "") { + throw new Error(`Invalid row split parameter. Split parameter must be a number`); + } + + const start = rowSplit[0] == "" ? 0 : parseInt(rowSplit[0]) + const end = rowSplit[1] == "" ? ndFrame.shape[0] : parseInt(rowSplit[1]) + + if (start < 0) { + throw new Error(`row slice [start] index cannot be less than 0`); + } + + if (end > ndFrame.shape[0]) { + throw new Error(`row slice [end] index cannot be bigger than ${ndFrame.shape[0]}`); + } + _rowIndexes = utils.range(start, end - 1) + } else { + const _formatedRows = [] + for (let i = 0; i < rows.length; i++) { + let _indexToUse = rows[i]; + if (_indexToUse > ndFrame.shape[0]) { + throw new Error(`Invalid row parameter: Specified index ${_indexToUse} cannot be bigger than index length ${ndFrame.shape[0]}`); + } + + if (typeof _indexToUse !== "number" && typeof _indexToUse !== "boolean") { + throw new Error(`Invalid row parameter: row index ${_indexToUse} must be a number or boolean`); + } + + if (typeof _indexToUse === "boolean" && _indexToUse === true) { + _formatedRows.push(_index[i]) + } + + if (typeof _indexToUse === "number") { + _formatedRows.push(_indexToUse) + } + } + + _rowIndexes = _formatedRows as number[] + } + + if (!columns) { + _columnIndexes = utils.range(0, ndFrame.shape[1] - 1) + + } else if (columns.length == 1 && typeof columns[0] == "string") { + const columnSplit = columns[0].split(":") + + if (columnSplit.length != 2) { + throw new Error(`Invalid column split parameter: If using column split string, it must be of the form; columns: ["start:end"]`); + } + if (isNaN(parseInt(columnSplit[0])) && columnSplit[0] != "") { + throw new Error(`Invalid column split parameter. Split parameter must be a number`); + } + + if (isNaN(parseInt(columnSplit[1])) && columnSplit[1] != "") { + throw new Error(`Invalid column split parameter. Split parameter must be a number`); + } + + const start = columnSplit[0] == "" ? 0 : parseInt(columnSplit[0]) + const end = columnSplit[1] == "" ? ndFrame.shape[1] : parseInt(columnSplit[1]) + + if (start < 0) { + throw new Error(`column slice [start] index cannot be less than 0`); + } + + if (end > ndFrame.shape[1]) { + throw new Error(`column slice [end] index cannot be bigger than ${ndFrame.shape[1]}`); + } + _columnIndexes = utils.range(start, end - 1) + } else { + + for (let i = 0; i < columns.length; i++) { + const _indexToUse = columns[i]; + if (_indexToUse > ndFrame.shape[1]) { + throw new Error(`Invalid column parameter: Specified index ${_indexToUse} cannot be bigger than index length ${ndFrame.shape[1]}`); + } + + if (typeof _indexToUse != "number") { + throw new Error(`Invalid column parameter: column index ${_indexToUse} must be a number`); + } + + } + + _columnIndexes = columns as number[] + } + + if (ndFrame instanceof Series) { + const newData = [] + const newIndex = [] + + for (let i = 0; i < _rowIndexes.length; i++) { + const rowIndx = _rowIndexes[i] + newData.push(_data[rowIndx]) + newIndex.push(_index[rowIndx]) + } + const sf = new Series( + newData, + { + index: newIndex, + columns: ndFrame.columns, + dtypes: ndFrame.dtypes, + config: ndFrame.config + }) + + return sf + } else { + const newData = [] + const newIndex = [] + const newColumnNames: string[] = [] + const newDtypes = [] + + for (let i = 0; i < _rowIndexes.length; i++) { + const rowIndx = _rowIndexes[i] + const rowData: any = _data[rowIndx] + const newRowDataWithRequiredCols = [] + + for (let j = 0; j < _columnIndexes.length; j++) { + const colIndx = _columnIndexes[j] + newRowDataWithRequiredCols.push(rowData[colIndx]) + } + newData.push(newRowDataWithRequiredCols) + newIndex.push(_index[rowIndx]) + } + + for (let i = 0; i < _columnIndexes.length; i++) { + const colIndx = _columnIndexes[i] + newColumnNames.push(ndFrame.columns[colIndx]) + newDtypes.push(ndFrame.dtypes[colIndx]) + + } + + const df = new DataFrame( + newData, + { + index: newIndex, + columns: newColumnNames, + dtypes: newDtypes, + config: ndFrame.config + }) + + return df + + } + +} + +/** +* Internal function to slice a Series/DataFrame by specified string location based labels +* @param Object +*/ +export function _loc({ ndFrame, rows, columns }: { + ndFrame: NDframeInterface + rows?: Array | Series + columns?: Array +}): Series | DataFrame { + + let _rowIndexes: Array + let _columnIndexes: Array + + const _data = ndFrame.values; + const _index = ndFrame.index; + + if (rows instanceof Series) { + rows = rows.values as Array + } + + if (rows !== undefined && !Array.isArray(rows)) { + throw new Error(`rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`) + } + + if (columns !== undefined && !Array.isArray(columns)) { + throw new Error(`columns parameter must be an Array. For example: columns: ["a","b"] or columns: ["a:c"]`) + } + + if (!rows) { + _rowIndexes = _index.map(indexValue => _index.indexOf(indexValue)) // Return all row index + + } else if (rows.length == 1 && typeof rows[0] == "string") { + + if (rows[0].indexOf(":") === -1) { // Input type ==> ["1"] or [`"1"`] + let temp; + if (rows[0].startsWith(`"`) || rows[0].startsWith(`'`) || rows[0].startsWith("`")) { + temp = _index.indexOf(rows[0].replace(/['"`]/g, '')) + } else { + temp = _index.indexOf(Number(rows[0])) + } + + if (temp === -1) { + throw new Error(`IndexError: Specified index (${rows[0]}) not found`); + } + + _rowIndexes = [temp] + + } else { + // Input type ==> ["1:2"] or [`"1":"4"`] + const rowSplit = rows[0].split(":") + + if (rowSplit.length != 2) { + throw new Error(`Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + } + + let start: number + let end: number + + if (rowSplit[0] === "") { + start = _index.indexOf(_index[0]) + } else { + if (rowSplit[0].startsWith(`"`) || rowSplit[0].startsWith(`'`) || rowSplit[0].startsWith("`")) { + start = _index.indexOf(rowSplit[0].replace(/['"`]/g, '')) + } else { + start = _index.indexOf(Number(rowSplit[0])) + } + + } + + if (rowSplit[1] === "") { + end = _index.indexOf(_index[_index.length - 1]) + 1 + } else { + if (rowSplit[0].startsWith(`"`) || rowSplit[0].startsWith(`'`) || rowSplit[0].startsWith("`")) { + end = _index.indexOf(rowSplit[1].replace(/['"`]/g, '')) + } else { + end = _index.indexOf(Number(rowSplit[1])) + } + + } + + if (start === -1) { + throw new Error(`IndexError: Specified start index not found`); + } + + if (end === -1) { + throw new Error(`IndexError: Specified end index not found`); + } + + _rowIndexes = _index.slice(start, end).map(indexValue => _index.indexOf(indexValue)) + } + + } else { + // Input type ==> ["1", "2"] or [1, 5] or [true, false] + const rowsIndexToUse = [] + for (let i = 0; i < rows.length; i++) { + const isBoolean = typeof rows[i] === "boolean" + if (isBoolean && rows[i]) { + rowsIndexToUse.push(_index.indexOf(_index[i])) + } + + if (!isBoolean) { + const rowIndex = _index.indexOf(rows[i] as number | string) + if (rowIndex === -1) { + throw new Error(`IndexError: Specified index (${rows[i]}) not found`); + } + rowsIndexToUse.push(rowIndex) + } + } + + _rowIndexes = rowsIndexToUse + } + + const _columnNames = ndFrame.columns + + if (!columns) { + _columnIndexes = _columnNames.map(columnName => _columnNames.indexOf(columnName))// Return all column index + + } else if (columns.length == 1) { + if (typeof columns[0] !== "string") { + throw new Error(`ColumnIndexError: columns parameter must be an array of a string name. For example: columns: ["b"]`) + } + + if (columns[0].indexOf(":") == -1) { // Input type ==> ["A"] + _columnIndexes = [_columnNames.indexOf(columns[0])] + + } else { // Input type ==> ["a:b"] or [`"col1":"col5"`] + const columnSplit = columns[0].split(":") + + if (columnSplit.length != 2) { + throw new Error(`ColumnIndexError: Invalid row split parameter. If using row split string, it must be of the form; rows: ["start:end"]`); + } + + const start = columnSplit[0] == "" ? _columnNames.indexOf(_columnNames[0]) : _columnNames.indexOf(columnSplit[0]) + const end = columnSplit[1] == "" ? _columnNames.indexOf(_columnNames[_columnNames.length - 1]) : _columnNames.indexOf(columnSplit[1]) + + if (start === -1) { + throw new Error(`ColumnIndexError: Specified start index not found`); + } + + if (end === -1) { + throw new Error(`ColumnIndexError: Specified end index not found`); + } + _columnIndexes = _columnNames.slice(start, end + 1).map(columnName => _columnNames.indexOf(columnName)) + _columnIndexes.pop() //Remove the last element + + } + } else {// Input type ==> ["A", "B"] or ["col1", "col2"] + for (let i = 0; i < columns.length; i++) { + if (_columnNames.indexOf(columns[i]) === -1) { + throw new Error(`ColumnIndexError: Specified column (${columns[i]}) not found`); + } + } + _columnIndexes = columns.map(columnName => _columnNames.indexOf(columnName)) + } + + if (ndFrame instanceof Series) { + const newData = [] + const newIndex = [] + + for (let i = 0; i < _rowIndexes.length; i++) { + const rowIndx = _rowIndexes[i] + newData.push(_data[rowIndx]) + newIndex.push(_index[rowIndx]) + } + const sf = new Series( + newData, + { + index: newIndex, + columns: ndFrame.columns, + dtypes: ndFrame.dtypes, + config: ndFrame.config + }) + + return sf + } else { + const newData = [] + const newIndex = [] + const newColumnNames: string[] = [] + const newDtypes = [] + + for (let i = 0; i < _rowIndexes.length; i++) { + const rowIndx: number = _rowIndexes[i] + const rowData: any = _data[rowIndx] + const newRowDataWithRequiredCols = [] + + for (let j = 0; j < _columnIndexes.length; j++) { + const colIndx = _columnIndexes[j] + newRowDataWithRequiredCols.push(rowData[colIndx]) + } + newData.push(newRowDataWithRequiredCols) + newIndex.push(_index[rowIndx]) + } + + for (let i = 0; i < _columnIndexes.length; i++) { + const colIndx = _columnIndexes[i] + newColumnNames.push(ndFrame.columns[colIndx]) + newDtypes.push(ndFrame.dtypes[colIndx]) + + } + + const df = new DataFrame( + newData, + { + index: newIndex, + columns: newColumnNames, + dtypes: newDtypes, + config: ndFrame.config + }) + return df + + } + +} \ No newline at end of file diff --git a/src/danfojs-base/core/math.ops.ts b/src/danfojs-base/core/math.ops.ts new file mode 100644 index 00000000..6b141a2e --- /dev/null +++ b/src/danfojs-base/core/math.ops.ts @@ -0,0 +1,167 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "./series"; +import Utils from "../shared/utils" + +const utils = new Utils(); + +/** + * Generic function for performing math operations on a series + * @param object + * + * ndframe ==> The current Series + * + * other ==> The Series or number to perform math operation with + * + * operation ==> The type of operation to perform +*/ +export function _genericMathOp({ ndFrame, other, operation }: { + ndFrame: Series + other: Series | number | Array + operation: string +}) { + if (typeof other === 'number') { + //broadcast operation + let newData; + switch (operation) { + case 'add': + newData = (ndFrame.values as number[]).map((ele => ele + other)) + return newData + + case 'sub': + newData = (ndFrame.values as number[]).map((ele => ele - other)) + return newData + + case 'mul': + newData = (ndFrame.values as number[]).map((ele => ele * other)) + return newData + + case 'div': + newData = (ndFrame.values as number[]).map((ele => ele / other)) + return newData + + case 'mod': + newData = (ndFrame.values as number[]).map((ele => ele % other)) + return newData + + case 'pow': + newData = (ndFrame.values as number[]).map((ele => ele ** other)) + return newData + + case 'minimum': + newData = (ndFrame.values as number[]).map((ele => Math.min(ele, other))) + return newData + + case 'maximum': + newData = (ndFrame.values as number[]).map((ele => Math.max(ele, other))) + return newData + + default: + throw new Error(`${operation} is not implemented`); + + } + } else if (other instanceof Series) { + utils.checkSeriesOpCompactibility({ firstSeries: ndFrame, secondSeries: other, operation }) + + let newData; + switch (operation) { + case 'add': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele + (other.values as number[])[index] }) + return newData + + case 'sub': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele - (other.values as number[])[index] }) + return newData + + case 'mul': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele * (other.values as number[])[index] }) + return newData + + case 'div': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele / (other.values as number[])[index] }) + return newData + + case 'mod': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele % (other.values as number[])[index] }) + return newData + + case 'pow': + newData = (ndFrame.values as number[]).map((ele, index) => { return ele ** (other.values as number[])[index] }) + return newData + + case 'minimum': + newData = (ndFrame.values as number[]).map((ele, index) => { return Math.min(ele, (other.values as number[])[index]) }) + return newData + + case 'maximum': + newData = (ndFrame.values as number[]).map((ele, index) => { return Math.max(ele, (other.values as number[])[index]) }) + return newData + + default: + throw new Error(`${operation} is not implemented`); + } + } else if (Array.isArray(other)) { + if(other.length !== ndFrame.values.length){ + throw new Error(`ParamError: Length of array must be equal to length of Series`) + } + let newData; + switch (operation) { + case 'add': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele + (other as number[])[index] }) + return newData + + case 'sub': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele - (other as number[])[index] }) + return newData + + case 'mul': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele * (other as number[])[index] }) + return newData + + case 'div': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele / (other as number[])[index] }) + return newData + + case 'mod': + + newData = (ndFrame.values as number[]).map((ele, index) => { return ele % (other as number[])[index] }) + return newData + + case 'pow': + newData = (ndFrame.values as number[]).map((ele, index) => { return ele ** (other as number[])[index] }) + return newData + + case 'minimum': + newData = (ndFrame.values as number[]).map((ele, index) => { return Math.min(ele, (other as number[])[index]) }) + return newData + + case 'maximum': + newData = (ndFrame.values as number[]).map((ele, index) => { return Math.max(ele, (other as number[])[index]) }) + return newData + + } + } else { + throw new Error("ParamError: value for other not supported. It must be either a scalar, Array or Series"); + } +} \ No newline at end of file diff --git a/src/danfojs-base/core/series.ts b/src/danfojs-base/core/series.ts new file mode 100644 index 00000000..9db5f37a --- /dev/null +++ b/src/danfojs-base/core/series.ts @@ -0,0 +1,2191 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import dummyEncode from "../transformers/encoders/dummy.encoder"; +import { variance, std, median, mode } from 'mathjs'; +import tensorflow from '../shared/tensorflowlib' +import { DATA_TYPES } from '../shared/defaults' +import { _genericMathOp } from "./math.ops"; +import ErrorThrower from "../shared/errors" +import { _iloc, _loc } from "./indexing"; +import Utils from "../shared/utils" +import NDframe from "./generic"; +import { table } from "table"; +import Str from './strings'; +import Dt from './datetime'; +import DataFrame from "./frame"; +import { + ArrayType1D, + BaseDataOptionType, + SeriesInterface, + mapParam, + IPlotlyLib +} from "../shared/types"; +import { PlotlyLib } from "../../danfojs-base/plotting"; + +const utils = new Utils(); + + +/** + * One-dimensional ndarray with axis labels. + * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. + * Operations between Series (+, -, /, , *) align values based on their associated index values – they need not be the same length. + * @param data 1D Array, JSON, Tensor, Block of data. + * @param options.index Array of numeric or string index for subseting array. If not specified, indices are auto generated. + * @param options.columns Column name. This is like the name of the Series. If not specified, column name is set to 0. + * @param options.dtypes Data types of the Series data. If not specified, dtypes is inferred. + * @param options.config General configuration object for extending or setting Series behavior. + */ +export default class Series extends NDframe implements SeriesInterface { + + constructor(data: any = [], options: BaseDataOptionType = {}) { + const { index, columns, dtypes, config } = options; + if (Array.isArray(data[0]) || utils.isObject(data[0])) { + data = utils.convert2DArrayToSeriesArray(data); + super({ + data, + index, + columns, + dtypes, + config, + isSeries: true + }); + } else { + super({ + data, + index, + columns, + dtypes, + config, + isSeries: true + }); + } + } + + /** + * Purely integer-location based indexing for selection by position. + * ``.iloc`` is primarily integer position based (from ``0`` to + * ``length-1`` of the axis), but may also be used with a boolean array. + * + * @param rows Array of row indexes + * + * Allowed inputs are in rows and columns params are: + * + * - An array of single integer, e.g. ``[5]``. + * - A list or array of integers, e.g. ``[4, 3, 0]``. + * - A slice array string with ints, e.g. ``["1:7"]``. + * - A boolean array. + * - A ``callable`` function with one argument (the calling Series or + * DataFrame) and that returns valid output for indexing (one of the above). + * This is useful in method chains, when you don't have a reference to the + * calling object, but would like to base your selection on some value. + * + * ``.iloc`` will raise ``IndexError`` if a requested indexer is + * out-of-bounds. + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.iloc([0, 2, 4]); + * sf2.print(); + * ``` + */ + iloc(rows: Array): Series { + return _iloc({ ndFrame: this, rows }) as Series + } + + /** + * Access a group of rows by label(s) or a boolean array. + * ``loc`` is primarily label based, but may also be used with a boolean array. + * + * @param rows Array of row indexes + * + * Allowed inputs are: + * + * - A single label, e.g. ``["5"]`` or ``['a']``, (note that ``5`` is interpreted as a + * *label* of the index, and **never** as an integer position along the index). + * + * - A list or array of labels, e.g. ``['a', 'b', 'c']``. + * + * - A slice object with labels, e.g. ``["a:f"]``. Note that start and the stop are included + * + * - A boolean array of the same length as the axis being sliced, + * e.g. ``[True, False, True]``. + * + * - A ``callable`` function with one argument (the calling Series or + * DataFrame) and that returns valid output for indexing (one of the above) + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.loc(['a', 'c', 'e']); + * sf2.print(); + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.loc(sf.gt(2)); + * sf2.print(); + * ``` + */ + loc(rows: Array): Series { + return _loc({ ndFrame: this, rows }) as Series + } + + /** + * Returns the first n values in a Series + * @param rows The number of rows to return + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.head(3); + * sf2.print(); + * ``` + */ + head(rows: number = 5): Series { + if (rows <= 0) { + throw new Error("ParamError: Number of rows cannot be less than 1") + } + if (this.shape[0] <= rows) { + return this.copy() + } + if (this.shape[0] - rows < 0) { + throw new Error("ParamError: Number of rows cannot be greater than available rows in data") + } + return this.iloc([`0:${rows}`]) + } + + /** + * Returns the last n values in a Series + * @param rows The number of rows to return + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.tail(3); + * sf2.print(); + * ``` + */ + tail(rows: number = 5): Series { + if (rows <= 0) { + throw new Error("ParamError: Number of rows cannot be less than 1") + } + if (this.shape[0] <= rows) { + return this.copy() + } + if (this.shape[0] - rows < 0) { + throw new Error("ParamError: Number of rows cannot be greater than available rows in data") + } + + const startIdx = this.shape[0] - rows + return this.iloc([`${startIdx}:`]) + } + + /** + * Returns specified number of random rows in a Series + * @param num The number of rows to return + * @param options.seed An integer specifying the random seed that will be used to create the distribution. + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const df2 = await df.sample(2) + * df2.print() + * ``` + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const df2 = await df.sample(1, { seed: 1 }) + * df2.print() + * ``` + */ + async sample(num = 5, options?: { seed?: number }): Promise { + const { seed } = { seed: 1, ...options } + + if (num > this.shape[0]) { + throw new Error("Sample size n cannot be bigger than size of dataset"); + } + if (num < -1 || num == 0) { + throw new Error("Sample size cannot be less than -1 or be equal to 0"); + } + num = num === -1 ? this.shape[0] : num; + + const shuffledIndex = await tensorflow.data.array(this.index).shuffle(num, `${seed}`).take(num).toArray(); + const sf = this.iloc(shuffledIndex); + return sf; + } + + /** + * Return Addition of series and other, element-wise (binary operator add). + * Equivalent to series + other + * @param other Series, Array of same length or scalar number to add + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.add(2); + * console.log(sf2.values); + * //output [3, 4, 5, 6, 7, 8] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.add([2, 3, 4, 5, 6, 7]); + * console.log(sf2.values); + * //output [3, 5, 7, 9, 11, 13] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * sf.add(2, { inplace: true }); + * console.log(sf.values); + * //output [3, 4, 5, 6, 7, 8] + * ``` + */ + add(other: Series | Array | number, options?: { inplace?: boolean }): Series + add(other: Series | Array | number, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("add") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "add" }) + + if (inplace) { + this.$setValues(newData as ArrayType1D) + } else { + return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }) as Series + } + } + + /** + * Returns the subtraction between a series and other, element-wise (binary operator subtraction). + * Equivalent to series - other + * @param other Number to subtract + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.sub(2); + * console.log(sf2.values); + * //output [-1, 0, 1, 2, 3, 4] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.sub([2, 3, 4, 5, 6, 7]); + * console.log(sf2.values); + * //output [-1, -1, -1, -1, -1, -1] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * sf.sub(2, { inplace: true }); + * console.log(sf.values); + * //output [-1, 0, 1, 2, 3, 4] + * ``` + */ + sub(other: Series | number | Array, options?: { inplace?: boolean }): Series + sub(other: Series | number | Array, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("sub") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "sub" }) + + if (inplace) { + this.$setValues(newData as ArrayType1D) + } else { + return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }) as Series + } + + } + + /** + * Return Multiplication of series and other, element-wise (binary operator mul). + * Equivalent to series * other + * @param other Number to multiply with. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.mul(2); + * console.log(sf2.values); + * //output [2, 4, 6, 8, 10, 12] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.mul([2, 3, 4, 5, 6, 7]); + * console.log(sf2.values); + * //output [2, 6, 12, 20, 30, 42] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * sf.mul(2, { inplace: true }); + * console.log(sf.values); + * //output [2, 4, 6, 8, 10, 12] + * ``` + */ + mul(other: Series | number | Array, options?: { inplace?: boolean }): Series + mul(other: Series | number | Array, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("mul") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "mul" }) + + if (inplace) { + this.$setValues(newData as ArrayType1D) + } else { + return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }) as Series + } + } + + /** + * Return division of series and other, element-wise (binary operator div). + * Equivalent to series / other + * @param other Series or number to divide with. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.div(2); + * console.log(sf2.values); + * //output [0.5, 1, 1.5, 2, 2.5, 3] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.div([2, 3, 4, 5, 6, 7]); + * console.log(sf2.values); + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * sf.div(2, { inplace: true }); + * console.log(sf.values); + * //output [0.5, 1, 1.5, 2, 2.5, 3] + * ``` + */ + div(other: Series | number | Array, options?: { inplace?: boolean }): Series + div(other: Series | number | Array, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("div") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "div" }) + + if (inplace) { + this.$setValues(newData as ArrayType1D) + } else { + return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }) as Series + } + } + + /** + * Return Exponential power of series and other, element-wise (binary operator pow). + * Equivalent to series ** other + * @param other Number to raise to power. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.pow(2); + * console.log(sf2.values); + * //output [1, 4, 9, 16, 25, 36] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.pow(new Series([2, 3, 4, 5, 6, 7])); + * console.log(sf2.values); + * //output [ 1, 8, 81, 1024, 15625, 279936 ] + * ``` + * + */ + pow(other: Series | number | Array, options?: { inplace?: boolean }): Series + pow(other: Series | number | Array, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("pow") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "pow" }) + + if (inplace) { + this.$setValues(newData as ArrayType1D) + } else { + return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }) as Series + } + } + + /** + * Return Modulo of series and other, element-wise (binary operator mod). + * Equivalent to series % other + * @param other Number to modulo with + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.mod(2); + * console.log(sf2.values); + * //output [1, 0, 1, 0, 1, 0] + * ``` + */ + mod(other: Series | number | Array, options?: { inplace?: boolean }): Series + mod(other: Series | number | Array, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("mod") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "mod" }) + + if (inplace) { + this.$setValues(newData as ArrayType1D) + } else { + return utils.createNdframeFromNewDataWithOldProps({ ndFrame: this, newData, isSeries: true }) as Series + } + } + + /** + * Checks if the array value passed has a compatible dtype, removes NaN values, and if + * boolean values are present, converts them to integer values. + */ + private $checkAndCleanValues(values: ArrayType1D, operation: string): number[] { + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError(operation) + values = utils.removeMissingValuesFromArray(values); + + if (this.dtypes[0] == "boolean") { + values = (utils.mapBooleansToIntegers(values as boolean[], 1) as ArrayType1D); + } + return values as number[] + } + + /** + * Returns the mean of elements in Series. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.mean()); + * //output 3.5 + * ``` + */ + mean(): number { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "mean") + return (values.reduce((a, b) => a + b) / values.length) as number + } + + + /** + * Returns the median of elements in Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.median()); + * //output 3.5 + * ``` + */ + median(): number { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "median") + return median(values); + } + + /** + * Returns the modal value of elements in Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 4, 5, 6]); + * console.log(sf.mode()); + * //output [ 4 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 4, 5, 5, 6]); + * console.log(sf.mode()); + * //output [ 4, 5 ] + * ``` + * + */ + mode() { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "mode") + return mode(values); + } + + /** + * Returns the minimum value in a Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.min()); + * //output 1 + * ``` + * + */ + min(): number { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "min") + let smallestValue = values[0] + for (let i = 0; i < values.length; i++) { + smallestValue = smallestValue < values[i] ? smallestValue : values[i] + } + return smallestValue + } + + /** + * Returns the maximum value in a Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.max()); + * //output 6 + * ``` + */ + max(): number { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "max") + let biggestValue = values[0] + for (let i = 0; i < values.length; i++) { + biggestValue = biggestValue > values[i] ? biggestValue : values[i] + } + return biggestValue + } + + /** + * Return the sum of the values in a series. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.sum()); + * //output 21 + * ``` + */ + sum(): number { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "sum") + return values.reduce((sum, value) => sum + value, 0) + } + + /** + * Return number of non-null elements in a Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.count()); + * //output 6 + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, NaN]); + * console.log(sf.count()); + * //output 6 + * ``` + */ + count(): number { + const values = utils.removeMissingValuesFromArray(this.values as ArrayType1D) + return values.length + } + + /** + * Return maximum of series and other. + * @param other Series, number or Array of numbers to check against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.maximum(3); + * console.log(sf2.values); + * //output [ 3, 3, 3, 4, 5, 6 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = new Series([4, 1, 3, 40, 5, 3]); + * const sf3 = sf.maximum(sf2); + * console.log(sf3.values); + * //output [ 4, 2, 3, 40, 5, 6 ] + * ``` + */ + maximum(other: Series | number | Array): Series { + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("maximum") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "maximum" }) + return new Series(newData, { + columns: this.columns, + index: this.index + }); + } + + /** + * Return minimum of series and other. + * @param other Series, number of Array of numbers to check against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.minimum(3); + * console.log(sf2.values); + * //output [ 1, 2, 3, 3, 3, 3 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = new Series([4, 1, 3, 40, 5, 3]); + * const sf3 = sf.minimum(sf2); + * console.log(sf3.values); + * //output [ 1, 1, 3, 4, 5, 3 ] + * ``` + * + */ + minimum(other: Series | number | Array): Series { + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("maximum") + + const newData = _genericMathOp({ ndFrame: this, other, operation: "minimum" }) + return new Series(newData, { + columns: this.columns, + index: this.index + }); + } + + /** + * Round each value in a Series to the specified number of decimals. + * @param dp Number of Decimal places to round to + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const sf = new Series([1.23, 2.4, 3.123, 4.1234, 5.12345]); + * const sf2 = sf.round(2); + * console.log(sf2.values); + * //output [ 1.23, 2.4, 3.12, 4.12, 5.12 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1.23, 2.4, 3.123, 4.1234, 5.12345]); + * sf.round(2, { inplace: true }); + * console.log(sf.values); + * //output [ 1.23, 2.4, 3.12, 4.12, 5.12 ] + * ``` + */ + round(dp?: number, options?: { inplace?: boolean }): Series + round(dp = 1, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + if (dp === undefined) dp = 1; + const newValues = utils.round(this.values as number[], dp, true); + + if (inplace) { + this.$setValues(newValues) + } else { + return utils.createNdframeFromNewDataWithOldProps({ + ndFrame: this, + newData: newValues, + isSeries: true + }) as Series + } + + } + + /** + * Return sample standard deviation of elements in Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.std()); + * //output 1.8708286933869707 + * ``` + */ + std(): number { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "max") + return std(values); + } + + /** + * Return unbiased variance of elements in a Series. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * console.log(sf.var()); + * //output 3.5 + * ``` + */ + var(): number { + const values = this.$checkAndCleanValues(this.values as ArrayType1D, "max") + return variance(values); + } + + /** + * Return a boolean same-sized object indicating where elements are NaN. + * NaN and undefined values gets mapped to true, and everything else gets mapped to false. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, NaN, 6]); + * console.log(sf.isNaN()); + * //output [ false, false, false, false, true, false ] + * ``` + * + */ + isNa(): Series { + const newData = this.values.map((value) => { + + if (utils.isEmpty(value)) { + return true; + } else { + return false; + } + }) + const sf = new Series(newData, + { + index: this.index, + dtypes: ["boolean"], + config: this.config + }); + return sf; + } + + /** + * Replace all missing values with a specified value + * @param value The value to replace NaN with + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, NaN, 6]); + * const sf2 = sf.fillNa(-99); + * console.log(sf2.values); + * //output [ 1, 2, 3, 4, -99, 6 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, NaN, 6]); + * sf.fillNa(-99, { inplace: true }); + * console.log(sf.values); + * //output [ 1, 2, 3, 4, -99, 6 ] + * ``` + */ + fillNa(value: number | string | boolean, options?: { inplace?: boolean }): Series + fillNa(value: number | string | boolean, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (!value && typeof value !== "boolean" && typeof value !== "number") { + throw Error('ParamError: value must be specified'); + } + + const newValues: ArrayType1D = []; + (this.values as ArrayType1D).forEach((val) => { + if (utils.isEmpty(val)) { + newValues.push(value); + } else { + newValues.push(val); + } + }); + + if (inplace) { + this.$setValues(newValues) + } else { + return utils.createNdframeFromNewDataWithOldProps({ + ndFrame: this, + newData: newValues, + isSeries: true + }) as Series + } + } + + + /** + * Sort a Series in ascending or descending order by some criterion. + * @param options Method options + * @param ascending Whether to return sorted values in ascending order or not. Defaults to true + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([2, 1, 3, 4, 6, 5]); + * const sf2 = sf.sortValues(); + * console.log(sf2.values); + * //output [ 1, 2, 3, 4, 5, 6 ] + * ``` + */ + sortValues(options?: { ascending?: boolean, inplace?: boolean }): Series + sortValues(options?: { ascending?: boolean, inplace?: boolean }): Series | void { + const { ascending, inplace, } = { ascending: true, inplace: false, ...options } + + let sortedValues = []; + let sortedIndex = [] + const rangeIdx = utils.range(0, this.index.length - 1); + let sortedIdx = utils.sortArrayByIndex(rangeIdx, this.values, this.dtypes[0]); + + for (let indx of sortedIdx) { + sortedValues.push(this.values[indx]) + sortedIndex.push(this.index[indx]) + } + + if (ascending) { + sortedValues = sortedValues.reverse(); + sortedIndex = sortedIndex.reverse(); + } + + if (inplace) { + this.$setValues(sortedValues as ArrayType1D) + this.$setIndex(sortedIndex); + } else { + const sf = new Series(sortedValues, { + index: sortedIndex, + dtypes: this.dtypes, + config: this.config + }); + return sf; + + } + } + + + /** + * Makes a deep copy of a Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.copy(); + * ``` + * + */ + copy(): Series { + const sf = new Series([...this.values], { + columns: [...this.columns], + index: [...this.index], + dtypes: [...this.dtypes], + config: { ...this.config } + }); + return sf; + } + + + /** + * Generate descriptive statistics. + * Descriptive statistics include those that summarize the central tendency, + * dispersion and shape of a dataset’s distribution, excluding NaN values. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.describe(); + * sf2.print(); + * ``` + */ + describe(): Series { + if (this.dtypes[0] == "string") { + throw new Error("DType Error: Cannot generate descriptive statistics for Series with string dtype") + } else { + + const index = ['count', 'mean', 'std', 'min', 'median', 'max', 'variance']; + const count = this.count(); + const mean = this.mean(); + const std = this.std(); + const min = this.min(); + const median = this.median(); + const max = this.max(); + const variance = this.var(); + + const data = [count, mean, std, min, median, max, variance]; + const sf = new Series(data, { index: index }); + return sf; + + } + } + + + /** + * Resets the index of the Series to default values. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.resetIndex(); + * console.log(sf2.index); + * //output [ 0, 1, 2, 3, 4, 5 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * sf.resetIndex({ inplace: true }); + * console.log(sf.index); + * //output [ 0, 1, 2, 3, 4, 5 ] + * ``` + */ + resetIndex(options?: { inplace?: boolean }): Series + resetIndex(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (inplace) { + this.$resetIndex(); + } else { + const sf = this.copy(); + sf.$resetIndex(); + return sf; + } + } + + /** + * Set the Series index (row labels) using an array of the same length. + * @param index Array of new index values, + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['a', 'b', 'c', 'd', 'e', 'f'] }); + * const sf2 = sf.setIndex(['g', 'h', 'i', 'j', 'k', 'l']); + * console.log(sf2.index); + * //output [ 'g', 'h', 'i', 'j', 'k', 'l' ] + * ``` + */ + setIndex(index: Array, options?: { inplace?: boolean }): Series + setIndex(index: Array, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (!index) { + throw Error('Param Error: Must specify index array'); + } + + if (inplace) { + this.$setIndex(index) + } else { + const sf = this.copy(); + sf.$setIndex(index) + return sf; + } + } + + + /** + * map all the element in a Series to a function or object. + * @param callable callable can either be a funtion or an object. If function, then each value and the corresponding index is passed. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.map((x) => x * 2); + * console.log(sf2.values); + * //output [ 2, 4, 6, 8, 10, 12 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.map({ + * 1: -99, + * 3: -99 + * }); + * console.log(sf2.values); + * //output [ -99, 2, -99, 4, -99, 6 ] + * ``` + */ + map(callable: mapParam, options?: { inplace?: boolean }): Series + map(callable: mapParam, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + const isCallable = utils.isFunction(callable); + + const data = (this.values as ArrayType1D).map((val: any, i: number) => { + if (isCallable) { + return (callable as Function)(val, i); + } else if (utils.isObject(callable)) { + if (val in callable) { + //@ts-ignore + return callable[val]; + } else { + return val + } + } else { + throw new Error("Param Error: callable must either be a function or an object"); + } + }); + + if (inplace) { + this.$setValues(data) + } else { + const sf = this.copy(); + sf.$setValues(data) + return sf; + } + } + + /** + * Applies a function to each element of a Series + * @param callable Function to apply to each element of the series + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.apply((x) => x * 2); + * console.log(sf2.values); + * //output [ 2, 4, 6, 8, 10, 12 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * sf.apply((x) => x * 2, { inplace: true }); + * console.log(sf.values); + * //output [ 2, 4, 6, 8, 10, 12 ] + * ``` + * + */ + apply(callable: (value: any) => any, options?: { inplace?: boolean }): Series + apply(callable: (value: any) => any, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + const isCallable = utils.isFunction(callable); + if (!isCallable) { + throw new Error("Param Error: callable must be a function"); + } + + const data = this.values.map((val) => { + return callable(val); + }); + + if (inplace) { + this.$setValues(data) + } else { + const sf = this.copy(); + sf.$setValues(data) + return sf; + } + } + + /** + * Returns a Series with only the unique value(s) in the original Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]); + * const sf2 = sf.unique(); + * console.log(sf2.values); + * //output [ 1, 2, 3, 4, 5, 6 ] + * ``` + */ + unique(): Series { + const newValues = new Set(this.values as ArrayType1D); + let series = new Series(Array.from(newValues)); + return series; + } + + /** + * Return the number of unique elements in a Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]); + * console.log(sf.nUnique()); + * //output 6 + * ``` + * + */ + nUnique(): number { + return (new Set(this.values as ArrayType1D)).size; + } + + /** + * Returns unique values and their counts in a Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]); + * const sf2 = sf.valueCounts(); + * sf2.print(); + * ``` + */ + valueCounts(): Series { + const sData = this.values; + const dataDict: any = {}; + for (let i = 0; i < sData.length; i++) { + const val = sData[i]; + if (`${val}` in dataDict) { + dataDict[`${val}`] = dataDict[`${val}`] + 1; + } else { + dataDict[`${val}`] = 1; + } + } + + const index = Object.keys(dataDict).map((x) => { + return parseInt(x) ? parseInt(x) : x; + }); + const data = Object.values(dataDict); + + const series = new Series(data, { index: index }); + return series; + + } + + /** + * Returns the absolute of values in Series + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, -2, 3, -4, 5, -6]); + * const sf2 = sf.abs(); + * console.log(sf2.values); + * //output [ 1, 2, 3, 4, 5, 6 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, -2, 3, -4, 5, -6]); + * sf.abs({ inplace: true }); + * console.log(sf.values); + * //output [ 1, 2, 3, 4, 5, 6 ] + * ``` + */ + abs(options?: { inplace?: boolean }): Series + abs(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError("abs") + let newValues; + + + newValues = this.values.map(val => Math.abs(val as number)); + + if (inplace) { + this.$setValues(newValues as ArrayType1D) + } else { + const sf = this.copy(); + sf.$setValues(newValues as ArrayType1D) + return sf; + } + } + + /** + * Returns the cumulative sum over a Series + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.cumsum(); + * console.log(sf2.values); + * //output [ 1, 3, 6, 10, 15, 21 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * sf.cumSum({ inplace: true }); + * console.log(sf.values); + * //output [ 1, 3, 6, 10, 15, 21 ] + * ``` + */ + cumSum(options?: { inplace?: boolean }): Series + cumSum(options?: { inplace?: boolean }): Series | void { + const ops = { inplace: false, ...options } + return this.cumOps("sum", ops); + } + + /** + * Returns cumulative minimum over a Series + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.cumMin(); + * console.log(sf2.values); + * //output [ 1, 1, 1, 1, 1, 1 ] + * ``` + * + */ + cumMin(options?: { inplace?: boolean }): Series + cumMin(options?: { inplace?: boolean }): Series | void { + const ops = { inplace: false, ...options } + return this.cumOps("min", ops); + } + + + /** + * Returns cumulative maximum over a Series + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.cumMax(); + * console.log(sf2.values); + * //output [ 1, 2, 3, 4, 5, 6 ] + * ``` + */ + cumMax(options?: { inplace?: boolean }): Series + cumMax(options?: { inplace?: boolean }): Series | void { + const ops = { inplace: false, ...options } + return this.cumOps("max", ops); + } + + /** + * Returns cumulative product over a Series + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.cumProd(); + * console.log(sf2.values); + * //output [ 1, 2, 6, 24, 120, 720 ] + * ``` + */ + cumProd(options?: { inplace?: boolean }): Series + cumProd(options?: { inplace?: boolean }): Series | void { + const ops = { inplace: false, ...options } + return this.cumOps("prod", ops); + } + + /** + * Internal helper function to calculate cumulative operations on series data + */ + private cumOps(ops: string, options: { inplace: boolean }): Series | void { + if (this.dtypes[0] == "string") ErrorThrower.throwStringDtypeOperationError(ops) + const { inplace } = options; + + const sData = this.values; + let tempval = sData[0]; + const data = [tempval]; + + for (let i = 1; i < sData.length; i++) { + let currVal = sData[i]; + switch (ops) { + case "max": + if (currVal > tempval) { + data.push(currVal); + tempval = currVal; + } else { + data.push(tempval); + } + break; + case "min": + if (currVal < tempval) { + data.push(currVal); + tempval = currVal; + } else { + data.push(tempval); + } + break; + case "sum": + tempval = (tempval as number) + (currVal as number) + data.push(tempval); + break; + case "prod": + tempval = (tempval as number) * (currVal as number) + data.push(tempval); + break; + + } + } + + if (inplace) { + this.$setValues(data as ArrayType1D) + } else { + return new Series(data, { + index: this.index, + config: { ...this.config } + }); + } + } + + + /** + * Returns less than of series and other. Supports element wise operations + * @param other Series, number, or Array of numbers to compare against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.lt(3); + * console.log(sf2.values); + * //output [ true, true, false, false, false, false ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.lt([3, 4, 5, 6, 7, 8]); + * console.log(sf2.values); + * //output [ true, true, false, false, false, false ] + * ``` + */ + lt(other: Series | number | Array | boolean[]): Series { + return this.boolOps(other, "lt"); + } + + /** + * Returns Greater than of series and other. Supports element wise operations + * @param other Series, number or Array of numbers to compare against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.gt(3); + * console.log(sf2.values); + * //output [ false, false, true, true, true, true ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.gt([3, 4, 5, 6, 7, 8]); + * console.log(sf2.values); + * //output [ false, false, true, true, true, true ] + * ``` + */ + gt(other: Series | number | Array | boolean[]): Series { + return this.boolOps(other, "gt"); + } + + /** + * Returns Less than or Equal to of series and other. Supports element wise operations + * @param other Series, number or Array of numbers to compare against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.le(3); + * console.log(sf2.values); + * //output [ true, true, true, true, false, false ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.le([3, 4, 5, 6, 7, 8]); + * console.log(sf2.values); + * //output [ true, true, true, true, false, false ] + * ``` + * + */ + le(other: Series | number | Array | boolean[]): Series { + return this.boolOps(other, "le"); + } + + /** + * Returns Greater than or Equal to of series and other. Supports element wise operations + * @param other Series, number or Array of numbers to compare against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.ge(3); + * console.log(sf2.values); + * //output [ false, false, true, true, true, true ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.ge([3, 4, 5, 6, 7, 8]); + * console.log(sf2.values); + * //output [ false, false, true, true, true, true ] + * ``` + */ + ge(other: Series | number | Array | boolean[]): Series { + return this.boolOps(other, "ge"); + } + + /** + * Returns Not Equal to of series and other. Supports element wise operations + * @param other Series, number or Array of numbers to compare against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.ne(3); + * console.log(sf2.values); + * //output [ true, true, false, true, true, true ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.ne([3, 2, 5, 6, 7, 8]); + * console.log(sf2.values); + * //output [ true, false, true, true, true, true ] + * ``` + * + */ + ne(other: Series | number | Array | boolean[]): Series { + return this.boolOps(other, "ne"); + } + + /** + * Returns Equal to of series and other. Supports element wise operations + * @param other Series, number or Array of numbers to compare against + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.eq(3); + * console.log(sf2.values); + * //output [ false, false, true, false, false, false ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.eq(new Series([3, 2, 5, 6, 7, 8])); + * console.log(sf2.values); + * //output [ false, true, false, false, false, false ] + * ``` + */ + eq(other: Series | number | Array | boolean[]): Series { + return this.boolOps(other, "eq"); + } + + /** + * Internal function to perform boolean operations + * @param other Other Series or number to compare with + * @param bOps Name of operation to perform [ne, ge, le, gt, lt, eq] + */ + private boolOps(other: Series | number | Array | boolean[], bOps: string) { + const data = []; + const lSeries = this.values; + let rSeries; + + if (typeof other == "number") { + rSeries = Array(this.values.length).fill(other); //create array of repeated value for broadcasting + } else if (typeof other == "string" && ["eq", "ne"].includes(bOps)) { + rSeries = Array(this.values.length).fill(other); + } else if (other instanceof Series) { + rSeries = other.values; + } else if (Array.isArray(other)) { + rSeries = other; + } else { + throw new Error("ParamError: value for other not supported. It must be either a scalar, Array or Series"); + } + + if (!(lSeries.length === rSeries.length)) { + throw new Error("LengthError: length of other must be equal to length of Series"); + } + + + for (let i = 0; i < lSeries.length; i++) { + let lVal = lSeries[i]; + let rVal = rSeries[i]; + let bool = null; + switch (bOps) { + case "lt": + bool = lVal < rVal ? true : false; + data.push(bool); + break; + case "gt": + bool = lVal > rVal ? true : false; + data.push(bool); + break; + case "le": + bool = lVal <= rVal ? true : false; + data.push(bool); + break; + case "ge": + bool = lVal >= rVal ? true : false; + data.push(bool); + break; + case "ne": + bool = lVal !== rVal ? true : false; + data.push(bool); + break; + case "eq": + bool = lVal === rVal ? true : false; + data.push(bool); + break; + } + } + return new Series(data, { + index: this.index, + config: { ...this.config } + }); + } + + /** + * Replace all occurence of a value with a new value + * @param oldValue The value you want to replace + * @param newValue The new value you want to replace the old value with + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * const sf2 = sf.replace(3, 10); + * console.log(sf2.values); + * //output [ 1, 2, 10, 4, 5, 6 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6]); + * sf.replace(3, 10, { inplace: true }); + * console.log(sf.values); + * //output [ 1, 2, 10, 4, 5, 6 ] + * ``` + */ + replace( + oldValue: string | number | boolean, + newValue: string | number | boolean, + options?: { inplace?: boolean } + ): Series + replace( + oldValue: string | number | boolean, + newValue: string | number | boolean, + options?: { inplace?: boolean } + ): Series | void { + const { inplace } = { inplace: false, ...options } + + if (typeof oldValue === 'number' && isNaN(oldValue)) { + throw Error(`Params Error: Param 'oldValue' does not support NaN. Use Series.fillNa() instead.`); + } + + if (!oldValue && typeof oldValue !== 'boolean' && typeof oldValue !== 'number' && typeof oldValue !== 'string') { + throw Error(`Params Error: Must specify param 'oldValue' to replace`); + } + + if (!newValue && typeof newValue !== 'boolean' && typeof newValue !== 'number' && typeof newValue !== 'string') { + throw Error(`Params Error: Must specify param 'newValue' to replace with`); + } + + const newArr = [...this.values].map((val) => { + if (val === oldValue) { + return newValue + } else { + return val + } + }); + + if (inplace) { + this.$setValues(newArr as ArrayType1D) + } else { + const sf = this.copy(); + sf.$setValues(newArr as ArrayType1D) + return sf; + } + + } + + /** + * Drops all missing values (NaN, null, undefined) from a Series. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const sf = new Series([1, 2, NaN, 4, 5, NaN]); + * const sf2 = sf.dropNa(); + * console.log(sf2.values); + * //output [ 1, 2, 4, 5 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, NaN, 4, 5, null]); + * sf.dropNa({ inplace: true }); + * console.log(sf.values); + * //output [ 1, 2, 4, 5 ] + * ``` + */ + dropNa(options?: { inplace?: boolean }): Series + dropNa(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + const oldValues = this.values; + const oldIndex = this.index; + const newValues: ArrayType1D = []; + const newIndex: Array = []; + const isNaVals = this.isNa().values; + + isNaVals.forEach((val, i) => { + if (!val) { + newValues.push((oldValues as ArrayType1D)[i]); + newIndex.push(oldIndex[i]) + } + }); + + if (inplace) { + this.$setValues(newValues, false) + this.$setIndex(newIndex) + } else { + const sf = this.copy(); + sf.$setValues(newValues, false) + sf.$setIndex(newIndex) + return sf; + } + + } + + /** + * Returns the integer indices that would sort the Series. + * @param ascending Boolean indicating whether to sort in ascending order or not. Defaults to true + * @example + * ``` + * const sf = new Series([3, 1, 2]); + * const sf2 = sf.argSort(); + * console.log(sf2.values); + * //output [ 1, 2, 0 ] + * ``` + * + * @example + * ``` + * const sf = new Series([3, 1, 2]); + * const sf2 = sf.argSort({ascending: false}); + * console.log(sf2.values); + * //output [ 0, 2, 1 ] + * + */ + argSort(options?: { ascending: boolean }): Series { + const { ascending } = { ascending: true, ...options } + const sortedIndex = this.sortValues({ ascending }); + const sf = new Series(sortedIndex.index); + return sf; + } + + /** + * Returns integer position of the largest value in the Series. + * @example + * ``` + * const sf = new Series([3, 1, 2]); + * const sf2 = sf.argMax(); + * console.log(sf2); + * //output 0 + * ``` + * + */ + argMax(): number { + return this.tensor.argMax().arraySync() as number + } + + + /** + * Returns integer position of the smallest value in the Series. + * @example + * ``` + * const sf = new Series([3, 1, 2]); + * const sf2 = sf.argMin(); + * console.log(sf2); + * //output 1 + * ``` + * + */ + argMin(): number { + return this.tensor.argMin().arraySync() as number + } + + /** + * Remove duplicate values from a Series + * @param keep "first" | "last", which dupliate value to keep. Defaults to "first". + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * const sf2 = sf.dropDuplicates(); + * console.log(sf2.values); + * //output [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * sf.dropDuplicates({ keep: "last", inplace: true }); + * console.log(sf.values); + * //output [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] + * ``` + * + */ + dropDuplicates(options?: { keep?: "first" | "last", inplace?: boolean }): Series + dropDuplicates(options?: { keep?: "first" | "last", inplace?: boolean }): Series | void { + const { keep, inplace } = { keep: "first", inplace: false, ...options } + + if (!(["first", "last"].includes(keep))) { + throw Error(`Params Error: Keep must be one of 'first' or 'last'`); + } + + let dataArr: ArrayType1D + let newArr: ArrayType1D = []; + let oldIndex: Array + let newIndex: Array = []; + + if (keep === "last") { + dataArr = (this.values as ArrayType1D).reverse(); + oldIndex = this.index.reverse(); + } else { + dataArr = (this.values as ArrayType1D) + oldIndex = this.index; + } + + dataArr.forEach((val, i) => { + if (!newArr.includes(val)) { + newIndex.push(oldIndex[i]); + newArr.push(val); + } + }); + + if (keep === "last") { + //re-reversed the array and index to its true order + newArr = newArr.reverse(); + newIndex = newIndex.reverse(); + } + + if (inplace) { + this.$setValues(newArr, false) + this.$setIndex(newIndex) + } else { + const sf = this.copy(); + sf.$setValues(newArr, false) + sf.$setIndex(newIndex) + return sf; + } + + } + + /** + * Cast Series to specified data type + * @param dtype Data type to cast to. One of [float32, int32, string, boolean, undefined] + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * const sf2 = sf.asType("float32"); + * console.log(sf2.dtype); + * //output "float32" + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * sf.asType("float32", {inplace: true}); + * console.log(sf.dtype); + * //output "float32" + * ``` + */ + asType(dtype: "float32" | "int32" | "string" | "boolean" | "undefined", options?: { inplace?: boolean }): Series + asType(dtype: "float32" | "int32" | "string" | "boolean" | "undefined", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + + if (!dtype) { + throw Error("Param Error: Please specify dtype to cast to"); + } + + if (!(DATA_TYPES.includes(dtype))) { + throw Error(`dtype ${dtype} not supported. dtype must be one of ${DATA_TYPES}`); + } + + const oldValues = [...this.values]; + const newValues: ArrayType1D = []; + + switch (dtype) { + case "float32": + oldValues.forEach((val) => { + newValues.push(Number(val)); + }); + break; + case "int32": + oldValues.forEach((val) => { + newValues.push(parseInt(val as any)); + }); + break; + case "string": + oldValues.forEach((val) => { + newValues.push(String(val)); + }); + break; + case "boolean": + oldValues.forEach((val) => { + newValues.push(Boolean(val)); + }); + break; + case "undefined": + oldValues.forEach((_) => { + newValues.push(NaN); + }); + break; + default: + break; + } + + if (inplace) { + this.$setValues(newValues, false) + this.$setDtypes([dtype]) + } else { + const sf = this.copy(); + sf.$setValues(newValues, false) + sf.$setDtypes([dtype]) + return sf; + } + + } + + /** + * Appends a new value or values to the end of the Series + * @param newValue Single value | Array | Series to append to the Series + * @param index The new index value(s) to append to the Series. Must contain the same number of values as `newValues` + * as they map `1 - 1`. + * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * sf.append(11); + * console.log(sf.values); + * //output [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * sf.append([11, 12, 13]); + * console.log(sf.values); + * //output [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ] + * ``` + * + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * sf.append(new Series([11, 12, 13]), { inplace: true}); + * console.log(sf.values); + * //output [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ] + * ``` + */ + append( + newValue: string | number | boolean | Series | ArrayType1D, + index: Array | number | string, + options?: { inplace?: boolean } + ): Series + append( + newValue: string | number | boolean | Series | ArrayType1D, + index: Array | number | string, + options?: { inplace?: boolean } + ): Series | void { + const { inplace } = { inplace: false, ...options } + + if (!newValue && typeof newValue !== "boolean" && typeof newValue !== "number") { + throw Error("Param Error: newValue cannot be null or undefined"); + } + + if (!index) { + throw Error("Param Error: index cannot be null or undefined"); + } + + const newData = [...this.values] + const newIndx = [...this.index] + + if (Array.isArray(newValue) && Array.isArray(index)) { + + if (newValue.length !== index.length) { + throw Error("Param Error: Length of new values and index must be the same"); + } + + newValue.forEach((el, i) => { + newData.push(el); + newIndx.push(index[i]); + }); + + } else if (newValue instanceof Series) { + const _value = newValue.values; + + if (!Array.isArray(index)) { + throw Error("Param Error: index must be an array"); + } + + if (index.length !== _value.length) { + throw Error("Param Error: Length of new values and index must be the same"); + } + + _value.forEach((el, i) => { + newData.push(el); + newIndx.push(index[i]); + }); + } else { + newData.push(newValue); + newIndx.push(index as string | number); + } + + if (inplace) { + this.$setValues(newData as ArrayType1D, false) + this.$setIndex(newIndx) + } else { + const sf = new Series( + newData, + { + index: newIndx, + columns: this.columns, + dtypes: this.dtypes, + config: this.config + }) + + return sf + } + } + + /** + * Returns dtype of Series + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + * console.log(sf.dtype); + * //output "int32" + * ``` + */ + get dtype(): string { + return this.dtypes[0]; + } + + /** + * Exposes numerous string methods to manipulate Series of string dtype + * @example + * ``` + * const sf = new Series(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]); + * const sfs = sf.str.join("HelloWorld", ""); + * console.log(sfs.values); + * //output ["aHelloWorld", "bHelloWorld", "cHelloWorld", "dHelloWorld", "eHelloWorld", "fHelloWorld", "gHelloWorld", "hHelloWorld", "iHelloWorld", "jHelloWorld"] + * ``` + */ + get str() { + if (this.dtypes[0] == "string") { + return new Str(this); + } else { + throw new Error("Cannot call accessor str on non-string type"); + } + } + + /** + * Returns time class that exposes different date time method + * @example + * ``` + * const sf = new Series([ + * "2020-01-01", + * "2020-01-02", + * "2020-01-03", + * "2020-01-04", + * "2020-01-05", + * ]); + * const sfd = sf.dt.dayOfWeekName(); + * console.log(sfd.values); + * //output [ 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ] + * ``` + */ + get dt() { + if (["string", "datetime"].includes(this.dtypes[0])) { + return new Dt(this) + } else { + throw new Error("Cannot call accessor dt on non-string type"); + } + } + + /** + * Overrides default toString implementation. This essentially makes `print()` works. + */ + toString(): string { + const maxRow = this.$config.getMaxRow; + let indx: (string | number)[] + let values = [] + + if (this.shape[0] > maxRow) { + //slice rows to show [max_rows] rows + const sfSlice = this.iloc([`0:${maxRow}`]); + + indx = sfSlice.index + values = sfSlice.values; + + } else { + indx = this.index + values = this.values; + } + + const tabledata = values.map((x, i) => [indx[i], x]) + return table(tabledata as any); + } + + /** + * Returns the logical AND between Series and other. Supports element wise operations and broadcasting. + * @param other Series, Scalar, Array of Scalars + * @example + * ``` + * const sf = new Series([true, true, false, false, true]); + * const sf2 = new Series([true, false, true, false, true]); + * const sf3 = sf.and(sf2); + * console.log(sf3.values); + * //output [ true, false, false, false, false ] + * ``` + */ + and(other: any): Series { + + if (other === undefined) { + throw new Error("Param Error: other cannot be undefined"); + } + const newValues: ArrayType1D = []; + + if (other instanceof Series) { + if (this.dtypes[0] !== other.dtypes[0]) { + throw new Error("Param Error: Series must be of same dtype"); + } + + if (this.shape[0] !== other.shape[0]) { + throw new Error("Param Error: Series must be of same shape"); + } + + this.values.forEach((val, i) => { + newValues.push(Boolean(val) && Boolean(other.values[i])); + }); + + } else if (typeof other === "boolean") { + + this.values.forEach((val) => { + newValues.push(Boolean(val) && Boolean(other)); + }); + + } else if (Array.isArray(other)) { + + this.values.forEach((val, i) => { + newValues.push(Boolean(val) && Boolean(other[i])); + }); + + } else { + throw new Error("Param Error: other must be a Series, Scalar, or Array of Scalars"); + } + return new Series(newValues, { + index: this.index, + config: { ...this.config } + }); + } + + /** + * Returns the logical OR between Series and other. Supports element wise operations and broadcasting. + * @param other Series, Scalar, Array of Scalars + * @example + * ``` + * const sf = new Series([true, true, false, false, true]); + * const sf2 = new Series([true, false, true, false, true]); + * const sf3 = sf.or(sf2); + * console.log(sf3.values); + * //output [ true, true, true, false, true ] + * ``` + * + */ + or(other: any): Series { + + if (other === undefined) { + throw new Error("Param Error: other cannot be undefined"); + } + const newValues: ArrayType1D = []; + + if (other instanceof Series) { + if (this.dtypes[0] !== other.dtypes[0]) { + throw new Error("Param Error: Series must be of same dtype"); + } + + if (this.shape[0] !== other.shape[0]) { + throw new Error("Param Error: Series must be of same shape"); + } + + this.values.forEach((val, i) => { + newValues.push(Boolean(val) || Boolean(other.values[i])); + }); + + } else if (typeof other === "boolean") { + + this.values.forEach((val) => { + newValues.push(Boolean(val) || Boolean(other)); + }); + + } else if (Array.isArray(other)) { + + this.values.forEach((val, i) => { + newValues.push(Boolean(val) || Boolean(other[i])); + }); + + } else { + throw new Error("Param Error: other must be a Series, Scalar, or Array of Scalars"); + } + + return new Series(newValues, { + index: this.index, + config: { ...this.config } + }); + } + + /** + * One-hot encode values in the Series. + * @param options Options for the operation. The following options are available: + * - `prefix`: Prefix to add to the new column. Defaults to unique labels. + * - `prefixSeparator`: Separator to use for the prefix. Defaults to '_'. + * @example + * ``` + * const sf = new Series(["a", "b", "c", "a"]); + * const sf2 = sf.getDummies({ prefix: "category" }); + * console.log(sf2.values); + * //output [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ] + * ``` + * + * @example + * ``` + * const sf = new Series(["a", "b", "c", "a"]); + * const sf2 = sf.getDummies({ prefix: "category", prefixSeparator: "-" }); + * console.log(sf2.values); + * //output [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ] + * ``` + */ + getDummies(options?: { + columns?: string | Array, + prefix?: string | Array, + prefixSeparator?: string, + }): DataFrame { + return dummyEncode(this, options) + } + + /** + * Access a single value for a row index. + * Similar to iloc, in that both provide index-based lookups. + * Use iat if you only need to get or set a single value in a Series. + * @param row Row index of the value to access. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5]) + * sf.iat(0) //returns 1 + * sf.iat(1) //returns 2 + * sf.iat(2) //returns 3 + * ``` + */ + iat(row: number): number | string | boolean | undefined { + if (typeof row === 'string') { + throw new Error('ParamError: row index must be an integer. Use .at to get a row by label.') + } + return (this.values as ArrayType1D)[row]; + } + + /** + * Access a single value for a row label. + * Similar to loc, in that both provide label-based lookups. + * Use at if you only need to get or set a single value in a Series. + * @param row Row label of the value to access. + * @example + * ``` + * const sf = new Series([1, 2, 3, 4, 5, 6], { index: ['A', 'B', 'C', 'D', 'E', 'F'] }) + * sf.at('A') //returns 1 + * sf.at('B') //returns 2 + * sf.at('C') //returns 3 + * ``` + */ + at(row: string): number | string | boolean | undefined { + if (typeof row !== 'string') { + throw new Error('ParamError: row index must be a string. Use .iat to get a row by index.') + } + return (this.values as ArrayType1D)[this.index.indexOf(row)]; + } + + /** + * Exposes functions for creating charts from a DataFrame. + * Charts are created using the Plotly.js library, so all Plotly's configuration parameters are available. + * @param divId name of the HTML Div to render the chart in. + */ + plot(divId: string): IPlotlyLib { + //TODO: Add support for check plot library to use. So we can support other plot library like d3, vega, etc + if (utils.isBrowserEnv()) { + const plt = new PlotlyLib(this, divId); + return plt; + } else { + throw new Error("Not supported in NodeJS"); + } + } +} diff --git a/src/danfojs-base/core/strings.ts b/src/danfojs-base/core/strings.ts new file mode 100644 index 00000000..0f5e2b68 --- /dev/null +++ b/src/danfojs-base/core/strings.ts @@ -0,0 +1,766 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { ArrayType1D } from "../shared/types"; +import Utils from "../shared/utils" +import Series from "./series"; + +const utils = new Utils(); +/** + * Exposes numerous String methods. All methods are applied Element-wise + */ +export default class Str { + private series: Series + private values: ArrayType1D + + constructor(series: Series) { + this.series = series; + this.values = (series.values as ArrayType1D); + } + + /** + * Converts all characters to lowercase. + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["GooD", "Bad", "CrAzy"]) + * const newSf = sf.str.toLowerCase() + * console.log(newSf.values) + * // ["good", "bad", "crazy"] + * ``` + */ + toLowerCase(options?: { inplace?: boolean }): Series + toLowerCase(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.toLowerCase()); + } + + }); + + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + + } + + /** + * Converts all characters to uppercase. + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["GooD", "Bad", "CrAzy"]) + * const newSf = sf.str.toUpperCase() + * console.log(newSf.values) + * // ["GOOD", "BAD", "CRAZY"] + * ``` + */ + toUpperCase(options?: { inplace?: boolean }): Series + toUpperCase(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.toUpperCase()); + } + + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + + } + } + + /** + * Capitalize first string + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "bad", "crazy"]) + * const newSf = sf.str.capitalize() + * console.log(newSf.values) + * // ["Good", "Bad", "Crazy"] + * ``` + */ + capitalize(options?: { inplace?: boolean }): Series + capitalize(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + let firstChar = `${val}`.slice(0, 1); + let leftChar = `${val}`.slice(1); + let newStr = `${firstChar.toUpperCase()}${leftChar.toLowerCase()}`; + newArr.push(newStr); + } + + }); + + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + + } + + /** + * Returns the character at the specified index (position) + * @param index position of character + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "bad", "crazy"]) + * const newSf = sf.str.charAt(1) + * console.log(newSf.values) + * // ["o", "a", "r"] + * ``` + */ + charAt(index: number, options?: { inplace?: boolean }): Series + charAt(index = 0, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.charAt(index)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Joins specified `other` with values in the Series. + * @param other string|values to concatenate with. + * @param position where to concat the string from. O concats from the start, 1 concats from the end. Defaults to 1. + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "bad", "crazy"]) + * const newSf = sf.str.concat("_new") + * console.log(newSf.values) + * // ["Good_new", "bad_new", "crazy_new" + * ``` + */ + concat(other: Array | string, position: number, options?: { inplace?: boolean }): Series + concat(other: Array | string, position = 1, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + + if (Array.isArray(other)) { + for (let i = 0; i < other.length; i++) { + let leftStr = `${this.values[i]}`; + let rightStr = `${other[i]}`; + if (position == 1) { + newArr.push(leftStr.concat(rightStr)); + } else { + newArr.push(rightStr.concat(leftStr)); + } + + } + } else { + this.values.map((val) => { + if (position == 1) { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.concat(`${other}`)); + } + + } else { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(other.concat(`${val}`)); + } + } + }); + } + + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + + } + + + /** + * Checks whether a string begins with specified characters + * @param str String or Character to check against + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "bad", "crazy"]) + * const newSf = sf.str.startsWith("G") + * console.log(newSf.values) + * // [true, false, false] + * ``` + */ + startsWith(str: string, options?: { inplace?: boolean }): Series + startsWith(str = "", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.forEach((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.startsWith(str)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Checks whether a string ends with specified characters + * @param str String or Character to check against + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "bad", "crazy"]) + * const newSf = sf.str.endsWith("d") + * console.log(newSf.values) + * // [true, true, false] + * ``` + */ + endsWith(str: string, options?: { inplace?: boolean }): Series + endsWith(str = "", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.endsWith(str)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Checks whether a string contains the specified string/characters + * @param str String or Character to check against + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "bad", "crazy"]) + * const newSf = sf.str.includes("d") + * console.log(newSf.values) + * // [true, true, false] + * ``` + */ + includes(str: string, options?: { inplace?: boolean }): Series + includes(str = "", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.includes(str)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Returns the position of the first occurrence of a specified value in a string. + * @param str String or Character to check against + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "bad", "crazy"]) + * const newSf = sf.str.indexOf("d") + * console.log(newSf.values) + * // [3, 2, -1] + * ``` + */ + indexOf(str: string, options?: { inplace?: boolean }): Series + indexOf(str = "", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.indexOf(str)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Returns the position of the last found occurrence of a specified value in a string + * @param str String or Character to check against + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "crazy"]) + * const newSf = sf.str.lastIndexOf("d") + * console.log(newSf.values) + * // [3, 2, -1] + * ``` + */ + lastIndexOf(str: string, options?: { inplace?: boolean }): Series + lastIndexOf(str = "", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.lastIndexOf(str)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + + /** + * Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced + * @param searchValue String | Character value to replace + * @param replaceValue String | Character string to replace with + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "crazy"]) + * const newSf = sf.str.replace("d", 7) + * console.log(newSf.values) + * // ["Goo7", "o77", "crazy"] + * ``` + */ + replace(searchValue: string, replaceValue: string, options?: { inplace?: boolean }): Series + replace(searchValue = "", replaceValue = "", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.replace(searchValue, replaceValue)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Returns a new string with a specified number of copies of an existing string + * @param num Number of times to repeat + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "crazy"]) + * const newSf = sf.str.replace(2) + * console.log(newSf.values) + * // ["GoodGood", "oddodd", "crazycrazy"] + * ``` + */ + repeat(num: number, options?: { inplace?: boolean }): Series + repeat(num = 1, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.repeat(num)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + + /** + * Searches a string for a specified value, or regular expression, and returns the position of the match + * @param str String or Character to check against + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "crazy"]) + * const newSf = sf.str.search("d") + * console.log(newSf.values) + * ``` + */ + search(str: string, options?: { inplace?: boolean }): Series + search(str = "", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.search(str)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Extracts a part of a string and returns a new string + * @param startIndex index position of start character + * @param endIndex index position of last character + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "crazy"]) + * const newSf = sf.str.slice(0,1) + * console.log(newSf.values) + * // ["G", "o", "c"] + * ``` + */ + slice(startIndex: number, endIndex: number, options?: { inplace?: boolean }): Series + slice(startIndex = 0, endIndex = 1, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.slice(startIndex, endIndex)); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Splits a string into an values of substrings + * @param splitVal string or character to split at + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "grade"]) + * const newSf = sf.str.split(d) + * console.log(newSf.values) + * ``` + */ + split(splitVal: string, options?: { inplace?: boolean }): Series + split(splitVal = " ", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${String(val).split(splitVal)}`); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Extracts the characters from a string, beginning at a specified start position, and through the specified number of character + * @param startIndex index position of start character + * @param num number of characters to return + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "grade"]) + * const newSf = sf.str.substr(d) + * ``` + */ + substr(startIndex: number, num: number, options?: { inplace?: boolean }): Series + substr(startIndex = 0, num = 1, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${String(val).substr(startIndex, num)}`); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Extracts the characters from a string, between two specified indices + * @param startIndex index position of start character + * @param endIndex index position of last character + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "grade"]) + * const newSf = sf.str.substring(d) + * ``` + */ + substring(startIndex: number, endIndex: number, options?: { inplace?: boolean }): Series + substring(startIndex = 0, endIndex = 1, options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${String(val).substring(startIndex, endIndex)}`); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Removes whitespace from both ends of a string + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series([" Good", "odd ", " grade "]) + * const newSf = sf.str.trim(d) + * ["Good", "odd", "grade"] + * ``` + */ + trim(options?: { inplace?: boolean }): Series + trim(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.trim()); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Joins strings to specified value + * @param valToJoin string value to join to the values + * @param joinChar Character to Join with + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "grade"]) + * const newSf = sf.str.join("new", "_") + * // ["Good_new", "odd_new", "grade_new"] + * ``` + */ + join(valToJoin: string, joinChar: string, options?: { inplace?: boolean }): Series + join(valToJoin = "", joinChar = " ", options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + let leftChar = val; + let rightChar = valToJoin; + let new_char = `${leftChar}${joinChar}${rightChar}`; + newArr.push(new_char); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + + /** + * Counts the number of characters in string + * @param options The following optional parameters are supported: + * - `inplace` Boolean, indicating whether to perform the operation inplace or not. Defaults to `false` + * @example + * ``` + * import { Series } from "danfojs-node" + * const sf = new Series(["Good", "odd", "grade"]) + * const newSf = sf.str.len(d) + * // [4,3,5] + * ``` + */ + len(options?: { inplace?: boolean }): Series + len(options?: { inplace?: boolean }): Series | void { + const { inplace } = { inplace: false, ...options } + const newArr: Array = []; + this.values.map((val) => { + if (utils.isEmpty(val)) { + newArr.push(NaN); + } else { + newArr.push(`${val}`.length); + } + }); + if (inplace) { + this.series.$setValues(newArr as ArrayType1D) + this.series.print() + } else { + const sf = this.series.copy() + sf.$setValues(newArr as ArrayType1D) + return sf; + } + } + +} diff --git a/src/danfojs-base/index.ts b/src/danfojs-base/index.ts new file mode 100644 index 00000000..aca26bb0 --- /dev/null +++ b/src/danfojs-base/index.ts @@ -0,0 +1,53 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import NDframe from "./core/generic"; +import Config from './shared/config'; +import Utils from './shared/utils'; +import Series from "./core/series"; +import DataFrame from "./core/frame"; +import Str from "./core/strings" +import Dt, { toDateTime } from "./core/datetime" +import MinMaxScaler from "./transformers/scalers/min.max.scaler"; +import StandardScaler from "./transformers/scalers/standard.scaler"; +import LabelEncoder from "./transformers/encoders/label.encoder"; +import OneHotEncoder from "./transformers/encoders/one.hot.encoder"; +import getDummies from "./transformers/encoders/dummy.encoder" +import concat from "./transformers/concat" +import merge from "./transformers/merge" +import dateRange from "./core/daterange" +import tensorflow from "./shared/tensorflowlib" + +const __version = "1.2.0"; + +export { + NDframe, + Config, + Utils, + Str, + Dt, + toDateTime, + Series, + DataFrame, + MinMaxScaler, + StandardScaler, + LabelEncoder, + OneHotEncoder, + getDummies, + concat, + merge, + dateRange, + tensorflow, + __version, +} diff --git a/danfojs-browser/src/io/index.js b/src/danfojs-base/io/browser/index.ts similarity index 56% rename from danfojs-browser/src/io/index.js rename to src/danfojs-base/io/browser/index.ts index e969aac9..b3df0460 100644 --- a/danfojs-browser/src/io/index.js +++ b/src/danfojs-base/io/browser/index.ts @@ -1,6 +1,6 @@ /** * @license -* Copyright 2021, JsData. All rights reserved. +* Copyright 2022 JsData. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -13,20 +13,22 @@ * ========================================================================== */ import { - $readCSV, - $toCSV -} from "./io.csv"; + $readCSV, + $streamCSV, + $toCSV, +} from "./io.csv" import { - $readJSON, - $toJSON -} from "./io.json"; -import { $readExcel, $toExcel } from "./io.excel"; + $readJSON, + $toJSON, +} from "./io.json" +import { $readExcel, $toExcel } from "./io.excel" export { - $readCSV as readCSV, - $toCSV as toCSV, - $readJSON as readJSON, - $toJSON as toJSON, - $readExcel as readExcel, - $toExcel as toExcel -}; + $readCSV as readCSVBrowser, + $streamCSV as streamCSVBrowser, + $toCSV as toCSVBrowser, + $readJSON as readJSONBrowser, + $toJSON as toJSONBrowser, + $readExcel as readExcelBrowser, + $toExcel as toExcelBrowser, +} \ No newline at end of file diff --git a/src/danfojs-base/io/browser/io.csv.ts b/src/danfojs-base/io/browser/io.csv.ts new file mode 100644 index 00000000..3def7ad6 --- /dev/null +++ b/src/danfojs-base/io/browser/io.csv.ts @@ -0,0 +1,221 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { CsvInputOptionsBrowser, CsvOutputOptionsBrowser, ArrayType2D } from "../../shared/types" +import { DataFrame, NDframe, Series } from '../../' +import Papa from 'papaparse' + + +/** + * Reads a CSV file from local or remote location into a DataFrame. + * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, + * hence all PapaParse options are supported. + * @param options Configuration object. Supports all Papaparse parse config options. + * @returns DataFrame containing the parsed CSV file. + * @throws {Error} If file cannot be read or parsed + * @example + * ``` + * import { readCSV } from "danfojs-node" + * const df = await readCSV("https://raw.githubusercontent.com/test.csv") + * ``` + * @example + * ``` + * import { readCSV } from "danfojs-node" + * const df = await readCSV("https://raw.githubusercontent.com/test.csv", { + * delimiter: ",", + * headers: { + * Accept: "text/csv", + * Authorization: "Bearer YWRtaW46YWRtaW4=" + * } + * }) + * ``` + * @example + * ``` + * import { readCSV } from "danfojs-node" + * const df = await readCSV("./data/sample.csv") + * ``` + */ +const $readCSV = async (file: any, options?: CsvInputOptionsBrowser): Promise => { + const frameConfig = options?.frameConfig || {} + const hasStringType = frameConfig.dtypes?.includes("string") + + return new Promise((resolve, reject) => { + let hasError = false; + + Papa.parse(file, { + header: true, + dynamicTyping: !hasStringType, + skipEmptyLines: 'greedy', + delimiter: ",", + ...options, + error: (error) => { + hasError = true; + reject(new Error(`Failed to parse CSV: ${error.message}`)); + }, + download: true, + complete: (results) => { + if (hasError) return; // Skip if error already occurred + + if (!results.data || results.data.length === 0) { + reject(new Error('No data found in CSV file')); + return; + } + + if (results.errors && results.errors.length > 0) { + reject(new Error(`CSV parsing errors: ${results.errors.map(e => e.message).join(', ')}`)); + return; + } + + try { + const df = new DataFrame(results.data, frameConfig); + resolve(df); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + reject(new Error(`Failed to create DataFrame from CSV: ${errorMessage}`)); + } + } + }); + }); +}; + +/** + * Streams a CSV file from local or remote location in chunks. Intermediate chunks is passed as a DataFrame to the callback function. + * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, + * hence all PapaParse options are supported. + * @param options Configuration object. Supports all Papaparse parse config options. + * @param callback Callback function to be called once the specifed rows are parsed into DataFrame. + * @example + * ``` + * import { streamCSV } from "danfojs-node" + * streamCSV("https://raw.githubusercontent.com/test.csv", (dfRow) => { + * const dfModified = dfRow["Names"].map((name) => name.split(",")[0]) + * return dfModified + * }) + * ``` + */ +const $streamCSV = async (file: string, callback: (df: DataFrame) => void, options: CsvInputOptionsBrowser,): Promise => { + const frameConfig = options?.frameConfig || {} + + return new Promise((resolve, reject) => { + let count = 0 + let hasError = false; + const hasStringType = frameConfig.dtypes?.includes("string") + Papa.parse(file, { + header: true, + download: true, + dynamicTyping: !hasStringType, + delimiter: ",", + ...options, + step: results => { + if (hasError) return; + try { + const df = new DataFrame([results.data], { ...frameConfig, index: [count++] }); + callback(df); + } catch (error) { + hasError = true; + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + reject(new Error(`Failed to process CSV chunk: ${errorMessage}`)); + } + }, + complete: () => { + if (!hasError) { + resolve(null); + } + }, + error: (error) => { + hasError = true; + reject(new Error(`Failed to parse CSV: ${error.message}`)); + } + }); + }); +}; + + +/** + * Converts a DataFrame or Series to CSV. + * @param df DataFrame or Series to be converted to CSV. + * @param options Configuration object. Supports the following options: + * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. + * - `header`: Boolean indicating whether to include a header row in the CSV file. + * - `sep`: Character to be used as a separator in the CSV file. + * @example + * ``` + * import { toCSV } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * const csv = toCSV(df) + * ``` + * @example + * ``` + * import { toCSV } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toCSV(df, { + * filePath: "./data/sample.csv", + * header: true, + * sep: "+" + * }) + * ``` + */ +const $toCSV = (df: NDframe | DataFrame | Series, options?: CsvOutputOptionsBrowser): string | void => { + let { fileName, download, sep, header } = { fileName: "output.csv", sep: ",", header: true, download: false, ...options } + + if (df.$isSeries) { + const csv = df.values.join(sep); + + if (download) { + if (!(fileName.endsWith(".csv"))) { + fileName = fileName + ".csv" + } + $downloadFileInBrowser(csv, fileName); + } else { + return csv; + } + } else { + const rows = df.values as ArrayType2D + let csvStr = header === true ? `${df.columns.join(sep)}\n` : "" + + for (let i = 0; i < rows.length; i++) { + const row = `${rows[i].join(sep)}\n`; + csvStr += row; + } + + if (download) { + if (!(fileName.endsWith(".csv"))) { + fileName = fileName + ".csv" + } + $downloadFileInBrowser(csvStr, fileName); + } else { + return csvStr; + } + } +}; + +/** + * Internal function to download a CSV file in the browser. + * @param content A string of CSV file contents + * @param fileName The name of the file to be downloaded + */ +const $downloadFileInBrowser = (content: any, fileName: string) => { + var hiddenElement = document.createElement('a'); + hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(content); + hiddenElement.target = '_blank'; + hiddenElement.download = fileName; + hiddenElement.click(); +} + + +export { + $readCSV, + $streamCSV, + $toCSV, +} diff --git a/src/danfojs-base/io/browser/io.excel.ts b/src/danfojs-base/io/browser/io.excel.ts new file mode 100644 index 00000000..b62cd5ed --- /dev/null +++ b/src/danfojs-base/io/browser/io.excel.ts @@ -0,0 +1,140 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { + ArrayType1D, + ArrayType2D, + ExcelOutputOptionsBrowser, + ExcelInputOptionsBrowser +} from "../../shared/types" +import { DataFrame, NDframe, Series } from '../../' +import { + read, + writeFile, + utils +} from "xlsx"; + +/** + * Reads a JSON file from local or remote location into a DataFrame. + * @param file URL or local file path to JSON file. + * @param options Configuration object. Supported options: + * - `method`: The HTTP method to use. Defaults to `'GET'`. + * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] + * @example + * ``` + * import { readExcel } from "danfojs-node" + * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx") + * ``` + * @example + * ``` + * import { readExcel } from "danfojs-node" + * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx", { + * method: "GET", + * headers: { + * Accept: "text/csv", + * Authorization: "Bearer YWRtaW46YWRtaW4=" + * } + * }) + * ``` + */ +const $readExcel = async (file: any, options?: ExcelInputOptionsBrowser) => { + const { + sheet, + method, + headers, + frameConfig, + parsingOptions + } = { sheet: 0, method: "GET", headers: {}, frameConfig: {}, parsingOptions: {}, ...options } + + if (typeof file === "string" && file.startsWith("http")) { + + return new Promise(resolve => { + fetch(file, { method, headers }).then(response => { + if (response.status !== 200) { + throw new Error(`Failed to load ${file}`) + } + response.arrayBuffer().then(arrBuf => { + const arrBufInt8 = new Uint8Array(arrBuf); + const workbook = read(arrBufInt8, { type: "array", ...parsingOptions }); + const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; + const data = utils.sheet_to_json(worksheet); + const df = new DataFrame(data, frameConfig); + resolve(df); + }); + }).catch((err) => { + throw new Error(err) + }) + }) + + } else if (file instanceof File) { + const arrBuf = await file.arrayBuffer() + const arrBufInt8 = new Uint8Array(arrBuf); + const workbook = read(arrBufInt8, { type: "array", ...parsingOptions }); + const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; + const data = utils.sheet_to_json(worksheet); + const df = new DataFrame(data, frameConfig); + return df; + } else { + throw new Error("ParamError: File not supported. file must be a url or an input File object") + } +}; + +/** + * Converts a DataFrame or Series to Excel Sheet. + * @param df DataFrame or Series to be converted to JSON. + * @param options Configuration object. Supported options: + * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. + * - `fileName`: The file to be written to. Defaults to `'./output.xlsx'`. + * @example + * ``` + * import { toExcel } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toExcel(df, { + * fileName: "./data/sample.xlsx", + * sheetName: "MySheet", + * }) + * ``` + */ +const $toExcel = (df: NDframe | DataFrame | Series, options?: ExcelOutputOptionsBrowser) => { + let { + fileName, + sheetName, + writingOptions + } = { fileName: "./output.xlsx", sheetName: "Sheet1", ...options } + + if (!(fileName.endsWith(".xlsx"))) { + fileName = fileName + ".xlsx" + } + let data; + + if (df.$isSeries) { + const row = df.values as ArrayType1D + const col = df.columns + data = [col, ...(row.map(x => [x]))] + } else { + const row = df.values as ArrayType2D + const cols = df.columns + data = [cols, ...row] + } + + const worksheet = utils.aoa_to_sheet(data); + const wb = utils.book_new(); + utils.book_append_sheet(wb, worksheet, sheetName); + writeFile(wb, `${fileName}`, writingOptions) +}; + +export { + $readExcel, + $toExcel +} diff --git a/src/danfojs-base/io/browser/io.json.ts b/src/danfojs-base/io/browser/io.json.ts new file mode 100644 index 00000000..5a11f324 --- /dev/null +++ b/src/danfojs-base/io/browser/io.json.ts @@ -0,0 +1,187 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { + ArrayType1D, + ArrayType2D, + JsonInputOptionsBrowser, + JsonOutputOptionsBrowser +} from '../../shared/types' +import { DataFrame, NDframe, Series } from '../../' + +/** + * Reads a JSON file from local or remote location into a DataFrame. + * @param fileName URL or local file path to JSON file. + * @param options Configuration object. Supported options: + * - `method`: The HTTP method to use. Defaults to `'GET'`. + * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] + * @example + * ``` + * import { readJSON } from "danfojs-node" + * const df = await readJSON("https://raw.githubusercontent.com/test.json") + * ``` + * @example + * ``` + * import { readJSON } from "danfojs-node" + * const df = await readJSON("https://raw.githubusercontent.com/test.json", { + * headers: { + * Accept: "text/json", + * Authorization: "Bearer YWRtaW46YWRtaW4=" + * } + * }) + * ``` + * @example + * ``` + * import { readJSON } from "danfojs-node" + * const df = await readJSON("./data/sample.json") + * ``` + */ +const $readJSON = async (file: any, options?: JsonInputOptionsBrowser) => { + const { method, headers, frameConfig } = { method: "GET", headers: {}, frameConfig: {}, ...options } + + if (typeof file === "string" && file.startsWith("http")) { + + return new Promise(resolve => { + fetch(file, { method, headers }).then(response => { + if (response.status !== 200) { + throw new Error(`Failed to load ${file}`) + } + response.json().then(json => { + resolve(new DataFrame(json, frameConfig)); + }); + }).catch((err) => { + throw new Error(err) + }) + }) + + } else if (file instanceof File) { + return new Promise(resolve => { + const reader = new FileReader(); + reader.readAsText(file); + reader.onload = (event) => { + const jsonObj = JSON.parse(event?.target?.result as string); + resolve(new DataFrame(jsonObj, frameConfig)); + } + }) + } else { + throw new Error("ParamError: File not supported. file must be a url or an input File object") + } +}; + + +/** + * Converts a DataFrame or Series to JSON. + * @param df DataFrame or Series to be converted to JSON. + * @param options Configuration object. Supported options: + * - `fileName`: The file path to write the JSON to. If not specified, the JSON object is returned. + * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: + * ``` + * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, + * { "a": 5, "b": 6, "c": 7, "d": 8 }] + * ``` + * and `row` format: + * ``` + * { "a": [1, 5, 9], + * "b": [2, 6, 10] + * } + * ``` + * @example + * ``` + * import { toJSON } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * const json = toJSON(df) + * ``` + * @example + * ``` + * import { toJSON } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toJSON(df, { + * fileName: "./data/sample.json", + * format: "row" + * }) + * ``` + */ +const $toJSON = (df: NDframe | DataFrame | Series, options?: JsonOutputOptionsBrowser): object | void => { + let { fileName, format, download } = { fileName: "output.json", download: false, format: "column", ...options } + + if (df.$isSeries) { + const obj: { [key: string]: ArrayType1D } = {}; + obj[df.columns[0]] = df.values as ArrayType1D; + + if (download) { + if (!fileName.endsWith(".json")) { + fileName = fileName + ".json" + } + $downloadFileInBrowser(obj, fileName) + } else { + return obj + } + + } else { + if (format === "row") { + const obj: { [key: string]: ArrayType1D } = {}; + for (let i = 0; i < df.columns.length; i++) { + obj[df.columns[i]] = (df as DataFrame).column(df.columns[i]).values as ArrayType1D; + } + if (download) { + if (!(fileName.endsWith(".json"))) { + fileName = fileName + ".json" + } + + $downloadFileInBrowser(obj, fileName) + } else { + return obj + } + } else { + const values = df.values as ArrayType2D + const header = df.columns + const jsonArr: any = []; + + values.forEach((val) => { + const obj: any = {}; + header.forEach((h, i) => { + obj[h] = val[i] + }); + jsonArr.push(obj); + }); + if (download) { + if (!fileName.endsWith(".json")) { + fileName = fileName + ".json" + } + $downloadFileInBrowser(jsonArr, fileName) + } else { + return jsonArr + } + } + } +}; + +/** + * Internal function to download a JSON file in the browser. + * @param content A string of JSON file contents + * @param fileName The name of the file to be downloaded + */ +const $downloadFileInBrowser = (content: any, fileName: string) => { + var hiddenElement = document.createElement('a'); + hiddenElement.href = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(content)); + hiddenElement.target = '_blank'; + hiddenElement.download = fileName; + hiddenElement.click(); +} + + +export { + $readJSON, + $toJSON +} \ No newline at end of file diff --git a/src/danfojs-base/io/node/index.ts b/src/danfojs-base/io/node/index.ts new file mode 100644 index 00000000..3f5eb6ce --- /dev/null +++ b/src/danfojs-base/io/node/index.ts @@ -0,0 +1,40 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { + $readCSV, + $streamCSV, + $toCSV, + $openCsvInputStream, + $writeCsvOutputStream, +} from "./io.csv" +import { + $readJSON, + $toJSON, + $streamJSON +} from "./io.json" +import { $readExcel, $toExcel } from "./io.excel" + +export { + $readCSV as readCSVNode, + $streamCSV as streamCSVNode, + $toCSV as toCSVNode, + $openCsvInputStream as openCsvInputStreamNode, + $writeCsvOutputStream as writeCsvOutputStreamNode, + $readJSON as readJSONNode, + $toJSON as toJSONNode, + $streamJSON as streamJSONNode, + $readExcel as readExcelNode, + $toExcel as toExcelNode, +} \ No newline at end of file diff --git a/src/danfojs-base/io/node/io.csv.ts b/src/danfojs-base/io/node/io.csv.ts new file mode 100644 index 00000000..6cf11e86 --- /dev/null +++ b/src/danfojs-base/io/node/io.csv.ts @@ -0,0 +1,499 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { CsvInputOptionsNode, CsvOutputOptionsNode, ArrayType2D } from "../../shared/types" +import { DataFrame, NDframe, Series } from '../../' +import request from "request" +import Papa from 'papaparse' +import stream from "stream" +import fs from 'fs' + +/** + * Reads a CSV file from local or remote location into a DataFrame. + * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, + * hence all PapaParse options are supported. + * @param options Configuration object. Supports all Papaparse parse config options. + * @returns DataFrame containing the parsed CSV file. + * @throws {Error} If file cannot be read or parsed + * @example + * ``` + * import { readCSV } from "danfojs-node" + * const df = await readCSV("https://raw.githubusercontent.com/test.csv") + * ``` + * @example + * ``` + * import { readCSV } from "danfojs-node" + * const df = await readCSV("https://raw.githubusercontent.com/test.csv", { + * delimiter: ",", + * headers: { + * Accept: "text/csv", + * Authorization: "Bearer YWRtaW46YWRtaW4=" + * } + * }) + * ``` + * @example + * ``` + * import { readCSV } from "danfojs-node" + * const df = await readCSV("./data/sample.csv") + * ``` + */ +const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promise => { + const frameConfig = options?.frameConfig || {} + const hasStringType = frameConfig.dtypes?.includes("string") + + if (filePath.startsWith("http") || filePath.startsWith("https")) { + return new Promise((resolve, reject) => { + let hasError = false; + const optionsWithDefaults = { + header: true, + dynamicTyping: !hasStringType, + skipEmptyLines: 'greedy', + delimiter: ",", + ...options, + } + + const dataStream = request.get(filePath); + // reject any non-2xx status codes + dataStream.on('response', (response: any) => { + if (response.statusCode < 200 || response.statusCode >= 300) { + hasError = true; + reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`)); + } + }); + + const parseStream: any = Papa.parse(Papa.NODE_STREAM_INPUT, optionsWithDefaults as any); + dataStream.pipe(parseStream); + + const data: any = []; + parseStream.on("data", (chunk: any) => { + if (!hasError) { + data.push(chunk); + } + }); + + parseStream.on("error", (error: any) => { + hasError = true; + reject(new Error(`Failed to parse CSV: ${error.message}`)); + }); + + parseStream.on("finish", () => { + if (hasError) return; + + if (!data || data.length === 0) { + reject(new Error('No data found in CSV file')); + return; + } + + try { + const df = new DataFrame(data, frameConfig); + resolve(df); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + reject(new Error(`Failed to create DataFrame: ${errorMessage}`)); + } + }); + }); + + } else { + return new Promise((resolve, reject) => { + fs.access(filePath, fs.constants.F_OK, (err) => { + if (err) { + reject(new Error("ENOENT: no such file or directory")); + return; + } + + const fileStream = fs.createReadStream(filePath) + let hasError = false; + + Papa.parse(fileStream, { + header: true, + dynamicTyping: !hasStringType, + delimiter: ",", + ...options, + error: (error) => { + hasError = true; + reject(new Error(`Failed to parse CSV: ${error.message}`)); + }, + complete: results => { + if (hasError) return; + + if (!results.data || results.data.length === 0) { + reject(new Error('No data found in CSV file')); + return; + } + + if (results.errors && results.errors.length > 0) { + reject(new Error(`CSV parsing errors: ${results.errors.map(e => e.message).join(', ')}`)); + return; + } + + try { + const df = new DataFrame(results.data, frameConfig); + resolve(df); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + reject(new Error(`Failed to create DataFrame: ${errorMessage}`)); + } + } + }); + }) + }); + } +}; + +/** + * Streams a CSV file from local or remote location in chunks. Intermediate chunks is passed as a DataFrame to the callback function. + * @param filePath URL or local file path to CSV file. `readCSV` uses PapaParse to parse the CSV file, + * hence all PapaParse options are supported. + * @param callback Callback function to be called once the specifed rows are parsed into DataFrame. + * @param options Configuration object. Supports all Papaparse parse config options. + * @throws {Error} If file cannot be read or parsed + * @example + * ``` + * import { streamCSV } from "danfojs-node" + * streamCSV("https://raw.githubusercontent.com/test.csv", (dfRow) => { + * const dfModified = dfRow["Names"].map((name) => name.split(",")[0]) + * return dfModified + * }) + * ``` + */ +const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, options?: CsvInputOptionsNode): Promise => { + const frameConfig = options?.frameConfig || {} + + if (filePath.startsWith("http") || filePath.startsWith("https")) { + const optionsWithDefaults = { + header: true, + dynamicTyping: true, + ...options, + } + return new Promise((resolve, reject) => { + let count = 0; + let hasError = false; + const dataStream = request.get(filePath); + + // reject any non-2xx status codes + dataStream.on('response', (response: any) => { + if (response.statusCode < 200 || response.statusCode >= 300) { + hasError = true; + reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`)); + } + }); + + const parseStream: any = Papa.parse(Papa.NODE_STREAM_INPUT, optionsWithDefaults); + dataStream.pipe(parseStream); + + parseStream.on("data", (chunk: any) => { + if (hasError) return; + try { + const df = new DataFrame([chunk], { ...frameConfig, index: [count++] }); + callback(df); + } catch (error) { + hasError = true; + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + reject(new Error(`Failed to process CSV chunk: ${errorMessage}`)); + } + }); + + parseStream.on("error", (error: any) => { + hasError = true; + reject(new Error(`Failed to parse CSV: ${error.message}`)); + }); + + parseStream.on("finish", () => { + if (!hasError) { + resolve(null); + } + }); + }); + } else { + return new Promise((resolve, reject) => { + fs.access(filePath, fs.constants.F_OK, (err) => { + if (err) { + reject(new Error("ENOENT: no such file or directory")); + return; + } + + const fileStream = fs.createReadStream(filePath) + let hasError = false; + let count = 0; + + Papa.parse(fileStream, { + header: true, + dynamicTyping: true, + ...options, + error: (error) => { + hasError = true; + reject(new Error(`Failed to parse CSV: ${error.message}`)); + }, + step: results => { + if (hasError) return; + + if (results.errors && results.errors.length > 0) { + hasError = true; + reject(new Error(`CSV parsing errors: ${results.errors.map(e => e.message).join(', ')}`)); + return; + } + + try { + const df = new DataFrame([results.data], { ...frameConfig, index: [count++] }); + callback(df); + } catch (error) { + hasError = true; + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + reject(new Error(`Failed to process CSV chunk: ${errorMessage}`)); + } + }, + complete: () => { + if (!hasError) { + resolve(null); + } + } + }); + }); + }); + } +}; + + +/** + * Converts a DataFrame or Series to CSV. + * @param df DataFrame or Series to be converted to CSV. + * @param options Configuration object. Supports the following options: + * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. + * - `header`: Boolean indicating whether to include a header row in the CSV file. + * - `sep`: Character to be used as a separator in the CSV file. + * @example + * ``` + * import { toCSV } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * const csv = toCSV(df) + * ``` + * @example + * ``` + * import { toCSV } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toCSV(df, { + * filePath: "./data/sample.csv", + * header: true, + * sep: "+" + * }) + * ``` + */ +const $toCSV = (df: NDframe | DataFrame | Series, options?: CsvOutputOptionsNode): string | void => { + let { filePath, sep, header } = { sep: ",", header: true, filePath: undefined, ...options } + + if (df.$isSeries) { + const csv = df.values.join(sep); + + if (filePath !== undefined) { + if (!(filePath.endsWith(".csv"))) { + filePath = filePath + ".csv" + } + fs.writeFileSync(filePath, csv, "utf8") + } else { + return csv; + } + } else { + const rows = df.values as ArrayType2D + let csvStr = header === true ? `${df.columns.join(sep)}\n` : "" + + for (let i = 0; i < rows.length; i++) { + const row = `${rows[i].join(sep)}\n`; + csvStr += row; + } + + if (filePath !== undefined) { + if (!(filePath.endsWith(".csv"))) { + filePath = filePath + ".csv" + } + fs.writeFileSync(filePath, csvStr, "utf8") + } else { + return csvStr; + } + } +}; + + +/** + * Opens a CSV file from local or remote location as a Stream. Intermediate row is returned as a DataFrame object. + * @param filePath URL or local file path to CSV file. + * @param options Configuration object. Supports all Papaparse config options. + * @example + * ``` + * import { openCsvInputStream } from "danfojs-node" + * const csvStream = openCsvInputStream("./data/sample.csv") + * ``` + */ +const $openCsvInputStream = (filePath: string, options: CsvInputOptionsNode) => { + const { header } = { header: true, ...options } + let isFirstChunk = true + let ndFrameColumnNames: any = [] + + const csvInputStream = new stream.Readable({ objectMode: true }); + csvInputStream._read = () => { }; + + if (filePath.startsWith("http") || filePath.startsWith("https")) { + const dataStream = request.get(filePath); + + // reject any non-2xx status codes + dataStream.on('response', (response: any) => { + if (response.statusCode < 200 || response.statusCode >= 300) { + throw new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`); + } + }); + + const parseStream: any = Papa.parse(Papa.NODE_STREAM_INPUT, { header, dynamicTyping: true, ...options }); + dataStream.pipe(parseStream); + let count = 0 + + parseStream.on("data", (chunk: any) => { + if (isFirstChunk) { + if (header === true) { + ndFrameColumnNames = Object.keys(chunk) + } else { + ndFrameColumnNames = chunk + } + isFirstChunk = false + return + } + + const df = new DataFrame([Object.values(chunk)], { + columns: ndFrameColumnNames, + index: [count++] + }) + csvInputStream.push(df); + }); + + parseStream.on("finish", () => { + csvInputStream.push(null); + return (null); + }); + + return csvInputStream; + } else { + const fileStream = fs.createReadStream(filePath) + + fs.access(filePath, fs.constants.F_OK, (err) => { + if (err) { + throw new Error("ENOENT: no such file or directory"); + } + + let count = 0 + Papa.parse(fileStream, { + ...{ header, dynamicTyping: true, ...options }, + step: results => { + if (isFirstChunk) { + if (header === true) { + ndFrameColumnNames = results.meta.fields || [] + } else { + ndFrameColumnNames = results.data + } + isFirstChunk = false + return + } + + const df = new DataFrame([results.data], { + columns: ndFrameColumnNames, + index: [count++] + }) + + csvInputStream.push(df); + }, + complete: (result: any) => { + csvInputStream.push(null); + return null + }, + error: (err) => { + csvInputStream.emit("error", err); + } + }); + + return csvInputStream; + }); + } +}; + + +/** + * Writes a file stream to local storage. Stream objects must be a Series or DataFrame. + * @param filePath URL or local file path to write to. + * @param options Configuration object. Supports all `toCSV` options. + * @example + * ``` + * import { openCsvInputStream, + * writeCsvOutputStream, + * convertFunctionTotransformer } from "danfojs-node" + * + * const csvStream = openCsvInputStream("./data/sample.csv") + * const outStream = writeCsvOutputStream("./data/sampleOut.csv") + * + * const transformer = (dfRow) => { + * const dfModified = dfRow["Names"].map((name) => name.split(",")[0]) + * return dfModified + * } + * csvStream.pipe(convertFunctionTotransformer(transformer)).pipe(outStream) + * ``` + */ +const $writeCsvOutputStream = (filePath: string, options: CsvInputOptionsNode) => { + fs.access(filePath, fs.constants.F_OK, (err) => { + if (err) { + throw new Error("ENOENT: no such file or directory"); + } + + let isFirstRow = true + const fileOutputStream = fs.createWriteStream(filePath) + const csvOutputStream = new stream.Writable({ objectMode: true }) + + csvOutputStream._write = (chunk: DataFrame | Series, encoding, callback) => { + + if (chunk instanceof DataFrame) { + + if (isFirstRow) { + isFirstRow = false + fileOutputStream.write($toCSV(chunk, { header: true, ...options })); + callback(); + } else { + fileOutputStream.write($toCSV(chunk, { header: false, ...options })); + callback(); + } + + } else if (chunk instanceof Series) { + + fileOutputStream.write($toCSV(chunk)); + callback(); + + } else { + csvOutputStream.emit("error", new Error("ValueError: Intermediate chunk must be either a Series or DataFrame")) + } + + } + + csvOutputStream.on("finish", () => { + fileOutputStream.end() + }) + + return csvOutputStream + }); +} + + + + +export { + $readCSV, + $streamCSV, + $toCSV, + $writeCsvOutputStream, + $openCsvInputStream, +} diff --git a/src/danfojs-base/io/node/io.excel.ts b/src/danfojs-base/io/node/io.excel.ts new file mode 100644 index 00000000..f6554086 --- /dev/null +++ b/src/danfojs-base/io/node/io.excel.ts @@ -0,0 +1,147 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { ArrayType1D, ArrayType2D, ExcelInputOptionsNode, ExcelOutputOptionsNode } from "../../shared/types" +import { DataFrame, NDframe, Series } from '../../' +import fetch from "node-fetch"; +import { + read, + writeFile, + readFile, + utils +} from "xlsx"; +import fs from 'fs' + +/** + * Reads a JSON file from local or remote location into a DataFrame. + * @param filePath URL or local file path to JSON file. + * @param options Configuration object. Supported options: + * - `method`: The HTTP method to use. Defaults to `'GET'`. + * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] + * @example + * ``` + * import { readExcel } from "danfojs-node" + * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx") + * ``` + * @example + * ``` + * import { readExcel } from "danfojs-node" + * const df = await readExcel("https://raw.githubusercontent.com/test.xlsx", { + * method: "GET", + * headers: { + * Accept: "text/csv", + * Authorization: "Bearer YWRtaW46YWRtaW4=" + * } + * }) + * ``` + * @example + * ``` + * import { readExcel } from "danfojs-node" + * const df = await readExcel("./data/sample.xlsx") + * ``` + */ +const $readExcel = async (filePath: string, options: ExcelInputOptionsNode = {}) => { + const { + sheet, + method, + headers, + frameConfig, + parsingOptions + } = { sheet: 0, method: "GET", headers: {}, frameConfig: {}, parsingOptions: {}, ...options } + + if (filePath.startsWith("http") || filePath.startsWith("https")) { + + return new Promise((resolve, reject) => { + fetch(filePath, { method, headers }).then(response => { + if (response.status !== 200) { + throw new Error(`Failed to load ${filePath}`) + } + response.arrayBuffer().then(arrBuf => { + const arrBufInt8 = new Uint8Array(arrBuf); + const workbook = read(arrBufInt8, { type: "array", ...parsingOptions }); + const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; + const data = utils.sheet_to_json(worksheet, { defval: null }); + const df = new DataFrame(data, frameConfig); + resolve(df); + }); + }).catch((err) => { + reject(err) + }) + }) + + } else { + return new Promise((resolve, reject) => { + fs.access(filePath, fs.constants.F_OK, (err) => { + if (err) { + reject("ENOENT: no such file or directory"); + } + + const workbook = readFile(filePath, parsingOptions); + const worksheet = workbook.Sheets[workbook.SheetNames[sheet]]; + const data = utils.sheet_to_json(worksheet, { defval: null }); + const df = new DataFrame(data, frameConfig); + resolve(df); + }) + }); + } +}; + +/** + * Converts a DataFrame or Series to Excel Sheet. + * @param df DataFrame or Series to be converted to JSON. + * @param options Configuration object. Supported options: + * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. + * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. + * @example + * ``` + * import { toExcel } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toExcel(df, { + * filePath: "./data/sample.xlsx", + * sheetName: "MySheet", + * }) + * ``` + */ +const $toExcel = (df: NDframe | DataFrame | Series, options?: ExcelOutputOptionsNode) => { + let { + filePath, + sheetName, + writingOptions + } = { filePath: "./output.xlsx", sheetName: "Sheet1", ...options } + + if (!(filePath.endsWith(".xlsx"))) { + filePath = filePath + ".xlsx" + } + let data; + + if (df.$isSeries) { + const row = df.values as ArrayType1D + const col = df.columns + data = [col, ...(row.map(x => [x]))] + } else { + const row = df.values as ArrayType2D + const cols = df.columns + data = [cols, ...row] + } + + const worksheet = utils.aoa_to_sheet(data); + const wb = utils.book_new(); + utils.book_append_sheet(wb, worksheet, sheetName); + writeFile(wb, `${filePath}`, writingOptions); +}; + +export { + $readExcel, + $toExcel +} diff --git a/src/danfojs-base/io/node/io.json.ts b/src/danfojs-base/io/node/io.json.ts new file mode 100644 index 00000000..27a0e68b --- /dev/null +++ b/src/danfojs-base/io/node/io.json.ts @@ -0,0 +1,221 @@ +import { ArrayType1D, ArrayType2D, JsonInputOptionsNode, JsonOutputOptionsNode } from '../../shared/types'; +import { streamArray } from "stream-json/streamers/StreamArray" +import { DataFrame, NDframe, Series } from '../../' +import { parser } from "stream-json" +import fetch from "node-fetch"; +import request from "request" +import fs from 'fs' + +/** + * Reads a JSON file from local or remote location into a DataFrame. + * @param filePath URL or local file path to JSON file. + * @param options Configuration object. Supported options: + * - `method`: The HTTP method to use. Defaults to `'GET'`. + * - `headers`: Additional headers to send with the request. Supports the `node-fetch` [HeadersInit] + * @example + * ``` + * import { readJSON } from "danfojs-node" + * const df = await readJSON("https://raw.githubusercontent.com/test.json") + * ``` + * @example + * ``` + * import { readJSON } from "danfojs-node" + * const df = await readJSON("https://raw.githubusercontent.com/test.json", { + * headers: { + * Accept: "text/json", + * Authorization: "Bearer YWRtaW46YWRtaW4=" + * } + * }) + * ``` + * @example + * ``` + * import { readJSON } from "danfojs-node" + * const df = await readJSON("./data/sample.json") + * ``` + */ +const $readJSON = async (filePath: string, options: JsonInputOptionsNode = {}) => { + const { method, headers, frameConfig } = { method: "GET", headers: {}, frameConfig: {}, ...options } + + if (filePath.startsWith("http") || filePath.startsWith("https")) { + + return new Promise((resolve, reject) => { + fetch(filePath, { method, headers }).then(response => { + if (response.status !== 200) { + throw new Error(`Failed to load ${filePath}`) + } + response.json().then(json => { + resolve(new DataFrame(json, frameConfig)); + }); + }).catch((err) => { + reject(err) + }) + }) + + } else { + return new Promise((resolve, reject) => { + fs.access(filePath, fs.constants.F_OK, (err) => { + if (err) { + reject("ENOENT: no such file or directory"); + } + const file = fs.readFileSync(filePath, "utf8") + const df = new DataFrame(JSON.parse(file), frameConfig); + resolve(df); + }) + }); + } +}; + +/** + * Streams a JSON file from local or remote location in chunks. Intermediate chunks is passed as a DataFrame to the callback function. + * @param filePath URL or local file path to CSV file. + * @param callback Callback function to be called once the specifed rows are parsed into DataFrame. + * @param options Configuration object. We use the `request` library for reading remote json files, + * Hence all `request` parameters such as `method`, `headers`, are supported. + * @example + * ``` + * import { streamJSON } from "danfojs-node" + * streamJSON("https://raw.githubusercontent.com/test.json", {}, (dfRow) => { + * const dfModified = dfRow["Names"].map((name) => name.split(",")[0]) + * return dfModified + * }) + * ``` + */ +const $streamJSON = async ( + filePath: string, + callback: (df: DataFrame) => void, + options?: request.RequiredUriUrl & request.CoreOptions, +) => { + const { method, headers, frameConfig } = { method: "GET", headers: {}, frameConfig: {}, ...options } + if (filePath.startsWith("http") || filePath.startsWith("https")) { + return new Promise((resolve, reject) => { + let count = 0; + const dataStream = request({ url: filePath, method, headers }) + + // reject any non-2xx status codes + dataStream.on('response', (response: any) => { + if (response.statusCode < 200 || response.statusCode >= 300) { + reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`)); + } + }); + + + const pipeline = dataStream.pipe(parser()).pipe(streamArray()); + pipeline.on('data', ({ value }) => { + const df = new DataFrame([value], { ...frameConfig, index: [count++] }); + callback(df); + }); + pipeline.on('end', () => resolve(null)); + + }); + } else { + return new Promise((resolve, reject) => { + fs.access(filePath, fs.constants.F_OK, (err) => { + if (err) { + reject("ENOENT: no such file or directory"); + } + + let count = 0 + const fileStream = fs.createReadStream(filePath) + const pipeline = fileStream.pipe(parser()).pipe(streamArray()); + pipeline.on('data', ({ value }) => { + const df = new DataFrame([value], { ...frameConfig, index: [count++] }); + callback(df); + }); + pipeline.on('end', () => resolve(null)); + }); + }) + } +}; + + +/** + * Converts a DataFrame or Series to JSON. + * @param df DataFrame or Series to be converted to JSON. + * @param options Configuration object. Supported options: + * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. + * - `format`: The format of the JSON. Defaults to `'column'`. E.g for using `column` format: + * ``` + * [{ "a": 1, "b": 2, "c": 3, "d": 4 }, + * { "a": 5, "b": 6, "c": 7, "d": 8 }] + * ``` + * and `row` format: + * ``` + * { "a": [1, 5, 9], + * "b": [2, 6, 10] + * } + * ``` + * @example + * ``` + * import { toJSON } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * const json = toJSON(df) + * ``` + * @example + * ``` + * import { toJSON } from "danfojs-node" + * const df = new DataFrame([[1, 2, 3], [4, 5, 6]]) + * toJSON(df, { + * filePath: "./data/sample.json", + * format: "row" + * }) + * ``` + */ +const $toJSON = (df: NDframe | DataFrame | Series, options?: JsonOutputOptionsNode): object | void => { + let { filePath, format } = { filePath: undefined, format: "column", ...options } + + if (df.$isSeries) { + const obj: { [key: string]: ArrayType1D } = {}; + obj[df.columns[0]] = df.values as ArrayType1D; + if (filePath) { + if (!filePath.endsWith(".json")) { + filePath = filePath + ".json" + } + fs.writeFileSync(filePath, JSON.stringify(obj)) + } else { + return obj + } + } else { + const values = df.values as ArrayType2D + const header = df.columns + const jsonArr: any = []; + + if (format === "row") { + const obj: { [key: string]: ArrayType1D } = {}; + for (let i = 0; i < df.columns.length; i++) { + obj[df.columns[i]] = (df as DataFrame).column(df.columns[i]).values as ArrayType1D; + } + if (filePath !== undefined) { + if (!(filePath.endsWith(".json"))) { + filePath = filePath + ".json" + } + + fs.writeFileSync(filePath, JSON.stringify(obj), "utf8") + } else { + return obj + } + } else { + values.forEach((val) => { + const obj: any = {}; + header.forEach((h, i) => { + obj[h] = val[i] + }); + jsonArr.push(obj); + }); + if (filePath) { + if (!filePath.endsWith(".json")) { + filePath = filePath + ".json" + } + fs.writeFileSync(filePath, JSON.stringify(jsonArr)) + } else { + return jsonArr + } + } + } +}; + + +export { + $readJSON, + $toJSON, + $streamJSON +} diff --git a/src/danfojs-base/package.json b/src/danfojs-base/package.json new file mode 100644 index 00000000..85d2af9c --- /dev/null +++ b/src/danfojs-base/package.json @@ -0,0 +1,62 @@ +{ + "name": "danfojs-base", + "version": "1.2.0", + "description": "Base package used in danfojs-node and danfojs-browser", + "main": "index.ts", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@tensorflow/tfjs": "^3.13.0", + "@tensorflow/tfjs-node": "^3.13.0", + "mathjs": "^10.0.0", + "papaparse": "^5.3.1", + "request": "^2.88.2", + "stream-json": "^1.7.3", + "table": "6.7.1", + "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz", + "seedrandom": "^2.4.3", + "plotly.js-dist-min": "^2.8.0", + "node-fetch": "^2.6.7" + }, + "devDependencies": { + "@types/papaparse": "^5.3.1", + "@types/plotly.js-dist-min": "^2.3.0", + "dotenv": "^10.0.0", + "@babel/cli": "^7.10.5", + "@babel/core": "^7.10.5", + "@babel/plugin-transform-runtime": "^7.12.10", + "@babel/preset-env": "^7.10.4", + "@types/chai": "^4.2.19", + "@types/mocha": "^8.2.2", + "@types/node": "^15.12.5", + "@types/request": "^2.48.7", + "@types/stream-json": "^1.7.1", + "@types/table": "^6.3.2", + "@typescript-eslint/eslint-plugin": "^4.30.0", + "@typescript-eslint/parser": "^4.30.0", + "awesome-typescript-loader": "^5.2.1", + "babel-loader": "^8.1.0", + "browserify": "16.5.2", + "chai": "^4.2.0", + "coveralls": "^3.1.0", + "eslint": "^7.1.0", + "ify-loader": "^1.1.0", + "install-peers": "^1.0.3", + "karma": "6.3.16", + "karma-browserify": "7.0.0", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "^3.1.0", + "karma-mocha": "^2.0.1", + "mocha": "^8.3.0", + "nyc": "^15.1.0", + "source-map-loader": "^3.0.0", + "ts-loader": "^9.2.6", + "typescript": "^4.4.2", + "webpack": "5.21.2", + "webpack-cli": "4.5.0", + "yarn": "^1.22.10" + } +} diff --git a/src/danfojs-base/plotting/index.ts b/src/danfojs-base/plotting/index.ts new file mode 100644 index 00000000..21ba3b53 --- /dev/null +++ b/src/danfojs-base/plotting/index.ts @@ -0,0 +1,137 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { + linePlot, + barPlot, + scatterPlot, + histPlot, + piePlot, + boxPlot, + violinPlot, + tablePlot, +} from "./plotly/index"; +import Series from "../core/series"; +import DataFrame from "../core/frame"; +import { PlotConfigObject, IPlotlyLib } from "../shared/types" +let Plotly: IPlotlyLib; + +if (typeof window !== "undefined") { + //check if in browser environment and require "plotly.js-dist-min" module + Plotly = require("plotly.js-dist-min") as IPlotlyLib; + +} + +class PlotlyLib implements IPlotlyLib { + divId: string; + ndframe: DataFrame | Series; + + constructor(ndframe: DataFrame | Series, divId: string) { + this.ndframe = ndframe; + this.divId = divId; + } + + private getPlotConfig(plotConfig?: PlotConfigObject) { + const _plotConfig = { + config: plotConfig && plotConfig.config ? plotConfig.config : {}, + layout: plotConfig && plotConfig.layout ? plotConfig.layout : {} + }; + return _plotConfig; + } + /** + * Plot Series or DataFrame as lines. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + line(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + linePlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + + /** + * Plot Series or DataFrame as bars. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + bar(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + barPlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + + /** + * Plot Series or DataFrame as scatter. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + scatter(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + scatterPlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + + /** + * Plot Series or DataFrame as histogram. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + hist(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + histPlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + + /** + * Plot Series or DataFrame as pie. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + pie(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + piePlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + + /** + * Plot Series or DataFrame as boxplot. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + box(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + boxPlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + + /** + * Plot Series or DataFrame as violinplot. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + violin(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + violinPlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + + /** + * Plot Series or DataFrame as table. + * Uses Plotly library as backend, so supports Plotly's configuration parameters + * @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. + */ + table(plotConfig?: PlotConfigObject) { + const _plotConfig = this.getPlotConfig(plotConfig); + tablePlot(this.ndframe, this.divId, _plotConfig, Plotly); + } + +} + + +export { + PlotlyLib +} diff --git a/src/danfojs-base/plotting/plotly/bar.ts b/src/danfojs-base/plotting/plotly/bar.ts new file mode 100644 index 00000000..415ffba6 --- /dev/null +++ b/src/danfojs-base/plotting/plotly/bar.ts @@ -0,0 +1,142 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { Data } from "plotly.js-dist-min" +import { InternalPlotConfigObject } from "../../shared/types" +import { checkIfColsExist, throwErrorOnWrongColName } from "./utils" + + +/** +* Plot Series or DataFrame as bar. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* Line plot supports different types of parameters, and the behavior will depend on data specified. +* The precedence of columns to plot is: (x and y => x => y => columns). +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +*/ +export const barPlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + + if (ndframe instanceof Series) { + let trace: Data = { + x: ndframe.index as any, + y: ndframe.values as any, + type: 'bar', + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + + if (config["x"] && config["y"]) { + //Plotting two columns against each other, when user specifies x and y column names in configuration + throwErrorOnWrongColName(ndframe, config["x"]); + throwErrorOnWrongColName(ndframe, config["y"]); + + const x = ndframe[config.x].values; + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'bar', + }; + + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + + } else if (config["x"] || config["y"]) { + //plot single column specified in either of param [x | y] against index + if (config["x"]) { + throwErrorOnWrongColName(ndframe, config.x); + + const x = ndframe[config.x].values; + const y = ndframe.index; + + const trace: Data = { + x, + y, + type: 'bar', + }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: "Index", + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + if (config["y"]) { + throwErrorOnWrongColName(ndframe, config.y); + + const x = ndframe.index + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'bar', + }; + const _layout = { + xaxis: { + title: "Index", + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + } else { + //plot specified columns in config param against index + // if columns is not specified in config, then plot all columns + const cols = config["columns"] ? checkIfColsExist(ndframe, config['columns']) : ndframe.columns; + + const traces: Data[] = []; + cols.forEach((col) => { + const x = ndframe.index; + const y = (ndframe as DataFrame)[col].values; + + const trace: Data = { x, y, name: col, type: 'bar' }; + traces.push(trace); + }); + + Plotly.newPlot(divId, traces, layout, config); + + } + + } + +} diff --git a/src/danfojs-base/plotting/plotly/box.ts b/src/danfojs-base/plotting/plotly/box.ts new file mode 100644 index 00000000..6c8e517b --- /dev/null +++ b/src/danfojs-base/plotting/plotly/box.ts @@ -0,0 +1,143 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { Data } from "plotly.js-dist-min" +import { InternalPlotConfigObject } from "../../shared/types" +import { checkIfColsExist, throwErrorOnWrongColName } from "./utils" + + +/** +* Plot Series or DataFrame as box chart. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* Line plot supports different types of parameters, and the behavior will depend on data specified. +* The precedence of columns to plot is: (x and y => x => y => columns). +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +*/ +export const boxPlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + + if (ndframe instanceof Series) { + let trace: Data = { + y: ndframe.values as any, + type: 'box', + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + + if (config["x"] && config["y"]) { + //Plotting two columns against each other, when user specifies x and y column names in configuration + throwErrorOnWrongColName(ndframe, config["x"]); + throwErrorOnWrongColName(ndframe, config["y"]); + + const x = ndframe[config.x].values; + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'box', + }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + + } else if (config["x"] || config["y"]) { + //plot single column specified in either of param [x | y] against index + if (config["x"]) { + throwErrorOnWrongColName(ndframe, config.x); + + const x = ndframe[config.x].values; + const y = ndframe.index; + + const trace: Data = { + x, + y, + type: 'box', + }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: "Index", + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + if (config["y"]) { + throwErrorOnWrongColName(ndframe, config.y); + + const x = ndframe.index + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'box', + }; + const _layout = { + xaxis: { + title: "Index", + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + } else { + //plot specified columns in config param against index + // if columns is not specified in config, then plot all columns + const cols = config["columns"] ? checkIfColsExist(ndframe, config['columns']) : ndframe.columns; + + const traces: Data[] = []; + cols.forEach((col) => { + const y = (ndframe as DataFrame)[col].values; + + const trace: Data = { + y, + name: col, + type: 'box', + }; + traces.push(trace); + }); + + Plotly.newPlot(divId, traces, layout, config); + + } + + } + +} diff --git a/src/danfojs-base/plotting/plotly/hist.ts b/src/danfojs-base/plotting/plotly/hist.ts new file mode 100644 index 00000000..7946438c --- /dev/null +++ b/src/danfojs-base/plotting/plotly/hist.ts @@ -0,0 +1,106 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { Data } from "plotly.js-dist-min" +import { InternalPlotConfigObject } from "../../shared/types" +import { checkIfColsExist, throwErrorOnWrongColName } from "./utils" + + +/** +* Plot Series or DataFrame as histogram. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* Line plot supports different types of parameters, and the behavior will depend on data specified. +* The precedence of columns to plot is: (x and y => x => y => columns). +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +*/ +export const histPlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + + if (ndframe instanceof Series) { + let trace: Data = { + x: ndframe.values as any, + type: 'histogram', + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + + if (config["x"] || config["y"]) { + //plot single column specified in either of param [x | y] against index + if (config["x"]) { + throwErrorOnWrongColName(ndframe, config.x); + + const x = ndframe[config.x].values; + + const trace: Data = { + x, + type: 'histogram', + }; + + const _layout = { + xaxis: { + title: config.x, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + if (config["y"]) { + throwErrorOnWrongColName(ndframe, config.y); + + const y = ndframe[config.y].values; + + const trace: Data = { + y, + type: 'histogram', + }; + const _layout = { + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + } else { + //plot specified columns in config param against index + // if columns is not specified in config, then plot all columns + const cols = config["columns"] ? checkIfColsExist(ndframe, config['columns']) : ndframe.columns; + + const traces: Data[] = []; + cols.forEach((col) => { + const y = ndframe.index; + const x = (ndframe as DataFrame)[col].values; + + const trace: Data = { x, y, name: col, type: 'histogram' }; + traces.push(trace); + }); + + Plotly.newPlot(divId, traces, layout, config); + + } + + } + +} diff --git a/danfojs-browser/src/shared/defaults.js b/src/danfojs-base/plotting/plotly/index.ts similarity index 61% rename from danfojs-browser/src/shared/defaults.js rename to src/danfojs-base/plotting/plotly/index.ts index 808494bc..67de8e15 100644 --- a/danfojs-browser/src/shared/defaults.js +++ b/src/danfojs-base/plotting/plotly/index.ts @@ -1,6 +1,6 @@ /** * @license -* Copyright 2021, JsData. All rights reserved. +* Copyright 2022 JsData. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -13,15 +13,11 @@ * ========================================================================== */ -/** - * Default config object - */ -export const BASE_CONFIG = { - tableMaxRow: 10, - tableMaxColInConsole: 21, - dtypeTestLim: 7, - lowMemoryMode: false -}; - - -export const DATA_TYPES = ["float32", "int32", "string", "boolean", 'undefined']; +export { linePlot } from "./line"; +export { barPlot } from "./bar"; +export { scatterPlot } from "./scatter"; +export { histPlot } from "./hist"; +export { piePlot } from "./pie"; +export { boxPlot } from "./box"; +export { violinPlot } from "./violin"; +export { tablePlot } from "./table"; diff --git a/src/danfojs-base/plotting/plotly/line.ts b/src/danfojs-base/plotting/plotly/line.ts new file mode 100644 index 00000000..1d238841 --- /dev/null +++ b/src/danfojs-base/plotting/plotly/line.ts @@ -0,0 +1,132 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { Data } from "plotly.js-dist-min" +import { InternalPlotConfigObject } from "../../shared/types" +import { checkIfColsExist, throwErrorOnWrongColName } from "./utils" + + +/** +* Plot Series or DataFrame as lines. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* Line plot supports different types of parameters, and the behavior will depend on data specified. +* The precedence of columns to plot is: (x and y => x => y => columns). +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +* @param Plotly Plotly package passed from the class. +*/ +export const linePlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + + if (ndframe instanceof Series) { + const y = ndframe.values as any; + let trace: Data = { + x: ndframe.index as any, + y, + type: 'scatter', + mode: 'lines', + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + + if (config["x"] && config["y"]) { + //Plotting two columns against each other, when user specifies x and y column names in configuration + throwErrorOnWrongColName(ndframe, config["x"]); + throwErrorOnWrongColName(ndframe, config["y"]); + + const x = ndframe[config.x].values; + const y = ndframe[config.y].values; + + const trace: Data = { x, y }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + + } else if (config["x"] || config["y"]) { + //plot single column specified in either of param [x | y] against index + if (config["x"]) { + throwErrorOnWrongColName(ndframe, config.x); + + const x = ndframe[config.x].values; + const y = ndframe.index; + + const trace: Data = { x, y }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: "Index", + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + if (config["y"]) { + throwErrorOnWrongColName(ndframe, config.y); + + const x = ndframe.index + const y = ndframe[config.y].values; + + const trace: Data = { x, y }; + const _layout = { + xaxis: { + title: "Index", + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + } else { + //plot specified columns in config param against index + // if columns is not specified in config, then plot all columns + const cols = config["columns"] ? checkIfColsExist(ndframe, config['columns']) : ndframe.columns; + + const traces: Data[] = []; + cols.forEach((col) => { + const x = ndframe.index; + const y = (ndframe as DataFrame)[col].values; + + const trace: Data = { x, y, name: col }; + traces.push(trace); + }); + + Plotly.newPlot(divId, traces, layout, config); + + } + + } + +} diff --git a/src/danfojs-base/plotting/plotly/pie.ts b/src/danfojs-base/plotting/plotly/pie.ts new file mode 100644 index 00000000..29683e1e --- /dev/null +++ b/src/danfojs-base/plotting/plotly/pie.ts @@ -0,0 +1,144 @@ +// @ts-nocheck + +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { Data } from "plotly.js-dist-min" +import { InternalPlotConfigObject } from "../../shared/types" +import { checkIfColsExist } from "./utils" + + +/** +* Plot Series or DataFrame as pie chart. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* Line plot supports different types of parameters, and the behavior will depend on data specified. +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +*/ +export const piePlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + + if (ndframe instanceof Series) { + let trace: Data = { + values: ndframe.values as any, + labels: config["labels"] || ndframe.index as any, + type: 'pie', + name: config.labels, + hoverinfo: 'label+percent+name', + automargin: true + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + if (config["labels"]) { + + if (!ndframe.columns.includes(config['labels'])) { + throw Error(`Column Error: ${config['labels']} not found in columns. Param "labels" name must be one of [ ${ndframe.columns}]`); + } + + if (config["values"]) { + + if (!ndframe.columns.includes(config['values'])) { + throw Error(`Column Error: ${config['values']} not found in columns. Param "values" name must be one of [ ${ndframe.columns}]`); + } + + let trace: Data = { + values: ndframe[config['values']].values as any, + labels: ndframe[config["labels"]].values as any, + type: 'pie', + name: config.labels, + hoverinfo: 'label+percent+name', + automargin: true + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + // if columns is not specified in config, then plot all columns + const cols = config["columns"] ? checkIfColsExist(ndframe, config['columns']) : ndframe.columns; + + if (config['rowPositions']) { + if (config['rowPositions'].length != cols.length) { + throw Error(`length of rowPositions array must be equal to number of columns. Got ${config['rowPositions'].length}, expected ${cols.length - 1}`); + } + } else { + let tempArr = []; + for (let i = 0; i < cols.length - 1; i++) { + tempArr.push(0); + } + config['rowPositions'] = tempArr; + + } + + if (config['columnPositions']) { + if (config['columnPositions'].length != cols.length) { + throw Error(`length of columnPositions array must be equal to number of columns. Got ${config['columnPositions'].length}, expected ${cols.length - 1}`); + } + } else { + let tempArr = []; + for (let i = 0; i < cols.length - 1; i++) { + tempArr.push(i); + } + config['columnPositions'] = tempArr; + + } + + const traces: Data[] = []; + cols.forEach((col, i) => { + const labels = (ndframe as DataFrame)[config["labels"]].values; + const values = (ndframe as DataFrame)[col].values; + + const trace: Data = { + labels, + values, + name: col, + type: 'pie', + domain: { + row: config['rowPositions'][i], + column: config['columnPositions'][i] + }, + hoverinfo: 'label+percent+name', + automargin: true, + textposition: 'outside' + }; + traces.push(trace); + }); + + const _layout = { + ...layout, + } + + if (!config["grid"]) { + //set default grid + let size = Number((ndframe.shape[1] / 2).toFixed()) + 1; + _layout["grid"] = { rows: size, columns: size }; + }else{ + _layout["grid"] = config["grid"]; + } + + Plotly.newPlot(divId, traces, _layout, config); + + } + } else { + throw new Error(`Param Error: Please provide a column name for "labels" param`) + } + + } + +} diff --git a/src/danfojs-base/plotting/plotly/scatter.ts b/src/danfojs-base/plotting/plotly/scatter.ts new file mode 100644 index 00000000..95e03262 --- /dev/null +++ b/src/danfojs-base/plotting/plotly/scatter.ts @@ -0,0 +1,151 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { Data } from "plotly.js-dist-min" +import { InternalPlotConfigObject } from "../../shared/types" +import { checkIfColsExist, throwErrorOnWrongColName } from "./utils" + +/** +* Plot Series or DataFrame as scatter points. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* Line plot supports different types of parameters, and the behavior will depend on data specified. +* The precedence of columns to plot is: (x and y => x => y => columns). +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +*/ +export const scatterPlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + + if (ndframe instanceof Series) { + const y = ndframe.values as any; + let trace: Data = { + x: ndframe.index as any, + y, + type: 'scatter', + mode: 'markers', + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + + if (config["x"] && config["y"]) { + //Plotting two columns against each other, when user specifies x and y column names in configuration + throwErrorOnWrongColName(ndframe, config["x"]); + throwErrorOnWrongColName(ndframe, config["y"]); + + const x = ndframe[config.x].values; + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'scatter', + mode: 'markers', + }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + + } else if (config["x"] || config["y"]) { + //plot single column specified in either of param [x | y] against index + if (config["x"]) { + throwErrorOnWrongColName(ndframe, config.x); + + const x = ndframe[config.x].values; + const y = ndframe.index; + + const trace: Data = { + x, + y, + type: 'scatter', + mode: 'markers', + }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: "Index", + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + if (config["y"]) { + throwErrorOnWrongColName(ndframe, config.y); + + const x = ndframe.index + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'scatter', + mode: 'markers', + }; + const _layout = { + xaxis: { + title: "Index", + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + } else { + //plot specified columns in config param against index + // if columns is not specified in config, then plot all columns + const cols = config["columns"] ? checkIfColsExist(ndframe, config['columns']) : ndframe.columns; + + const traces: Data[] = []; + cols.forEach((col) => { + const y = ndframe.index; + const x = (ndframe as DataFrame)[col].values; + + const trace: Data = { + x, + y, + name: col, + type: 'scatter', + mode: 'markers', + }; + traces.push(trace); + }); + + Plotly.newPlot(divId, traces, layout, config); + + } + + } + +} diff --git a/src/danfojs-base/plotting/plotly/table.ts b/src/danfojs-base/plotting/plotly/table.ts new file mode 100644 index 00000000..54d220e9 --- /dev/null +++ b/src/danfojs-base/plotting/plotly/table.ts @@ -0,0 +1,77 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { InternalPlotConfigObject } from "../../shared/types" + + +/** +* Display Series or DataFrame as table. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +*/ +export const tablePlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + let header: any = {}; + let cells: any = {}; + let colsData: any[] = []; + let cols2Show: any[] = [] + + if (config['columns']) { + + config['columns'].forEach((cname) => { + if (!ndframe.columns.includes(cname)) { + throw Error(`Column Error: ${cname} not found in columns. Columns should be one of [ ${ndframe.columns} ]`); + } + + let idx = ndframe.columns.indexOf(cname); + colsData.push(ndframe.getColumnData[idx]); + }); + + cols2Show = config['columns']; + } else { + + cols2Show = ndframe.columns; + colsData = ndframe.getColumnData; + + } + + header['values'] = cols2Show.map((col) => [col]); + cells['values'] = colsData; + + if (config['tableHeaderStyle']) { + Object.keys(config['tableHeaderStyle']).forEach((param) => { + header[param] = config['tableHeaderStyle'][param]; + }); + } + + if (config['tableCellStyle']) { + Object.keys(config['tableCellStyle']).forEach((param) => { + cells[param] = config['tableCellStyle'][param]; + }); + } + + const trace = { + type: 'table', + header, + cells + }; + /* @ts-ignore */ + Plotly.newPlot(divId, [trace], layout, config); + +} diff --git a/src/danfojs-base/plotting/plotly/utils.ts b/src/danfojs-base/plotting/plotly/utils.ts new file mode 100644 index 00000000..116ff9a7 --- /dev/null +++ b/src/danfojs-base/plotting/plotly/utils.ts @@ -0,0 +1,32 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; + +export const checkIfColsExist = (ndframe: DataFrame | Series, cols: string[]) => { + cols.forEach((col) => { + if (!ndframe.columns.includes(col)) { + throw Error(`Column Error: ${col} not found in columns. Columns should be one of [ ${ndframe.columns} ]`); + } + }); + return cols; +} + +export const throwErrorOnWrongColName = (ndframe: DataFrame, colName: string): void => { + if (!ndframe.columns.includes(colName)) { + throw Error(`ParamError: specified column ${colName} not found in columns`); + } +} diff --git a/src/danfojs-base/plotting/plotly/violin.ts b/src/danfojs-base/plotting/plotly/violin.ts new file mode 100644 index 00000000..c0ca5fcb --- /dev/null +++ b/src/danfojs-base/plotting/plotly/violin.ts @@ -0,0 +1,143 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import Series from "../../core/series"; +import DataFrame from "../../core/frame"; +import { Data } from "plotly.js-dist-min" +import { InternalPlotConfigObject } from "../../shared/types" +import { checkIfColsExist, throwErrorOnWrongColName } from "./utils" + + +/** +* Plot Series or DataFrame as violin chart. +* Uses the Plotly as backend, so supoorts Plotly's configuration parameters, +* Line plot supports different types of parameters, and the behavior will depend on data specified. +* The precedence of columns to plot is: (x and y => x => y => columns). +* @param ndframe Series or DataFrame to plot +* @param divId HTML div id to plot in. +* @param plotConfig configuration options for making Plots, supports Plotly.js Config and Layout parameters. +*/ +export const violinPlot = (ndframe: DataFrame | Series, divId: string, plotConfig: InternalPlotConfigObject, Plotly: any) => { + const config = plotConfig["config"] + const layout = plotConfig["layout"] + + if (ndframe instanceof Series) { + let trace: Data = { + y: ndframe.values as any, + type: 'violin', + }; + + Plotly.newPlot(divId, [trace], layout, config); + + } else { + + if (config["x"] && config["y"]) { + //Plotting two columns against each other, when user specifies x and y column names in configuration + throwErrorOnWrongColName(ndframe, config["x"]); + throwErrorOnWrongColName(ndframe, config["y"]); + + const x = ndframe[config.x].values; + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'violin', + }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + + } else if (config["x"] || config["y"]) { + //plot single column specified in either of param [x | y] against index + if (config["x"]) { + throwErrorOnWrongColName(ndframe, config.x); + + const x = ndframe[config.x].values; + const y = ndframe.index; + + const trace: Data = { + x, + y, + type: 'violin', + }; + const _layout = { + xaxis: { + title: config.x, + }, + yaxis: { + title: "Index", + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + if (config["y"]) { + throwErrorOnWrongColName(ndframe, config.y); + + const x = ndframe.index + const y = ndframe[config.y].values; + + const trace: Data = { + x, + y, + type: 'violin', + }; + const _layout = { + xaxis: { + title: "Index", + }, + yaxis: { + title: config.y, + }, + ...layout, + }; + + Plotly.newPlot(divId, [trace], _layout, config); + } + + } else { + //plot specified columns in config param against index + // if columns is not specified in config, then plot all columns + const cols = config["columns"] ? checkIfColsExist(ndframe, config['columns']) : ndframe.columns; + + const traces: Data[] = []; + cols.forEach((col) => { + const y = (ndframe as DataFrame)[col].values; + + const trace: Data = { + y, + name: col, + type: 'violin', + }; + traces.push(trace); + }); + + Plotly.newPlot(divId, traces, layout, config); + + } + + } + +} diff --git a/danfojs-browser/types/shared/defaults.d.ts b/src/danfojs-base/plotting/vega/index.ts similarity index 66% rename from danfojs-browser/types/shared/defaults.d.ts rename to src/danfojs-base/plotting/vega/index.ts index 72b539a5..480765d3 100644 --- a/danfojs-browser/types/shared/defaults.d.ts +++ b/src/danfojs-base/plotting/vega/index.ts @@ -1,6 +1,6 @@ /** * @license -* Copyright 2021, JsData. All rights reserved. +* Copyright 2022 JsData. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,13 +12,5 @@ * limitations under the License. * ========================================================================== */ -/** - * Default config object - */ -export declare const BASE_CONFIG: { - tableMaxRow: number; - tableMaxColInConsole: number; - dtypeTestLim: number; - lowMemoryMode: boolean; -}; -export declare const DATA_TYPES: string[]; + +//TODO: Add support for vega library plots \ No newline at end of file diff --git a/src/danfojs-base/shared/config.ts b/src/danfojs-base/shared/config.ts new file mode 100644 index 00000000..638d3394 --- /dev/null +++ b/src/danfojs-base/shared/config.ts @@ -0,0 +1,90 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { BaseUserConfig, TableUserConfig } from 'table'; +import { ConfigsType } from './types' + +/** + * Package wide configuration class + */ +export default class Configs { + tableDisplayConfig: BaseUserConfig & TableUserConfig + tableMaxRow: number; + tableMaxColInConsole: number; + dtypeTestLim: number; + lowMemoryMode: boolean; + + constructor(options: ConfigsType) { + const { + tableDisplayConfig, + tableMaxRow, + tableMaxColInConsole, + dtypeTestLim, + lowMemoryMode, + } = { + tableDisplayConfig: {}, + tableMaxRow: 10, + tableMaxColInConsole: 10, + dtypeTestLim: 500, + lowMemoryMode: false, + ...options + } + this.tableDisplayConfig = tableDisplayConfig + this.tableMaxRow = tableMaxRow // The maximum number of rows to display in console + this.tableMaxColInConsole = tableMaxColInConsole // The maximum number of columns to display in console + this.dtypeTestLim = dtypeTestLim // The number of rows to use when inferring data type + this.lowMemoryMode = lowMemoryMode // Whether to use minimal memory or not. + } + + setTableDisplayConfig(config: BaseUserConfig & TableUserConfig) { + this.tableDisplayConfig = config; + } + + get getTableDisplayConfig(): BaseUserConfig & TableUserConfig { + return this.tableDisplayConfig; + } + + setTableMaxColInConsole(val: number) { + this.tableMaxColInConsole = val; + } + + get getTableMaxColInConsole(): number { + return this.tableMaxColInConsole; + } + + setMaxRow(val: number) { + this.tableMaxRow = val; + } + + get getMaxRow(): number { + return this.tableMaxRow; + } + + get getDtypeTestLim(): number { + return this.dtypeTestLim; + } + + setDtypeTestLim(val: number) { + this.dtypeTestLim = val; + } + + get isLowMemoryMode(): boolean { + return this.lowMemoryMode; + } + + setIsLowMemoryMode(val: boolean) { + this.lowMemoryMode = val; + } +} + diff --git a/danfojs-node/src/shared/defaults.js b/src/danfojs-base/shared/defaults.ts similarity index 79% rename from danfojs-node/src/shared/defaults.js rename to src/danfojs-base/shared/defaults.ts index 808494bc..99e6d490 100644 --- a/danfojs-node/src/shared/defaults.js +++ b/src/danfojs-base/shared/defaults.ts @@ -1,6 +1,6 @@ /** * @license -* Copyright 2021, JsData. All rights reserved. +* Copyright 2022 JsData. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -17,11 +17,10 @@ * Default config object */ export const BASE_CONFIG = { - tableMaxRow: 10, - tableMaxColInConsole: 21, - dtypeTestLim: 7, - lowMemoryMode: false -}; + tableMaxRow: 10, + tableMaxColInConsole: 10, + dtypeTestLim: 20, + lowMemoryMode: false, +} - -export const DATA_TYPES = ["float32", "int32", "string", "boolean", 'undefined']; +export const DATA_TYPES = ["float32", "int32", "string", "boolean", "datetime",'undefined']; diff --git a/src/danfojs-base/shared/errors.ts b/src/danfojs-base/shared/errors.ts new file mode 100644 index 00000000..9ccc4f86 --- /dev/null +++ b/src/danfojs-base/shared/errors.ts @@ -0,0 +1,101 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import DataFrame from "../core/frame" +import NDframe from "../core/generic" +import { DATA_TYPES } from "./defaults" + +/** + * Package wide error throwing class + */ +class ErrorThrower { + + throwColumnNamesLengthError = (ndframe: NDframe, columns: Array): void => { + const msg = `ParamError: Column names length mismatch. You provided a column of length ${columns.length} but Ndframe columns has length of ${ndframe.shape[1]}` + throw new Error(msg) + } + + throwIndexLengthError = (ndframe: NDframe, index: Array): void => { + const msg = `IndexError: You provided an index of length ${index.length} but Ndframe rows has length of ${ndframe.shape[0]}` + throw new Error(msg) + } + + throwIndexDuplicateError = (): void => { + const msg = `IndexError: Row index must contain unique values` + throw new Error(msg) + } + + throwColumnDuplicateError = (): void => { + const msg = `ColumnIndexError: Column index must contain unique values` + throw new Error(msg) + } + + throwDtypesLengthError = (ndframe: NDframe, dtypes: Array): void => { + const msg = `DtypeError: You provided a dtype array of length ${dtypes.length} but Ndframe columns has length of ${ndframe.shape[1]}` + throw new Error(msg) + } + + throwDtypeNotSupportedError = (dtype: string): void => { + const msg = `DtypeError: Dtype "${dtype}" not supported. dtype must be one of "${DATA_TYPES}"` + throw new Error(msg) + } + + throwDtypeWithoutColumnError = (): void => { + const msg = `DtypeError: columns parameter must be provided when dtypes parameter is provided` + throw new Error(msg) + } + + throwColumnLengthError = (ndframe: NDframe | DataFrame, arrLen: number): void => { + const msg = `ParamError: Column data length mismatch. You provided data with length ${arrLen} but Ndframe has column of length ${ndframe.shape[0]}` + throw new Error(msg) + } + + throwRowLengthError = (ndframe: NDframe, arrLen: number): void => { + const msg = `ParamError: Row data length mismatch. You provided data with length ${arrLen} but Ndframe has row of length ${ndframe.shape[0]}` + throw new Error(msg) + } + + throwColumnNotFoundError = (ndframe: DataFrame | NDframe): void => { + const msg = `ParamError: Column not found!. Column name must be one of ${ndframe.columns}` + throw new Error(msg) + } + + throwNotImplementedError = (): void => { + const msg = `Method not implemented` + throw new Error(msg) + } + + throwIlocRowIndexError = (): void => { + const msg = `ParamError: rows parameter must be a Array. For example: rows: [1,2] or rows: ["0:10"]` + throw new Error(msg) + } + + throwIlocColumnsIndexError = (): void => { + const msg = `ParamError: columns parameter must be a Array. For example: columns: [1,2] or columns: ["0:10"]` + throw new Error(msg) + } + + throwStringDtypeOperationError = (operation: string): void => { + const msg = `DtypeError: String data type does not support ${operation} operation` + throw new Error(msg) + } + + throwSeriesMathOpLengthError = (ndframe: NDframe, other: NDframe): void => { + const msg = `ParamError: Row length mismatch. Length of other (${other.shape[0]}), must be the same as Ndframe (${ndframe.shape[0]})` + throw new Error(msg) + } + +} + +export default new ErrorThrower() \ No newline at end of file diff --git a/src/danfojs-base/shared/tensorflowlib.ts b/src/danfojs-base/shared/tensorflowlib.ts new file mode 100644 index 00000000..476573e8 --- /dev/null +++ b/src/danfojs-base/shared/tensorflowlib.ts @@ -0,0 +1,2 @@ +const tf = require("@tensorflow/tfjs-node") +export default tf \ No newline at end of file diff --git a/src/danfojs-base/shared/types.ts b/src/danfojs-base/shared/types.ts new file mode 100644 index 00000000..d89be170 --- /dev/null +++ b/src/danfojs-base/shared/types.ts @@ -0,0 +1,419 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import { BaseUserConfig, TableUserConfig, } from "table" +import { Config, Layout } from "plotly.js-dist-min" +import { HeadersInit } from "node-fetch"; +import Groupby from '../aggregators/groupby'; +import { ParseConfig } from 'papaparse'; +import DataFrame from '../core/frame'; +import Series from '../core/series'; +import Str from '../core/strings'; +import Dt from '../core/datetime'; +import { ParsingOptions, WritingOptions } from "xlsx"; + +export type DTYPES = "float32" | "int32" | "string" | "boolean" | "undefined" + +export type ArrayType2D = Array< + number[] + | string[] + | boolean[] + | (number | string | boolean)[]> + +export type ArrayType1D = Array< + number + | string + | boolean + | (number | string | boolean)> + +//Start of Config class types +export type ConfigsType = { + tableDisplayConfig?: BaseUserConfig & TableUserConfig + tableMaxRow?: number; + tableMaxColInConsole?: number; + dtypeTestLim?: number; + lowMemoryMode?: boolean + tfInstance?: any +} +//End of Config class types + +//Start of Generic class types +export interface BaseDataOptionType { + type?: number; + index?: Array + columns?: string[] + dtypes?: Array + config?: ConfigsType; +} +export interface NdframeInputDataType { + data: any + type?: number; + index?: Array + columns?: string[] + dtypes?: Array + config?: ConfigsType; + isSeries: boolean; +} +export interface LoadArrayDataType { + data: ArrayType1D | ArrayType2D + index?: Array + columns?: string[] + dtypes?: Array +} + +export interface LoadObjectDataType { + data: object | Array + type?: number; + index?: Array + columns?: string[] + dtypes?: Array +} + +export type AxisType = { + index: Array + columns: Array +} +export interface NDframeInterface { + config?: ConfigsType; + $setDtypes(dtypes: Array, infer: boolean): void; + $setIndex(index: Array): void; + $resetIndex(): void; + $setColumnNames(columns: string[]): void + get dtypes(): Array; + get ndim(): number; + get axis(): AxisType; + get index(): Array; + get columns(): string[] + get shape(): Array; + get values(): ArrayType1D | ArrayType2D + get tensor(): any + get size(): number; + print(): void; +} +//End of Generic class types + + +//Start of Series class types +type mapFunc = (val: any, i: number) => any[] + +export type mapParam = object | mapFunc +export interface SeriesInterface extends NDframeInterface { + iloc(rows: Array | boolean[]): Series; + head(rows: number): Series + tail(rows: number): Series + sample(num: number, options?: { seed?: number }): Promise; + add(other: Series | number | Array, options?: { inplace?: boolean }): Series | void; + sub(other: Series | number | Array, options?: { inplace?: boolean }): Series | void; + mul(other: Series | number | Array, options?: { inplace?: boolean }): Series | void; + div(other: Series | number | Array, options?: { inplace?: boolean }): Series | void; + pow(other: Series | number | Array, options?: { inplace?: boolean }): Series | void; + mod(other: Series | number | Array, options?: { inplace?: boolean }): Series | void; + mean(): number + median(): number + mode(): any + min(): number + max(): number + sum(): number + count(): number + maximum(other: Series | number | Array): Series + minimum(other: Series | number | Array): Series + round(dp: number, options?: { inplace?: boolean }): Series | void + std(): number + var(): number + isNa(): Series + fillNa(value: number | string | boolean, options?: { inplace?: boolean }): Series | void + sortValues(options?: { ascending?: boolean, inplace?: boolean }): Series | void + copy(): Series + describe(): Series + resetIndex(options?: { inplace?: boolean }): Series | void + setIndex(index: Array, options?: { inplace?: boolean }): Series | void + map( + callable: mapParam, + options?: { inplace?: boolean }) + : Series | void + apply( + callable: (value: any) => any, + options?: { inplace?: boolean }): Series | void + unique(): Series + nUnique(): number + valueCounts(): Series + abs(options?: { inplace?: boolean }): Series | void + cumSum(options?: { inplace?: boolean }): Series | void + cumMin(options?: { inplace?: boolean }): Series | void + cumMax(options?: { inplace?: boolean }): Series | void + cumProd(options?: { inplace?: boolean }): Series | void + lt(other: Series | number | Array | boolean[]): Series + gt(other: Series | number | Array | boolean[]): Series + le(other: Series | number | Array | boolean[]): Series + ge(other: Series | number | Array | boolean[]): Series + ne(other: Series | number | Array | boolean[]): Series + eq(other: Series | number | Array | boolean[]): Series + replace(oldValue: string | number | boolean, newValue: string | number | boolean, options?: { inplace?: boolean }): Series | void + dropNa(options?: { inplace?: boolean }): Series | void + argSort(options?: { ascending: boolean }): Series + argMax(): number + argMin(): number + get dtype(): string + dropDuplicates(options?: { keep?: "first" | "last", inplace?: boolean }): Series | void + asType(dtype: "float32" | "int32" | "string" | "boolean", options?: { inplace?: boolean }): Series | void + get str(): Str + get dt(): Dt + append(values: string | number | boolean | Series | ArrayType1D, + index: Array | number | string, + options?: { inplace?: boolean }): Series | void + toString(): string; + and(other: any): Series + or(other: any): Series + getDummies(options?: { + prefix?: string | Array, + prefixSeparator?: string | Array, + inplace?: boolean + }): DataFrame + iat(index: number): number | string | boolean | undefined + at(index: string | number): number | string | boolean | undefined + plot(divId: string): IPlotlyLib +} + +//Start of DataFrame class types +export interface DataFrameInterface extends NDframeInterface { + [key: string]: any + drop( + options: + { + columns?: string | Array, + index?: Array, + inplace?: boolean + } + ): DataFrame | void + loc(options: + { + rows?: Array, + columns?: Array + }): DataFrame; + iloc(options: + { + rows?: Array, + columns?: Array + }): DataFrame; + head(rows?: number): DataFrame + tail(rows?: number): DataFrame + sample(num: number, options?: { seed?: number }): Promise; + add(other: DataFrame | Series | number | number[], options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + sub(other: DataFrame | Series | number | number[], options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + mul(other: DataFrame | Series | number | number[], options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + div(other: DataFrame | Series | number | number[], options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + divNoNan(other: DataFrame | Series | number | number[], options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + pow(other: DataFrame | Series | number | number[], options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + mod(other: DataFrame | Series | number | number[], options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + pctChange(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + diff(other: DataFrame | Series | number[] | number, options?: { axis?: 0 | 1, inplace?: boolean }): DataFrame | void + mean(options?: { axis?: 0 | 1 }): Series + median(options?: { axis?: 0 | 1 }): Series + mode(options?: { axis?: 0 | 1, keep?: number }): Series + min(options?: { axis?: 0 | 1 }): Series + max(options?: { axis?: 0 | 1 }): Series + std(options?: { axis?: 0 | 1 }): Series + var(options?: { axis?: 0 | 1 }): Series + sum(options?: { axis?: 0 | 1 }): Series + count(options?: { axis?: 0 | 1 }): Series + round(dp?: number, options?: { inplace: boolean }): DataFrame | void + cumSum(options?: { axis?: 0 | 1 }): DataFrame | void + cumMin(options?: { axis?: 0 | 1 }): DataFrame | void + cumMax(options?: { axis?: 0 | 1 }): DataFrame | void + cumProd(options?: { axis?: 0 | 1 }): DataFrame | void + copy(): DataFrame + resetIndex(options: { inplace?: boolean }): DataFrame | void + setIndex( + options: + { + index: Array, + column?: string, + drop?: boolean, + inplace?: boolean + } + ): DataFrame | void + describe(): DataFrame + selectDtypes(include: Array): DataFrame + abs(options?: { inplace?: boolean }): DataFrame | void + query(condition: Series | Array, options?: { inplace?: boolean }): DataFrame | void + addColumn( + column: string, + values: Series | ArrayType1D, + options?: { + inplace?: boolean, + atIndex?: number | string + } + ): DataFrame | void + groupby(col: Array): Groupby + column(column: string): Series + fillNa(value: ArrayType1D, + options?: + { + columns?: Array, + inplace?: boolean + }): DataFrame | void + isNa(): DataFrame + dropNa(options?: { axis: 0 | 1, inplace?: boolean }): DataFrame | void + apply(callable: any, options?: { axis?: 0 | 1 }): DataFrame | Series + applyMap(callable: any, options?: { inplace?: boolean }): DataFrame | void + lt(other: DataFrame | Series | number, options?: { axis?: 0 | 1 }): DataFrame + gt(other: DataFrame | Series | number, options?: { axis?: 0 | 1 }): DataFrame + le(other: DataFrame | Series | number, options?: { axis?: 0 | 1 }): DataFrame + ge(other: DataFrame | Series | number, options?: { axis?: 0 | 1 }): DataFrame + ne(other: DataFrame | Series | number, options?: { axis?: 0 | 1 }): DataFrame + eq(other: DataFrame | Series | number, options?: { axis?: 0 | 1 }): DataFrame + replace( + oldValue: number | string | boolean, + newValue: number | string | boolean, + options?: { + columns?: Array + inplace?: boolean + } + ): DataFrame | void + transpose(options?: { inplace?: boolean }): DataFrame | void + get T(): DataFrame + get ctypes(): Series + asType( + column: string, + dtype: "float32" | "int32" | "string" | "boolean", + options?: { inplace?: boolean } + ): DataFrame | void + nUnique(axis: 0 | 1): Series + rename( + mapper: object, + options?: { + axis?: 0 | 1 + inplace?: boolean + } + ): DataFrame | void + sortIndex(options?: + { + inplace?: boolean + ascending?: boolean + } + ): DataFrame | void + sortValues( + column: string, + options?: + { + inplace?: boolean + ascending?: boolean + } + ): DataFrame | void + append( + newValues: ArrayType1D | ArrayType2D | Series | DataFrame, + index: Array | number | string, + options?: { + inplace?: boolean, + } + ): DataFrame | void + toString(): string; + getDummies(options?: { + columns?: string | Array, + prefix?: string | Array, + prefixSeparator?: string | Array, + inplace?: boolean + }): DataFrame | void + iat(row: number, column: number): number | string | boolean | undefined + at(row: string | number, column: string): number | string | boolean | undefined + plot(divId: string): IPlotlyLib +} + +export interface DateTime { + month(): Series + dayOfWeek(): Series + year(): Series + monthName(): Series + dayOfMonth(): Series + hours(): Series + seconds(): Series + minutes(): Series + date(): Series +} + +interface CustomConfig extends Config { + x: string + y: string, + values: string, + labels: string, + rowPositions: number[], + columnPositions: number[], + grid: { rows: number, columns: number }, + tableHeaderStyle: any, + tableCellStyle: any, + columns: string[]; +} + +export type PlotConfigObject = { + config?: Partial + layout?: Partial +} + +export type InternalPlotConfigObject = { + config: Partial + layout: Partial +} + +export interface IPlotlyLib { + line(plotConfig?: PlotConfigObject): void + bar(plotConfig?: PlotConfigObject): void + scatter(plotConfig?: PlotConfigObject): void + hist(plotConfig?: PlotConfigObject): void + pie(plotConfig?: PlotConfigObject): void + box(plotConfig?: PlotConfigObject): void + violin(plotConfig?: PlotConfigObject): void + table(plotConfig?: PlotConfigObject): void +} + +export interface CsvInputOptionsBrowser extends ParseConfig { + frameConfig?: BaseDataOptionType +} +export type ExcelInputOptionsBrowser = { + sheet?: number, + method?: string, + headers?: any, + frameConfig?: BaseDataOptionType + parsingOptions?: ParsingOptions +} +export type JsonInputOptionsBrowser = { + method?: string, + headers?: any, + frameConfig?: BaseDataOptionType +} + +export interface CsvInputOptionsNode extends ParseConfig { + frameConfig?: BaseDataOptionType +} + +export type ExcelInputOptionsNode = { + sheet?: number, + method?: string, + headers?: HeadersInit + frameConfig?: BaseDataOptionType + parsingOptions?: ParsingOptions +} +export type JsonInputOptionsNode = { + method?: string, + headers?: HeadersInit + frameConfig?: BaseDataOptionType +} + +export type CsvOutputOptionsBrowser = { fileName?: string, sep?: string, header?: boolean, download?: boolean }; +export type ExcelOutputOptionsBrowser = { fileName?: string, sheetName?: string, writingOptions?: WritingOptions }; +export type JsonOutputOptionsBrowser = { fileName?: string, format?: "row" | "column", download?: boolean }; + +export type CsvOutputOptionsNode = { filePath?: string, sep?: string, header?: boolean } +export type JsonOutputOptionsNode = { format?: "row" | "column", filePath?: string } +export type ExcelOutputOptionsNode = { filePath?: string, sheetName?: string, writingOptions?: WritingOptions } diff --git a/src/danfojs-base/shared/utils.ts b/src/danfojs-base/shared/utils.ts new file mode 100644 index 00000000..8dc4de8e --- /dev/null +++ b/src/danfojs-base/shared/utils.ts @@ -0,0 +1,858 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import { BASE_CONFIG } from './defaults' +import Config from './config'; +import { ArrayType1D, ArrayType2D } from './types'; +import { Series } from '../'; +import { DataFrame } from '../'; +import ErrorThrower from '../shared/errors' + +const config = new Config(BASE_CONFIG); + +/** + * General Utility class + */ +export default class Utils { + /** + * Removes an element from a 1D array + * + * ```js + * + * ``` + * @param arr The array to filter. + * @param index The index to filter by. + */ + removeElementFromArray(arr: ArrayType1D, index: number): ArrayType1D { + const newArr = arr.filter((_, i: number) => i != index); + return newArr; + } + + /** + * Check if value is a string. + * @param value The value to check. + * @returns + */ + isString(value: T): boolean { + return typeof value === "string"; + } + + /** + * Checks if value is a number. + * @param value The value to check. + * @returns + */ + isNumber(value: T): boolean { + return typeof value === "number" && isFinite(value); + } + + /** + * Checks if value is an object. + * @param value The value to check. + * @returns + */ + isObject(value: any): boolean { + return value && typeof value === "object" && value.constructor && value.constructor.name === "Object"; + } + + /** + * Checks if a value is null + * @param value The value to check. + * @returns + */ + isNull(value: T): boolean { + return value === null; + } + + /** + * Checks if a value is undefined + * @param value The value to check. + * @returns + */ + isUndefined(value: T): boolean { + return typeof value === "undefined"; + } + + /** + * Checks if a value is empty. Empty means it's either null, undefined or NaN. + * Empty strings are NOT considered empty. + * @param value The value to check. + * @returns boolean indicating if the value is empty + */ + isEmpty(value: T): boolean { + if (value === undefined || value === null) { + return true; + } + + if (typeof value === 'bigint') { + return false; // BigInt values are never considered empty + } + + if (typeof value === 'number') { + return isNaN(value); + } + + return false; // All other types (strings, objects, arrays, etc) are not considered empty + } + + /** + * Checks if a value is a date object + * @param value A date object + * @returns boolean + */ + isDate(value: any): boolean { + return value instanceof Date; + } + + /** + * Generates an array of integers between specified range + * @param start The starting number. + * @param end The ending number. + */ + range(start: number, end: number): Array { + if (end < start) { + throw new Error("ParamError: end must be greater than start") + } + + if (start === end) { + return [start] + } + + const arr = []; + for (let i = start; i <= end; i++) { + arr.push(i); + } + return arr; + } + + /** + * Checks if object has the specified key + * @param obj The object to check. + * @param key The key to find. + */ + keyInObject(obj: object, key: number | string): boolean { + return Object.prototype.hasOwnProperty.call(obj, key) + } + + /** + * Transposes an array of array + * @param obj The object to check. + * @param key The key to find. + */ + transposeArray(arr: ArrayType1D | ArrayType2D): ArrayType1D | ArrayType2D { //old name: __get_col_values + if (arr.length === 0) return arr + + const rowLen: number = arr.length; + if (Array.isArray(arr[0])) { + const colLen: number = arr[0].length; + const newArr = []; + + for (let i = 0; i <= colLen - 1; i++) { + const temp = []; + for (let j = 0; j < rowLen; j++) { + const _elem = (arr as any)[j][i] + temp.push(_elem); + } + newArr.push(temp); + } + return newArr; + } else { + return arr; + } + } + + /** + * Retrieve row array and column names from an object of the form {a: [1,2,3,4], b: [30,20, 30, 20]} + * @param obj The object to retrieve rows and column names from. + */ + getRowAndColValues(obj: object): [ArrayType1D | ArrayType2D, string[]] { + const colNames = Object.keys(obj); + const colData = Object.values(obj); + const firstColLen = colData[0].length; + + colData.forEach((cdata) => { + if (cdata.length != firstColLen) { + throw Error("Length Error: Length of columns must be the same!"); + } + }); + + const rowsArr = this.transposeArray(colData) + return [rowsArr, colNames]; + } + + /** + * Converts a 2D array of array to 1D array for Series Class + * @param arr The array to convert. + */ + convert2DArrayToSeriesArray(arr: ArrayType2D): Array { + const newArr = arr.map((val) => { + if (this.isObject(val)) { + return JSON.stringify(val) + } else { + return `${val}` + } + }); + return newArr; + } + + /** + * Replaces all missing values with NaN. Missing values are undefined, Null and Infinity + * @param arr The array + * @param isSeries Whether the arr is a series or not + */ + replaceUndefinedWithNaN(arr: ArrayType1D | ArrayType2D, isSeries: boolean): ArrayType1D | ArrayType2D { + if (arr.length === 0) return arr; + + if (isSeries && Array.isArray(arr)) { + const newArr = arr.map((ele) => { + if (typeof ele === "undefined") { + return NaN; + } + if (typeof ele === "number" && (isNaN(ele) || ele == Infinity)) { + return NaN; + } + if (ele == null) { + return NaN; + } + return ele + }); + return newArr as ArrayType1D + } else { + const newArr = [] + if (Array.isArray(arr)) { + for (let i = 0; i < arr.length; i++) { + const innerArr = arr[i] + const temp = (innerArr as unknown as ArrayType2D).map((ele: any) => { + if (typeof ele === "undefined") { + return NaN; + } + if (typeof ele === "number" && (isNaN(ele) || ele == Infinity)) { + return NaN; + } + if (ele == null) { + return NaN; + } + return ele + }); + newArr.push(temp); + } + } + return newArr; + } + } + + /** + * Infer data type from an array or array of arrays + * @param arr An array or array of arrays + */ + inferDtype(arr: ArrayType1D | ArrayType2D) { + const self = this; + if (this.is1DArray(arr)) { + return [this.$typeChecker(arr)]; + } else { + const arrSlice = this.transposeArray(arr.slice(0, config.getDtypeTestLim)) + const dtypes = arrSlice.map((innerArr) => { + return self.$typeChecker(innerArr as any); + }); + return dtypes; + } + } + + /** + * Private type checker used by inferDtype function + * @param arr The array + */ + private $typeChecker(arr: ArrayType1D | ArrayType2D) { + let dtypes: string; + let lim: number; + let intTracker: Array = []; + let floatTracker: Array = []; + let stringTracker: Array = []; + let boolTracker: Array = []; + let dateTracker: Array = []; + + if (arr.length < config.getDtypeTestLim) { + lim = arr.length; + } else { + lim = config.getDtypeTestLim; + } + + const arrSlice = arr.slice(0, lim); + + for (let i = 0; i < lim; i++) { + const ele = arrSlice[i]; + if (typeof ele == "boolean") { + floatTracker.push(false); + intTracker.push(false); + stringTracker.push(false); + boolTracker.push(true); + dateTracker.push(false); + } else if (this.isEmpty(ele)) { + floatTracker.push(true); + intTracker.push(false); + stringTracker.push(false); + boolTracker.push(false); + dateTracker.push(false); + } else if (this.isDate(ele)) { + floatTracker.push(false); + intTracker.push(false); + stringTracker.push(false); + boolTracker.push(false); + dateTracker.push(true); + } else if (!isNaN(Number(ele))) { + if ((ele as unknown as string).toString().includes(".")) { + floatTracker.push(true); + intTracker.push(false); + stringTracker.push(false); + boolTracker.push(false); + dateTracker.push(false); + } else { + floatTracker.push(false); + intTracker.push(true); + stringTracker.push(false); + boolTracker.push(false); + dateTracker.push(false); + } + } else { + floatTracker.push(false); + intTracker.push(false); + stringTracker.push(true); + boolTracker.push(false); + dateTracker.push(false); + } + } + + const even = (ele: number | string | boolean) => ele == true; + + if (stringTracker.some(even)) { + dtypes = "string"; + } else if (floatTracker.some(even)) { + dtypes = "float32"; + } else if (intTracker.some(even)) { + dtypes = "int32"; + } else if (boolTracker.some(even)) { + dtypes = "boolean"; + } else if (dateTracker.some(even)) { + dtypes = "datetime"; + } else { + dtypes = "undefined"; + } + + return dtypes; + } + + /** + * Returns the unique values in an 1D array + * @param arr The array + */ + unique(arr: ArrayType1D): ArrayType1D { + const uniqueArr = new Set(arr); + return Array.from(uniqueArr); + } + + /** + * Checks if array is 1D + * @param arr The array + */ + is1DArray(arr: ArrayType1D | ArrayType2D): boolean { + if ( + typeof arr[0] == "number" || + typeof arr[0] == "string" || + typeof arr[0] == "boolean" || + arr[0] === null + ) { + return true; + } else { + return false; + } + } + + /** + * Converts an array to an object using array index as object keys + * @param arr The array + */ + convertArrayToObject(arr: ArrayType1D | ArrayType2D) { + const arrObj: any = {}; + for (let i = 0; i < arr.length; i++) { + arrObj[i] = arr[i]; + + } + return arrObj; + } + + /** + * Count the NaN and non-NaN values present in an array + * @param arr Array object + * @param val whether to return the value count instead of the null count + * @param isSeries Whether the array is of type series or not + */ + countNaNs(arr: ArrayType1D | ArrayType2D, returnVal: boolean = true, isSeries: boolean): number | Array { + if (isSeries) { + let nullCount = 0; + let valCount = 0; + for (let i = 0; i < arr.length; i++) { + const ele = arr[i]; + if (Number.isNaN(ele)) { + nullCount = nullCount + 1; + } else { + valCount = valCount + 1; + } + + } + if (returnVal) { + return valCount; + } else { + return nullCount; + } + } else { + const resultArr = []; + for (let i = 0; i < arr.length; i++) { + const innerArr = arr[i]; + let nullCount = 0; + let valCount = 0; + for (let i = 0; i < (innerArr as unknown as ArrayType2D).length; i++) { + const ele = (innerArr as unknown as ArrayType2D)[i]; + if (Number.isNaN(ele)) { + nullCount = nullCount + 1; + } else { + valCount = valCount + 1; + } + } + + if (returnVal) { + resultArr.push(valCount); + } else { + resultArr.push(nullCount); + } + } + return resultArr; + } + } + + /** + * Round elements of an array or array of arrays to specified dp + * @param arr The Array to round + * @param dp The number of dp to round to + * @param isSeries Whether the array is of type Series or not + */ + round(arr: Array, dp: number = 1, isSeries: boolean): ArrayType1D | ArrayType2D { + if (dp < 0) { + dp = 1; + } + + if (isSeries) { + const newArr = []; + for (let i = 0; i < arr.length; i++) { + const ele = arr[i]; + if (typeof ele == "number" && !isNaN(ele) && ele !== undefined && ele !== null) { + newArr.push(Number((ele).toFixed(dp))); + } else { + newArr.push(ele) + } + } + return newArr as ArrayType1D + } else { + const resultArr = []; + for (let i = 0; i < arr.length; i++) { + const innerVal = arr[i]; + const newArr: Array = []; + if (Array.isArray(innerVal)) { + for (let i = 0; i < innerVal.length; i++) { + const ele = innerVal[i]; + if (typeof ele == "number" && !isNaN(ele) && ele !== undefined && ele !== null) { + newArr.push(Number((ele).toFixed(dp))); + } else { + newArr.push(ele) + } + } + resultArr.push(newArr); + } else { + if (typeof innerVal == "number" && !isNaN(innerVal) && innerVal !== undefined && innerVal !== null) { + newArr.push(Number((innerVal).toFixed(dp))); + } else { + newArr.push(innerVal) + } + } + + } + return resultArr; + } + } + + /** + * Checks if a func is a function + * @param func + */ + isFunction(func: object): boolean { + return typeof func == "function"; + } + + /** + * Generates n random numbers between start and end. + * @param start + * @param end + * @param size + */ + randNumberGenerator(start: number, end: number, size: number) { + let genNum: Array = []; + + function randi(a: number, b: number) { + return Math.floor(Math.random() * (b - a) + a); + } + + function recursive(val: number, arr: Array): any { + if (!arr.includes(val)) { + return val; + } + val = randi(start, end); + recursive(val, arr); + } + + for (let i = 0; i < size; i++) { + let genVal = randi(start, end); + let recursiveVal = recursive(genVal, genNum); + genNum.push(recursiveVal); + } + return genNum; + } + + /** + * Throws error when a required parameter is missing. + * @param paramsObject The parameters passed to the function + * @param paramsNeeded The required parameters in the function + */ + throwErrorOnWrongParams(paramsObject: object, paramsNeeded: Array) { + const keys = Object.keys(paramsObject); + const bool = []; + for (let i = 0; i < keys.length; i++) { + if (paramsNeeded.includes(keys[i])) { + bool.push(true); + } else { + bool.push(false); + } + } + const truthy = (element: boolean) => element == false; + if (bool.some(truthy)) { + throw Error( + `Params Error: Required parameter not found. Your params must include the following [${paramsNeeded}]` + ); + } + } + + /** + * Maps integer values (0, 1) to boolean (false, true) + * @param arr The array of integers + * @param dim The dimension of the array + */ + mapIntegersToBooleans(arr: Array, dim: number): Array { + if (dim == 2) { + const newArr: Array = []; + arr.map((innerArr) => { + const temp: Array = []; + (innerArr as Array).map((val) => temp.push(val == 1)); + newArr.push(temp); + }); + return newArr; + } else { + const newArr: Array = []; + arr.map((val) => newArr.push(val == 1)); + return newArr; + } + } + + /** + * Maps boolean values (false, true) to integer equivalent (0, 1) + * @param arr The array of booleans + * @param dim The dimension of the array + */ + mapBooleansToIntegers(arr: Array, dim: number): Array { + if (dim == 2) { + const newArr: Array = []; + arr.map((innerArr) => { + const temp: Array = []; + (innerArr as Array).map((val) => temp.push(val ? 1 : 0)); + newArr.push(temp); + }); + return newArr; + } else { + const newArr: Array = []; + arr.map((val) => newArr.push(val ? 1 : 0)); + return newArr; + } + } + + /** + * Generates an array of dim (row x column) with inner values set to zero + * @param row + * @param column + */ + zeros(row: number, column: number): ArrayType1D | ArrayType2D { + const zeroData = []; + for (let i = 0; i < row; i++) { + const colData = Array(column); + for (let j = 0; j < column; j++) { + colData[j] = 0; + } + zeroData.push(colData); + } + return zeroData; + } + + /** + * Shuffles and returns a random slice of an array + * @param num + * @param array + */ + shuffle(array: ArrayType1D | ArrayType2D, num: number): ArrayType1D | ArrayType2D { + let i = array.length; + let j = 0; + let temp; + + while (i--) { + j = Math.floor(Math.random() * (i + 1)); + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + + return array.slice(0, num); + } + + /** + * Sorts an array in specified order + * @param arr + * @param ascending + * @returns + */ + sort(arr: Array, ascending: boolean = true): Array { + const sorted = [...arr] + return sorted.sort((a, b) => { + if (ascending) { + if (typeof a === "string" && typeof b === "string") { + return a.charCodeAt(0) - b.charCodeAt(0); + } else { + return (a as unknown as number) - (b as unknown as number) + } + } else { + if (typeof a === "string" && typeof b === "string") { + return b.charCodeAt(0) - a.charCodeAt(0); + } else { + return (b as unknown as number) - (a as unknown as number) + } + } + }); + } + + /** + * Checks if current environment is Browser + */ + isBrowserEnv() { + const isBrowser = new Function( + "try {return this===window;}catch(e){ return false;}" + ); + return isBrowser(); + } + + /** + * Checks if current environment is Node + */ + isNodeEnv() { + const isNode = new Function( + "try {return this===global;}catch(e){return false;}" + ); + return isNode(); + } + + /** + * Remove NaN values from 1D array + * @param arr + */ + removeMissingValuesFromArray(arr: Array | ArrayType1D) { + const values = arr.filter((val) => { + return !(this.isEmpty(val)) + }) + return values; + } + + + /** + * Replace NaN with null before tensor operations + * @param arr + */ + replaceNanWithNull(arr: ArrayType1D | ArrayType2D) { + const values = arr.map((val) => { + if (isNaN(val as unknown as number)) { + return null; + } else { + return val; + } + }); + return values; + } + + /** + * Get duplicate values in a array + * @param arr + */ + getDuplicate(arr: Array) { + const tempObj: any = {}; + const resultObj: any = {}; + + for (let i = 0; i < arr.length; i++) { + const val = arr[i]; + if (this.keyInObject(tempObj, val as unknown as string | number)) { + tempObj[val]["count"] += 1; + tempObj[val]["index"].push(i); + } else { + tempObj[val] = {}; + tempObj[val]["count"] = 1; + tempObj[val]["index"] = [i]; + } + } + + for (let key in tempObj) { + if (tempObj[key]["count"] >= 2) { + resultObj[key] = {}; + resultObj[key]["count"] = tempObj[key]["count"]; + resultObj[key]["index"] = tempObj[key]["index"]; + } + } + + return resultObj; + } + + /** + * Returns the index of a sorted array + * @param arr1 The first array + * @param arr2 The second array + * @param dtype The data type of the arrays + * + * @returns sorted index + */ + sortArrayByIndex(arr1: ArrayType1D | ArrayType2D, arr2: ArrayType1D | ArrayType2D, dtype: string) { + const sortedIdx = arr1.map((item, index) => { + return [arr2[index], item]; + }); + if (dtype == "string") { + sortedIdx.sort(); + } else { + sortedIdx.sort(([arg1], [arg2]) => (arg2 as unknown as number) - (arg1 as unknown as number)); + } + + return sortedIdx.map(([, item]) => item) as number[] + } + + /** + * Returns a new series with properties of the old series + * + * @param series The series to copy + */ + createNdframeFromNewDataWithOldProps({ ndFrame, newData, isSeries }: { ndFrame: Series, newData: any, isSeries: boolean }) { + if (isSeries) { + return new Series( + newData, + { + index: [...ndFrame.index], + columns: [...ndFrame.columns], + dtypes: [...ndFrame.dtypes], + config: { ...ndFrame.config } + }) + } else { + return new DataFrame(newData, + { + index: [...ndFrame.index], + columns: [...ndFrame.columns], + dtypes: [...ndFrame.dtypes], + config: { ...ndFrame.config } + }) + } + } + + /** + * Checks if two series are compatible for a mathematical operation + * @param object + * + * firstSeries ==> First Series object + * + * secondSeries ==> Second Series object to comapre with + * + * operation ==> The mathematical operation + */ + checkSeriesOpCompactibility({ firstSeries, secondSeries, operation }: { + firstSeries: Series, secondSeries: Series, operation: string + }): void { + + if (firstSeries.shape[0] != secondSeries.shape[0]) { + ErrorThrower.throwSeriesMathOpLengthError(firstSeries, secondSeries) + } + if (firstSeries.dtypes[0] == 'string' || secondSeries.dtypes[0] == 'string') { + ErrorThrower.throwStringDtypeOperationError(operation) + } + } + + /** + * Custom sort for an array of index and values + * @param arr The array of objects to sort + * @param ascending Whether to sort in ascending order or not + */ + sortObj( + arr: Array<{ index: number | string, value: number | string | boolean }>, + ascending: boolean + ) { + let sortedValues = arr.sort((obj1, obj2) => { + let a = obj2.value; + let b = obj1.value; + + if (!ascending) { + if (typeof a === "string" && typeof b === "string") { + a = a.toUpperCase(); + b = b.toUpperCase(); + + if (a < b) { + return -1; + } + + if (a > b) { + return 1; + } + + return 0; + + } else { + return Number(a) - Number(b); + } + } else { + if (typeof a === "string" && typeof b === "string") { + a = a.toUpperCase(); + b = b.toUpperCase(); + + if (a > b) { + return -1; + } + + if (a < b) { + return 1; + } + + return 0; + } else { + return Number(b) - Number(a);; + } + } + }); + + return sortedValues; + } +} diff --git a/src/danfojs-base/transformers/concat.ts b/src/danfojs-base/transformers/concat.ts new file mode 100644 index 00000000..4a3c66e2 --- /dev/null +++ b/src/danfojs-base/transformers/concat.ts @@ -0,0 +1,147 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import Series from "../core/series" +import DataFrame from "../core/frame" +import { ArrayType1D, ArrayType2D } from "../shared/types" + +/** + * + * @param dfList Array + * @param axis number + * @returns DataFrame + */ +function processColumn(dfList: Array, axis: number ): DataFrame { + let allDf: any = {} + let dublicateColumns: any = {} + let maxLen = 0 + for(let i=0; i < dfList.length; i++) { + let df = dfList[i] + let columnData: ArrayType2D; + if ( df instanceof DataFrame) { + columnData = df.getColumnData as ArrayType2D + } else { + columnData = [df.values] as ArrayType2D + } + let columns = df.columns + for(let j=0; j < columns.length; j++) { + let column = columns[j] + let colData: ArrayType1D = columnData[j] + if (colData.length > maxLen) { + maxLen = colData.length + } + if (!(column in allDf)) { + allDf[column] = colData + dublicateColumns[column] = 0 + } else { + dublicateColumns[column] +=1 + column += dublicateColumns[column] + allDf[column] = colData + } + } + } + Object.keys(allDf).forEach(value => { + let colLength = allDf[value].length + if (colLength < maxLen) { + let residualLen = maxLen - colLength + let nanList = new Array(residualLen).fill(NaN) + allDf[value].push(...nanList) + } + }) + + return new DataFrame(allDf) +} + +/** + * Concat data along rows + * @param dfList Array + * @param axis Array + * @returns DataFrame + */ +function processRow(dfList: Array, axis: number ): DataFrame | Series { + let allDf: any = {} + let maxLen = 0 + for (let i=0; i < dfList.length; i++) { + let df = dfList[i] + let columns = df.columns + let columnData: ArrayType2D; + if ( df instanceof DataFrame) { + columnData = df.getColumnData as ArrayType2D + } else { + columnData = [df.values] as ArrayType2D + } + + + if (i ===0) { + for(let j=0; j < columns.length; j++) { + let column = columns[j] + let colData = columnData[j] + allDf[column] = colData + } + } else { + let nonColumn = Object.keys(allDf).filter( (key:any) =>{ + return !columns.includes(key) + }) + + for(let j=0; j < columns.length; j++) { + let column = columns[j] + let colData = columnData[j] + if (Object.keys(allDf).includes(column)) { + allDf[column].push(...colData) + } + else { + let residualArray = new Array(maxLen).fill(NaN) + residualArray.push(...colData) + allDf[column] = residualArray + } + } + if (nonColumn.length > 0) { + let currentDfLen = columnData[0].length + for( let j=0; j < nonColumn.length; j++) { + let column = nonColumn[j] + let residualArray = new Array(currentDfLen).fill(NaN) + allDf[column].push(...residualArray) + } + } + } + maxLen += columnData[0].length + } + + if (Object.keys(allDf).length === 1) { + return new Series(Object.values(allDf)[0]) + } + return new DataFrame(allDf) +} + +/** +* Concatenate pandas objects along a particular axis. +* @param object +* dfList: Array of DataFrame or Series +* axis: axis of concatenation 1 or 0 +* @returns {DataFrame} +* @example +* concat({dfList: [df1, df2, df3], axis: 1}) +*/ +function concat({dfList, axis}: { + dfList : Array, + axis: 1 | 0 +}): DataFrame | Series { + if (axis === 1) { + return processColumn(dfList, axis) + } + return processRow(dfList, 0) +} + +export default concat \ No newline at end of file diff --git a/src/danfojs-base/transformers/encoders/dummy.encoder.ts b/src/danfojs-base/transformers/encoders/dummy.encoder.ts new file mode 100644 index 00000000..64c13992 --- /dev/null +++ b/src/danfojs-base/transformers/encoders/dummy.encoder.ts @@ -0,0 +1,160 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import DataFrame from "../../core/frame" +import Series from "../../core/series" +import Utils from "../../shared/utils" +import { ArrayType1D, ArrayType2D } from "../../shared/types" + +const utils = new Utils() + +/** + * Generate one-hot encoding for categorical columns in an Array, Series or Dataframe. + * @param data Series or Dataframe + * @param columns Columns to encode + * @param prefix Prefix for the new columns + * @param prefixSeparator Separator for the prefix and the column name + * @returns Encoded Dataframe + * @example + * import { DataFrame, DummyEncoder }from 'danfojs'; + * const df = new DataFrame([[1,2,3], [4,5,6]], { columns: ['a', 'b', 'c'] }); + * const df2 = new DummyEncoder({data: df, columns: ['a', 'b'], prefix: 'enc', prefixSeparator: '#'}).encode(); + * df2.print(); + */ +function dummyEncode( + data: Series | DataFrame, + options?: { + columns?: string | Array, + prefix?: string | Array, + prefixSeparator?: string | Array + }) { + let { columns, prefix, prefixSeparator } = { columns: null, prefix: null, prefixSeparator: "_", ...options } + + if (!data) { + throw new Error('ParamError: data must be one of Array, Series or DataFrame') + } + + if (data instanceof Series || data instanceof DataFrame) { + if (!columns) { + const colsWithStringDtype: Array = [] + data.dtypes.forEach((dtype, index) => { + if (dtype === "string") { + colsWithStringDtype.push(data.columns[index]) + } + }) + columns = colsWithStringDtype as string[] + } + } else { + throw new Error('ParamError: data must be one of Array, Series or DataFrame') + } + + + if (typeof columns === "string") { + columns = [columns] + if (Array.isArray(prefix) && prefix.length === 1) { + prefix = prefix + } else if (typeof prefix === "string") { + prefix = [prefix] + } else { + throw new Error('ParamError: prefix must be a string, or an array of same length as columns') + } + + if (Array.isArray(prefixSeparator) && prefixSeparator.length === 1) { + prefixSeparator = prefixSeparator + } else if (typeof prefixSeparator === "string") { + prefixSeparator = [prefixSeparator] + } else { + throw new Error('ParamError: prefix must be a string, or an array of same length as columns') + } + } else if (Array.isArray(columns)) { + if (prefix) { + if (Array.isArray(prefix) && prefix.length !== columns.length) { + throw new Error(`ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "${prefix}"}`) + } + + if (typeof prefix === "string") { + prefix = columns.map(_ => prefix as string) + } + } + + if (prefixSeparator) { + if (Array.isArray(prefixSeparator) && prefixSeparator.length !== columns.length) { + throw new Error(`ParamError: prefixSeparator and data array must be of the same length. If you need to use the same prefix separator, then pass a string param instead. e.g {prefixSeparator: "${prefixSeparator}"}`) + } + + if (typeof prefixSeparator === "string") { + prefixSeparator = columns.map(_ => prefixSeparator as string) + } + } + + } else { + throw new Error('ParamError: columns must be a string or an array of strings') + } + + if (data instanceof Series) { + const colData = data.values as ArrayType1D + const newColumnNames = [] + const uniqueValues = Array.from(new Set(colData)) + const oneHotArr: any = utils.zeros(colData.length, uniqueValues.length) + + for (let i = 0; i < colData.length; i++) { + const index = uniqueValues.indexOf(colData[i]) + oneHotArr[i][index] = 1 + } + + for (let i = 0; i < uniqueValues.length; i++) { + const prefixToAdd = prefix ? prefix[0] : i + newColumnNames.push(`${prefixToAdd}${prefixSeparator[0]}${uniqueValues[i]}`) + + } + + return new DataFrame(oneHotArr, { columns: newColumnNames }) + + } else { + + const dfWithSelectedColumnsDropped = data.drop({ columns }) + let newData = dfWithSelectedColumnsDropped?.values as ArrayType2D + const newColumnNames = dfWithSelectedColumnsDropped?.columns as Array + + for (let i = 0; i < columns.length; i++) { + const column = columns[i] + const colData = data.column(column).values as Array + + const uniqueValues = Array.from(new Set(colData)) + const oneHotArr: any = utils.zeros(colData.length, uniqueValues.length) + + for (let j = 0; j < colData.length; j++) { + const index = uniqueValues.indexOf(colData[j]) + oneHotArr[j][index] = 1 + const prefixToAdd = prefix ? prefix[i] : column + const newColName = `${prefixToAdd}${prefixSeparator[i]}${colData[j]}`; + + if (!newColumnNames.includes(newColName)) { + newColumnNames.push(newColName); + } + } + + for (let k = 0; k < newData.length; k++) { + newData[k] = [...newData[k], ...oneHotArr[k]] + + } + + } + + return new DataFrame(newData, { columns: newColumnNames }) + } + +} + +export default dummyEncode diff --git a/src/danfojs-base/transformers/encoders/label.encoder.ts b/src/danfojs-base/transformers/encoders/label.encoder.ts new file mode 100644 index 00000000..3e00121e --- /dev/null +++ b/src/danfojs-base/transformers/encoders/label.encoder.ts @@ -0,0 +1,176 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import tensorflow from '../../shared/tensorflowlib' +import Series from "../../core/series" +import Utils from "../../shared/utils" + +const utils = new Utils() + +/** + * Encode target labels with value between 0 and n_classes-1. + */ +export default class LabelEncoder { + private $labels: { [key: string]: number } + + constructor() { + this.$labels = {} + } + + private $getData(data: Array | typeof tensorflow.Tensor | Series) { + let $data: Array + + if (data instanceof Array) { + if (utils.is1DArray(data)) { + $data = data + } else { + throw new Error("ValueError: data must be a 1D array.") + } + } else if (data instanceof Series) { + $data = data.values as Array + } else if (data instanceof tensorflow.Tensor) { + $data = data.arraySync() as Array + } else { + throw new Error("ParamError: data must be one of Array, 1d Tensor or Series.") + } + return $data + } + + /** + * Maps values to unique integer labels between 0 and n_classes-1. + * @param data 1d array of labels, Tensor, or Series to fit. + * @example + * ``` + * const encoder = new LabelEncoder() + * encoder.fit(["a", "b", "c", "d"]) + * ``` + */ + fit(data: Array | typeof tensorflow.Tensor | Series) { + const $data = this.$getData(data) + const dataSet = Array.from(new Set($data)) + const tempObj: { [key: string | number]: number } = {} + dataSet.forEach((value, index) => { + tempObj[value] = index + }) + this.$labels = tempObj + return this + } + + /** + * Encode labels with value between 0 and n_classes-1. + * @param data 1d array of labels, Tensor, or Series to be encoded. + * @example + * ``` + * const encoder = new LabelEncoder() + * encoder.fit(["a", "b", "c", "d"]) + * console.log(encoder.transform(["a", "b", "c", "d"])) + * // [0, 1, 2, 3] + * ``` + */ + transform(data: Array | typeof tensorflow.Tensor | Series) { + const $data = this.$getData(data) + const encodedData: Array = $data.map(value => { + const label = this.$labels[value] !== undefined ? this.$labels[value] : -1 + return label + }) + + if (data instanceof Array) { + return encodedData + } else if (data instanceof Series) { + return new Series(encodedData) + } else { + return tensorflow.tensor1d(encodedData) + } + } + + /** + * Fit and transform data in one step. + * @param data 1d array of labels, Tensor, or Series to be encoded. + * @example + * ``` + * const encoder = new LabelEncoder() + * encoder.fitTransform(["a", "b", "c", "d"]) + * // [0, 1, 2, 3] + * ``` + */ + fitTransform(data: Array | typeof tensorflow.Tensor | Series) { + this.fit(data) + return this.transform(data) + } + + /** + * Inverse transform values back to original values. + * @param data 1d array of labels, Tensor, or Series to be decoded. + * @example + * ``` + * const encoder = new LabelEncoder() + * encoder.fit(["a", "b", "c", "d"]) + * console.log(encoder.inverseTransform([0, 1, 2, 3])) + * // ["a", "b", "c", "d"] + * ``` + */ + inverseTransform(data: Array | typeof tensorflow.Tensor | Series) { + const $data = this.$getData(data) + const tempData = $data.map(value => { + return Object.keys(this.$labels).find(key => this.$labels[key] === value) + }) + + const decodedData = tempData.map(value => { + if (isNaN(parseInt(value as any))) { + return value + } else { + return Number(value) + } + }) + + if (data instanceof Array) { + return decodedData + } else if (data instanceof Series) { + return new Series(decodedData) + } else { + return tensorflow.tensor1d(decodedData as any) + } + } + + /** + * Get the number of classes. + * @returns number of classes. + * @example + * ``` + * const encoder = new LabelEncoder() + * encoder.fit(["a", "b", "c", "d"]) + * console.log(encoder.nClasses) + * // 4 + * ``` + */ + get nClasses(): number { + return Object.keys(this.$labels).length + } + + /** + * Get the mapping of classes to integers. + * @returns mapping of classes to integers. + * @example + * ``` + * const encoder = new LabelEncoder() + * encoder.fit(["a", "b", "c", "d"]) + * console.log(encoder.classes) + * // {a: 0, b: 1, c: 2, d: 3} + * ``` + */ + get classes(): { [key: string]: number } { + return this.$labels + } +} \ No newline at end of file diff --git a/src/danfojs-base/transformers/encoders/one.hot.encoder.ts b/src/danfojs-base/transformers/encoders/one.hot.encoder.ts new file mode 100644 index 00000000..69b613a3 --- /dev/null +++ b/src/danfojs-base/transformers/encoders/one.hot.encoder.ts @@ -0,0 +1,117 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import DataFrame from "../../core/frame"; +import tensorflow from '../../shared/tensorflowlib' +import Series from "../../core/series" +import Utils from "../../shared/utils" + +const utils = new Utils() + +/** + * Fits a OneHotEncoder to the data. + * @example + * ```js + * const encoder = new OneHotEncoder() + * encoder.fit(["a", "b", "c"]) + * ``` +*/ +export default class OneHotEncoder { + private $labels: Array + + constructor() { + this.$labels = [] + } + + private $getData(data: Array | typeof tensorflow.Tensor | Series) { + let $data: Array + + if (data instanceof Array) { + if (utils.is1DArray(data)) { + $data = data + } else { + throw new Error("ValueError: data must be a 1D array.") + } + } else if (data instanceof Series) { + $data = data.values as Array + } else if (data instanceof tensorflow.Tensor) { + $data = data.arraySync() as Array + } else { + throw new Error("ParamError: data must be one of Array, 1d Tensor or Series.") + } + return $data + } + + /** + * Fits a OneHotEncoder to the data. + * @param data 1d array of labels, Tensor, or Series to be encoded. + * @returns OneHotEncoder + * @example + * ```js + * const encoder = new OneHotEncoder() + * encoder.fit(["a", "b", "c"]) + * ``` + */ + public fit(data: Array | typeof tensorflow.Tensor | Series) { + const $data = this.$getData(data) + const dataSet = Array.from(new Set($data)) + this.$labels = dataSet + return this + } + + /** + * Encodes the data using the fitted OneHotEncoder. + * @param data 1d array of labels, Tensor, or Series to be encoded. + * @example + * ```js + * const encoder = new OneHotEncoder() + * encoder.fit(["a", "b", "c"]) + * encoder.transform(["a", "b", "c"]) + * ``` + */ + public transform(data: Array | typeof tensorflow.Tensor | Series): DataFrame | typeof tensorflow.Tensor | number[][] { + const $data = this.$getData(data) + const oneHotArr: any = utils.zeros($data.length, this.$labels.length) + + for (let i = 0; i < $data.length; i++) { + const index = this.$labels.indexOf($data[i]) + oneHotArr[i][index] = 1 + } + + if (data instanceof Array) { + return oneHotArr + } else if (data instanceof Series) { + return new DataFrame(oneHotArr, { + index: data.index, + }) + } else { + return tensorflow.tensor1d(oneHotArr) + } + } + + /** + * Fit and transform the data using the fitted OneHotEncoder. + * @param data 1d array of labels, Tensor, or Series to be encoded. + * @example + * ```js + * const encoder = new OneHotEncoder() + * encoder.fitTransform(["a", "b", "c"]) + * ``` + */ + public fitTransform(data: Array | typeof tensorflow.Tensor | Series): DataFrame | typeof tensorflow.Tensor | number[][] { + this.fit(data) + return this.transform(data) + } +} \ No newline at end of file diff --git a/src/danfojs-base/transformers/merge.ts b/src/danfojs-base/transformers/merge.ts new file mode 100644 index 00000000..f449557b --- /dev/null +++ b/src/danfojs-base/transformers/merge.ts @@ -0,0 +1,387 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import DataFrame from "../core/frame" +import { ArrayType1D, ArrayType2D } from "../shared/types" +import Utils from "../shared/utils"; +const utils = new Utils(); + +type mergeParam = { + left: DataFrame, + right: DataFrame, + on: Array, + how: "outer" | "inner" | "left" | "right" +} + +type keyComb = { + [key: string] : { + filters: ArrayType2D, + combValues: ArrayType1D + } +} + +class Merge { + left: DataFrame + right: DataFrame + on: Array + how: "outer" | "inner" | "left" | "right" + leftColIndex: ArrayType1D = [] + rightColIndex: ArrayType1D = [] + leftCol?: ArrayType1D + rightCol?: ArrayType1D + columns?: ArrayType1D + + constructor({left, right, on, how}: mergeParam) { + this.left = left + this.right = right + this.on = on + this.how = how + + //Obtain the column index of the column will + //want to merge on for both left and right dataframe + for(let i =0; i < this.on.length; i++) { + let key = this.on[i] + if (this.left.columns.includes(key) && this.right.columns.includes(key)) { + let leftIndex = this.left.columns.indexOf(key) + let rightIndex = this.right.columns.indexOf(key) + this.leftColIndex.push(leftIndex) + this.rightColIndex.push(rightIndex) + } + } + } + + /** + * Generate key combination base on the columns we want to merge on + * e.g df = { + * key1: ["KO", "K0", "K3", "K4"], + * Key2: ["K1", "K1", "K3", "K5"], + * A: [1,2,3,4] + * B: [3,4,5,6] + * } + * keycomb = generateKeyCombination(df.values, [0,1]) + * This should output + * { + * 'k0_k1': { + * filters: [[1,3], [2,4]], # the value of other columns in thesame row with the combination keys + * combValues: ["KO", "k1"] # the combination key from column Key1 (index 2) and key2 (index 1) + * }, + * 'K3_K3 : { + * filters: [[3,5]], + * combValues: ['K3', 'k3'] + * }, + * 'k4_k5' : { + * filters: [[4,6]] + * combValues: ['K4', 'K5'] + * } + * } + * This key combination will be generated for both left and right dataframe + * @param values + * @param colIndex + */ + private generateKeyCombination(values: ArrayType2D, colIndex: ArrayType1D): keyComb { + let colKeyComb: keyComb = {} + + for (let i=0; i < values.length; i++) { + let rowValues = values[i] + let rowKeyCombValues = []; + for (let j =0; j < colIndex.length; j++) { + let index = colIndex[j] as number + rowKeyCombValues.push(rowValues[index]) + } + let rowKeyComb = rowKeyCombValues.join('_') + let otherValues = rowValues.filter((val, index) => { + return !colIndex.includes(index) + }) + if (utils.keyInObject(colKeyComb, rowKeyComb)) { + colKeyComb[rowKeyComb].filters.push(otherValues) + } else { + colKeyComb[rowKeyComb] = { + filters: [otherValues], + combValues: rowKeyCombValues + } + } + } + return colKeyComb + } + + /** + * Generate columns for the newly generated merged DataFrame + * e.g df = { + * key1: ["KO", "K0", "K3", "K4"], + * Key2: ["K1", "K1", "K3", "K5"], + * A: [1,2,3,4] + * B: [3,4,5,6] + * } + * df2 = { + * key1: ["KO", "K0", "K3", "K4"], + * Key2: ["K1", "K1", "K3", "K5"], + * A: [1,2,3,4] + * c: [3,4,5,6] + * } + * And both dataframe are to be merged on `key1` and `key2` + * the newly generated column will be of the form + * columns = ['key1', 'Key2', 'A', 'A_1', 'B', 'C'] + * Notice 'A_1' , this because both DataFrame as column A and 1 is the + * number of duplicate of that column + */ + private createColumns() { + const self = this + this.leftCol = self.left.columns.filter((_, index)=>{ + return !self.leftColIndex.includes(index) + }) + this.rightCol = self.right.columns.filter((_, index) => { + return !self.rightColIndex.includes(index) + }) + this.columns = [...this.on] + const duplicateColumn: { + [key: string] : number + } = {} + const tempColumn = [...this.leftCol] + tempColumn.push(...this.rightCol) + for (let i=0; i< tempColumn.length; i++) { + const col = tempColumn[i] as string + if (utils.keyInObject(duplicateColumn, col)) { + let columnName = `${col}_${duplicateColumn[col]}` + this.columns.push(columnName) + duplicateColumn[col] +=1 + } else { + this.columns.push(col) + duplicateColumn[col] = 1 + } + } + } + + /** + * The basic methos perform the underneath operation of generating + * the merge dataframe; using the combination keys generated from + * bothe left and right DataFrame + * e.g df = { + * key1: ["KO", "K0", "K3", "K4"], + * Key2: ["K1", "K1", "K3", "K5"], + * A: [1,2,3,4] + * B: [3,4,5,6] + * } + * df2 = { + * key1: ["KO", "K0", "K3", "K4"], + * Key2: ["K1", "K2", "K4", "K5"], + * A: [3,6,8,9] + * c: [2,4,6,8] + * } + * Running generatekeyCombination on both left and right data frame + * we should have + * leftKeyDict = { + * 'k0_k1': { + * filters: [[1,3], [2,4]], + * combValues: ["KO", "k1"] + * }, + * 'K3_K3' : { + * filters: [[3,5]], + * combValues: ['K3', 'k3'] + * }, + * 'k4_k5' : { + * filters: [[4,6]] + * combValues: ['K4', 'K5'] + * } + * } + * rightKeyDict = { + * 'k0_k1': { + * filters: [[3,2]], + * combValues: ["KO", "k1"] + * }, + * 'K0_K2': { + * filters: [[6,4]], + * combValues: ['K0', 'K2'] + * }, + * 'K3_K4' : { + * filters: [[8,9]], + * combValues: ['K3', 'k4'] + * }, + * 'k4_k5' : { + * filters: [[9,8]] + * combValues: ['K4', 'K5'] + * } + * } + * The `keys` is generated base on the type of merge operation we want to + * perform. If we assume we are performing `outer` merge (which is a set of the + * key combination from both leftKeyDict and rightKeyDict) then Keys should be + * this + * keys = ['K0_K1', 'K3_K3', 'k4_k5', 'K0_K2', 'k3_k4'] + * The Keys, leftKeyDict and rightKeyDict are used to generated DataFrame data, + * by looping through the Keys and checking if leftKeyDict and rightKeyDict as the + * key if one of them does not the column in that row will be NaN + * e.g Data for each row base on keys + * COLUMNS = ['key1', 'Key2', 'A', 'B', 'A_1', 'C'] + * 'K0_K1': ['K0', 'K1', 1, 3 , 3, 2 ] + * 'K0_K1': ['K0', 'K1', 2, 4, NaN, NaN] + * 'K3_K3': ['k3', 'K3', 3, 5, NaN, NaN] + * 'K4_K5': ['K4', 'K5', 4, 6, 9, 8] + * 'k0_K2': ['k0', 'K2' NaN, NaN, 6, 4] + * 'k3_k4': ['K3', 'K4', NaN, NaN, 8, 6] + * + * @param keys + * @param leftKeyDict + * @param rightKeyDict + */ + private basic(keys: ArrayType1D, leftKeyDict: keyComb, rightKeyDict: keyComb): ArrayType2D { + const data = [] + for (let i=0; i < keys.length; i++) { + const key = keys[i] as string + + if (utils.keyInObject(leftKeyDict, key)) { + const leftRows = leftKeyDict[key].filters + const leftCombValues = leftKeyDict[key].combValues + + for (let lIndex=0; lIndex < leftRows.length; lIndex++) { + const leftRow = leftRows[lIndex] + if (utils.keyInObject(rightKeyDict, key)) { + const rightRows = rightKeyDict[key].filters + for (let rIndex=0; rIndex < rightRows.length; rIndex++) { + const rightRow = rightRows[rIndex] + const combineData = leftCombValues.slice(0) + combineData.push(...leftRow) + combineData.push(...rightRow) + data.push(combineData) + } + } else { + const nanArray = Array(this.rightCol?.length).fill(NaN) + const combineData = leftCombValues.slice(0) + combineData.push(...leftRow) + combineData.push(...nanArray) + data.push(combineData) + } + } + } else { + const rightRows = rightKeyDict[key].filters + const rightCombValues = rightKeyDict[key].combValues + + for (let i =0; i < rightRows.length; i++) { + const rightRow = rightRows[i] + const nanArray = Array(this.leftCol?.length).fill(NaN) + const combineData = rightCombValues.slice(0) + combineData.push(...nanArray) + combineData.push(...rightRow) + data.push(combineData) + + } + } + } + return data + } + + /** + * Generate outer key from leftKeyDict and rightKeyDict + * The Key pass into basic method is the union of + * leftKeyDict and rightKeyDict + * @param leftKeyDict + * @param rightKeyDict + */ + private outer(leftKeyDict: keyComb, rightKeyDict: keyComb): ArrayType2D { + const keys = Object.keys(leftKeyDict) + keys.push(...Object.keys(rightKeyDict)) + + const UniqueKeys = Array.from(new Set(keys)) + const data = this.basic(UniqueKeys, leftKeyDict, rightKeyDict) + return data + } + + /** + * Generate Key for basic method, + * the key geneerated is the intersection of + * leftKeyDict and rightKeyDict + * @param leftKeyDict + * @param rightKeyDict + */ + private inner(leftKeyDict: keyComb, rightKeyDict: keyComb): ArrayType2D { + const leftKey = Object.keys(leftKeyDict) + const rightKey = Object.keys(rightKeyDict) + const keys = leftKey.filter((val) => rightKey.includes(val)) + const data = this.basic(keys, leftKeyDict, rightKeyDict) + return data + } + + + /** + * The key is the leftKeyDict + * @param leftKeyDict + * @param rightKeyDict + */ + private leftMerge(leftKeyDict: keyComb, rightKeyDict: keyComb): ArrayType2D { + const keys = Object.keys(leftKeyDict) + const data = this.basic(keys, leftKeyDict, rightKeyDict) + return data + } + + /** + * The key is the rightKeyDict + * @param leftKeyDict + * @param rightKeyDict + */ + private rightMerge(leftKeyDict: keyComb, rightKeyDict: keyComb): ArrayType2D { + const keys = Object.keys(rightKeyDict) + const data = this.basic(keys, leftKeyDict, rightKeyDict) + return data + } + + /** + * Perform the merge operation + * 1) Obtain both left and right dataframe values + * 2) Generate the leftkeyDict and rightKeyDict + * 3) Generate new merge columns + * 4) check how merge is to be done and apply the + * right methods + */ + operation(): DataFrame { + let leftValues = this.left.values as ArrayType2D + let rightValues = this.right.values as ArrayType2D + let leftKeyDict = this.generateKeyCombination(leftValues, this.leftColIndex) + let rightKeyDict = this.generateKeyCombination(rightValues, this.rightColIndex) + + this.createColumns() + + let data: ArrayType2D= [] + switch (this.how) { + case "outer": + data = this.outer(leftKeyDict, rightKeyDict) + break; + case "inner": + data = this.inner(leftKeyDict, rightKeyDict) + break; + case "left": + data = this.leftMerge(leftKeyDict, rightKeyDict) + break; + case "right": + data = this.rightMerge(leftKeyDict, rightKeyDict) + break; + } + const columns = this.columns as Array + return new DataFrame(data, {columns: [...columns]}) + + } + +} + +/** + * Perform merge operation between two DataFrame + * @param params : { + * left: DataFrame + * right: DataFrame + * on: Array + * how: "outer" | "inner" | "left" | "right" + * } + */ +export default function merge(params: mergeParam): DataFrame { + const mergeClass = new Merge(params) + return mergeClass.operation() +} \ No newline at end of file diff --git a/src/danfojs-base/transformers/scalers/min.max.scaler.ts b/src/danfojs-base/transformers/scalers/min.max.scaler.ts new file mode 100644 index 00000000..c69539bd --- /dev/null +++ b/src/danfojs-base/transformers/scalers/min.max.scaler.ts @@ -0,0 +1,162 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import Series from "../../core/series" +import DataFrame from "../../core/frame" +import Utils from "../../shared/utils" +import tensorflow from '../../shared/tensorflowlib' + +const utils = new Utils() + +/** + * Transform features by scaling each feature to a given range. + * This estimator scales and translates each feature individually such + * that it is in the given range on the training set, e.g. between the maximum and minimum value. +*/ +export default class MinMaxScaler { + private $max: typeof tensorflow.Tensor + private $min: typeof tensorflow.Tensor + + constructor() { + this.$max = tensorflow.tensor1d([]) + this.$min = tensorflow.tensor1d([]) + } + + private $getTensor(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + let $tensorArray: typeof tensorflow.Tensor + + if (data instanceof Array) { + if (utils.is1DArray(data)) { + $tensorArray = tensorflow.tensor1d(data as number[]) + } else { + $tensorArray = tensorflow.tensor2d(data) + } + } else if (data instanceof DataFrame || data instanceof Series) { + $tensorArray = data.tensor + } else if (data instanceof tensorflow.Tensor) { + $tensorArray = data + } else { + throw new Error("ParamError: data must be one of Array, Tensor, DataFrame or Series") + } + return $tensorArray + } + + /** + * Fits a MinMaxScaler to the data + * @param data Array, Tensor, DataFrame or Series object + * @returns MinMaxScaler + * @example + * const scaler = new MinMaxScaler() + * scaler.fit([1, 2, 3, 4, 5]) + * // MinMaxScaler { + * // $max: [5], + * // $min: [1] + * // } + * + */ + public fit(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + const tensorArray = this.$getTensor(data) + this.$max = tensorArray.max(0) + this.$min = tensorArray.min(0) + return this + } + + /** + * Transform the data using the fitted scaler + * @param data Array, Tensor, DataFrame or Series object + * @returns Array, Tensor, DataFrame or Series object + * @example + * const scaler = new MinMaxScaler() + * scaler.fit([1, 2, 3, 4, 5]) + * scaler.transform([1, 2, 3, 4, 5]) + * // [0, 0.25, 0.5, 0.75, 1] + * */ + public transform(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + const tensorArray = this.$getTensor(data) + const outputData = tensorArray + .sub(this.$min) + .div(this.$max.sub(this.$min)) + + if (Array.isArray(data)) { + return outputData.arraySync() + + } else if (data instanceof Series) { + return new Series(outputData, { + index: data.index, + }); + + } else if (data instanceof DataFrame) { + return new DataFrame(outputData, { + index: data.index, + columns: data.columns, + config: { ...data.config }, + }); + } else { + return outputData + } + } + + /** + * Fit the data and transform it + * @param data Array, Tensor, DataFrame or Series object + * @returns Array, Tensor, DataFrame or Series object + * @example + * const scaler = new MinMaxScaler() + * scaler.fitTransform([1, 2, 3, 4, 5]) + * // [0, 0.25, 0.5, 0.75, 1] + * */ + public fitTransform(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + this.fit(data) + return this.transform(data) + } + + /** + * Inverse transform the data using the fitted scaler + * @param data Array, Tensor, DataFrame or Series object + * @returns Array, Tensor, DataFrame or Series object + * @example + * const scaler = new MinMaxScaler() + * scaler.fit([1, 2, 3, 4, 5]) + * scaler.inverseTransform([0, 0.25, 0.5, 0.75, 1]) + * // [1, 2, 3, 4, 5] + * */ + public inverseTransform(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + const tensorArray = this.$getTensor(data) + const outputData = tensorArray + .mul(this.$max.sub(this.$min)) + .add(this.$min) + + if (Array.isArray(data)) { + return outputData.arraySync() + + } else if (data instanceof Series) { + return new Series(outputData, { + index: data.index, + }); + + } else if (data instanceof DataFrame) { + return new DataFrame(outputData, { + index: data.index, + columns: data.columns, + config: { ...data.config }, + }); + } else { + return outputData + } + } + +} + + diff --git a/src/danfojs-base/transformers/scalers/standard.scaler.ts b/src/danfojs-base/transformers/scalers/standard.scaler.ts new file mode 100644 index 00000000..fe0c5253 --- /dev/null +++ b/src/danfojs-base/transformers/scalers/standard.scaler.ts @@ -0,0 +1,154 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import tensorflow from '../../shared/tensorflowlib' +import Series from "../../core/series" +import DataFrame from "../../core/frame" +import Utils from "../../shared/utils" + +const utils = new Utils() + +/** + * Standardize features by removing the mean and scaling to unit variance. + * The standard score of a sample x is calculated as: `z = (x - u) / s`, + * where `u` is the mean of the training samples, and `s` is the standard deviation of the training samples. + */ +export default class StandardScaler { + private $std: typeof tensorflow.Tensor + private $mean: typeof tensorflow.Tensor + + constructor() { + this.$std = tensorflow.tensor1d([]) + this.$mean = tensorflow.tensor1d([]) + } + + private $getTensor(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + let $tensorArray + + if (data instanceof Array) { + if (utils.is1DArray(data)) { + $tensorArray = tensorflow.tensor1d(data as number[]) + } else { + $tensorArray = tensorflow.tensor2d(data) + } + } else if (data instanceof DataFrame || data instanceof Series) { + $tensorArray = data.tensor + } else if (data instanceof tensorflow.Tensor) { + $tensorArray = data + } else { + throw new Error("ParamError: data must be one of Array, DataFrame or Series") + } + return $tensorArray + } + /** + * Fit a StandardScaler to the data. + * @param data Array, Tensor, DataFrame or Series object + * @returns StandardScaler + * @example + * const scaler = new StandardScaler() + * scaler.fit([1, 2, 3, 4, 5]) + */ + public fit(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + const tensorArray = this.$getTensor(data) + this.$std = tensorflow.moments(tensorArray, 0).variance.sqrt(); + this.$mean = tensorArray.mean(0); + return this + } + + /** + * Transform the data using the fitted scaler + * @param data Array, Tensor, DataFrame or Series object + * @returns Array, Tensor, DataFrame or Series object + * @example + * const scaler = new StandardScaler() + * scaler.fit([1, 2, 3, 4, 5]) + * scaler.transform([1, 2, 3, 4, 5]) + * // [0.0, 0.0, 0.0, 0.0, 0.0] + * */ + public transform(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + const tensorArray = this.$getTensor(data) + const outputData = tensorArray.sub(this.$mean).div(this.$std) + + if (Array.isArray(data)) { + return outputData.arraySync() + + } else if (data instanceof Series) { + return new Series(outputData, { + index: data.index, + }); + + } else if (data instanceof DataFrame) { + return new DataFrame(outputData, { + index: data.index, + columns: data.columns, + config: { ...data.config }, + }); + } else { + return outputData + } + } + + /** + * Fit and transform the data using the fitted scaler + * @param data Array, Tensor, DataFrame or Series object + * @returns Array, Tensor, DataFrame or Series object + * @example + * const scaler = new StandardScaler() + * scaler.fit([1, 2, 3, 4, 5]) + * scaler.fitTransform([1, 2, 3, 4, 5]) + * // [0.0, 0.0, 0.0, 0.0, 0.0] + * */ + public fitTransform(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + this.fit(data) + return this.transform(data) + } + + /** + * Inverse transform the data using the fitted scaler + * @param data Array, Tensor, DataFrame or Series object + * @returns Array, Tensor, DataFrame or Series object + * @example + * const scaler = new StandardScaler() + * scaler.fit([1, 2, 3, 4, 5]) + * scaler.transform([1, 2, 3, 4, 5]) + * // [0.0, 0.0, 0.0, 0.0, 0.0] + * scaler.inverseTransform([0.0, 0.0, 0.0, 0.0, 0.0]) + * // [1, 2, 3, 4, 5] + * */ + public inverseTransform(data: number[] | number[][] | typeof tensorflow.Tensor | DataFrame | Series) { + const tensorArray = this.$getTensor(data) + const outputData = tensorArray.mul(this.$std).add(this.$mean) + + if (Array.isArray(data)) { + return outputData.arraySync() + + } else if (data instanceof Series) { + return new Series(outputData, { + index: data.index, + }); + + } else if (data instanceof DataFrame) { + return new DataFrame(outputData, { + index: data.index, + columns: data.columns, + config: { ...data.config }, + }); + } else { + return outputData + } + } +} + + diff --git a/danfojs-browser/yarn.lock b/src/danfojs-base/yarn.lock similarity index 61% rename from danfojs-browser/yarn.lock rename to src/danfojs-base/yarn.lock index e4940929..3431a118 100644 --- a/danfojs-browser/yarn.lock +++ b/src/danfojs-base/yarn.lock @@ -3,393 +3,457 @@ "@babel/cli@^7.10.5": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.10.tgz#67a1015b1cd505bde1696196febf910c4c339a48" - integrity sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.16.7.tgz#4184b5ec6a22106e9dd64bbcaa2eb22675ff595d" + integrity sha512-0iBF+G2Qml0y3mY5dirolyToLSR88a/KB6F2Gm8J/lOnyL8wbEOHak0DHF8gjc9XZGgTDGv/jYXNiapvsYyHTA== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" fs-readdir-recursive "^1.1.0" glob "^7.0.0" - lodash "^4.17.19" make-dir "^2.1.0" slash "^2.0.0" source-map "^0.5.0" optionalDependencies: - "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents" + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": +"@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" - integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== +"@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4": + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" + integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== "@babel/core@^7.10.5", "@babel/core@^7.7.5": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" - integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.10" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.5" - "@babel/parser" "^7.12.10" - "@babel/template" "^7.12.7" - "@babel/traverse" "^7.12.10" - "@babel/types" "^7.12.10" + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.7.tgz#db990f931f6d40cb9b87a0dc7d2adc749f1dcbcf" + integrity sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.7" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" convert-source-map "^1.7.0" debug "^4.1.0" - gensync "^1.0.0-beta.1" + gensync "^1.0.0-beta.2" json5 "^2.1.2" - lodash "^4.17.19" - semver "^5.4.1" + semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.12.10", "@babel/generator@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" - integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== +"@babel/generator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.7.tgz#b42bf46a3079fa65e1544135f32e7958f048adbb" + integrity sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg== dependencies: - "@babel/types" "^7.12.11" + "@babel/types" "^7.16.7" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" - integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== - dependencies: - "@babel/types" "^7.12.10" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" - integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== +"@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== dependencies: - "@babel/helper-explode-assignable-expression" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" - integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" + integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== dependencies: - "@babel/compat-data" "^7.12.5" - "@babel/helper-validator-option" "^7.12.1" - browserslist "^4.14.5" - semver "^5.5.0" + "@babel/helper-explode-assignable-expression" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/helper-create-class-features-plugin@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" - integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-member-expression-to-functions" "^7.12.1" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-replace-supers" "^7.12.1" - "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" -"@babel/helper-create-regexp-features-plugin@^7.12.1": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" - integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" +"@babel/helper-create-class-features-plugin@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz#9c5b34b53a01f2097daf10678d65135c1b9f84ba" + integrity sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + +"@babel/helper-create-regexp-features-plugin@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz#0cb82b9bac358eb73bfbd73985a776bfa6b14d48" + integrity sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" regexpu-core "^4.7.1" -"@babel/helper-define-map@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" - integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/types" "^7.10.5" - lodash "^4.17.19" - -"@babel/helper-explode-assignable-expression@^7.10.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" - integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" - integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== - dependencies: - "@babel/helper-get-function-arity" "^7.12.10" - "@babel/template" "^7.12.7" - "@babel/types" "^7.12.11" - -"@babel/helper-get-function-arity@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" - integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== - dependencies: - "@babel/types" "^7.12.10" - -"@babel/helper-hoist-variables@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" - integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" - integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== - dependencies: - "@babel/types" "^7.12.7" - -"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" - integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== - dependencies: - "@babel/types" "^7.12.5" - -"@babel/helper-module-transforms@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" - integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== - dependencies: - "@babel/helper-module-imports" "^7.12.1" - "@babel/helper-replace-supers" "^7.12.1" - "@babel/helper-simple-access" "^7.12.1" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/helper-validator-identifier" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" - lodash "^4.17.19" - -"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" - integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== - dependencies: - "@babel/types" "^7.12.10" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" - integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== - -"@babel/helper-remap-async-to-generator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" - integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-wrap-function" "^7.10.4" - "@babel/types" "^7.12.1" - -"@babel/helper-replace-supers@^7.12.1": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" - integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.7" - "@babel/helper-optimise-call-expression" "^7.12.10" - "@babel/traverse" "^7.12.10" - "@babel/types" "^7.12.11" - -"@babel/helper-simple-access@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" - integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" - integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== +"@babel/helper-define-polyfill-provider@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz#c5b10cf4b324ff840140bb07e05b8564af2ae971" + integrity sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg== dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" - integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-explode-assignable-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" + integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== dependencies: - "@babel/types" "^7.12.11" + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" - integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-remap-async-to-generator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.7.tgz#5ce2416990d55eb6e099128338848ae8ffa58a9a" + integrity sha512-C3o117GnP/j/N2OWo+oepeWbFEKRfNaay+F1Eo5Mj3A1SRjyx+qaFhm23nlipub7Cjv2azdUUiDH+VlpdwUFRg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-wrap-function" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helper-wrap-function@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.7.tgz#8ddf9eaa770ed43de4bc3687f3f3b0d6d5ecf014" + integrity sha512-7a9sABeVwcunnztZZ7WTgSw6jVYLzM1wua0Z4HIXm9S3/HC96WKQTkFgGEaj5W06SHHihPJ6Le6HzS5cGOQMNw== + dependencies: + "@babel/helper-function-name" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helpers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc" + integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" + integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" -"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" - integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== +"@babel/parser@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.7.tgz#d372dda9c89fcec340a82630a9f533f2fe15877e" + integrity sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA== -"@babel/helper-wrap-function@^7.10.4": - version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" - integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" + integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/helpers@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" - integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" + integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" -"@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== +"@babel/plugin-proposal-async-generator-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.7.tgz#739adc1212a9e4892de440cd7dfffb06172df78d" + integrity sha512-TTXBT3A5c11eqRzaC6beO6rlFT3Mo9C2e8eB44tTr52ESXSK2CIc2fOp1ynpAwQA8HhBMho+WXhMHWlAe3xkpw== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" - integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-async-generator-functions@^7.12.1": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" - integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== +"@babel/plugin-proposal-class-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.12.1" - "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-class-properties@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" - integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== +"@babel/plugin-proposal-class-static-block@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" + integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-dynamic-import@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" - integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== +"@babel/plugin-proposal-dynamic-import@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" + integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" - integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== +"@babel/plugin-proposal-export-namespace-from@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" + integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" - integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== +"@babel/plugin-proposal-json-strings@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" + integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" - integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== +"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" + integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" - integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" + integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" - integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== +"@babel/plugin-proposal-numeric-separator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" + integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" - integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.12.1" - -"@babel/plugin-proposal-optional-catch-binding@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" - integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" - integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-private-methods@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" - integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" - integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-async-generators@^7.8.0": +"@babel/plugin-proposal-object-rest-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8" + integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.16.7" + +"@babel/plugin-proposal-optional-catch-binding@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" + integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" + integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.7.tgz#e418e3aa6f86edd6d327ce84eff188e479f571e0" + integrity sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-private-property-in-object@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" + integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" + integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" - integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-dynamic-import@^7.8.0": +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== @@ -403,7 +467,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-json-strings@^7.8.0": +"@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== @@ -417,7 +481,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== @@ -431,368 +495,387 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.0": +"@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-catch-binding@^7.8.0": +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-chaining@^7.8.0": +"@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" - integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" - integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-async-to-generator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" - integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== +"@babel/plugin-transform-arrow-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" + integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== dependencies: - "@babel/helper-module-imports" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.12.1" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-block-scoped-functions@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" - integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== +"@babel/plugin-transform-async-to-generator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.7.tgz#646e1262ac341b587ff5449844d4492dbb10ac4b" + integrity sha512-pFEfjnK4DfXCfAlA5I98BYdDJD8NltMzx19gt6DAmfE+2lXRfPUoa0/5SUjT4+TDE1W/rcxU/1lgN55vpAjjdg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.7" -"@babel/plugin-transform-block-scoping@^7.12.11": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" - integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== +"@babel/plugin-transform-block-scoped-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" + integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-classes@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" - integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== +"@babel/plugin-transform-block-scoping@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" + integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-define-map" "^7.10.4" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.12.1" - "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-classes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" + integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" - integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== +"@babel/plugin-transform-computed-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" + integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-destructuring@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" - integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== +"@babel/plugin-transform-destructuring@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23" + integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" - integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== +"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" + integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-duplicate-keys@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" - integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== +"@babel/plugin-transform-duplicate-keys@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" + integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-exponentiation-operator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" - integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== +"@babel/plugin-transform-exponentiation-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" + integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-for-of@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" - integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== +"@babel/plugin-transform-for-of@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" + integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-function-name@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" - integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== +"@babel/plugin-transform-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" + integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-literals@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" - integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== +"@babel/plugin-transform-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" + integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-member-expression-literals@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" - integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== +"@babel/plugin-transform-member-expression-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" + integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-modules-amd@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" - integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== +"@babel/plugin-transform-modules-amd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" + integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== dependencies: - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" - integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== +"@babel/plugin-transform-modules-commonjs@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.7.tgz#fd119e6a433c527d368425b45df361e1e95d3c1a" + integrity sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w== dependencies: - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" - integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== +"@babel/plugin-transform-modules-systemjs@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" + integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== dependencies: - "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" - integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== +"@babel/plugin-transform-modules-umd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" + integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== dependencies: - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" - integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.7.tgz#749d90d94e73cf62c60a0cc8d6b94d29305a81f2" + integrity sha512-kFy35VwmwIQwCjwrAQhl3+c/kr292i4KdLPKp5lPH03Ltc51qnFlIADoyPxc/6Naz3ok3WdYKg+KK6AH+D4utg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" -"@babel/plugin-transform-new-target@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" - integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== +"@babel/plugin-transform-new-target@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" + integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-object-super@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" - integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== +"@babel/plugin-transform-object-super@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" + integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" -"@babel/plugin-transform-parameters@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" - integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== +"@babel/plugin-transform-parameters@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" + integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-property-literals@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" - integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== +"@babel/plugin-transform-property-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" + integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-regenerator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" - integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== +"@babel/plugin-transform-regenerator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" + integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" - integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== +"@babel/plugin-transform-reserved-words@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" + integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-runtime@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz#af0fded4e846c4b37078e8e5d06deac6cd848562" - integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA== - dependencies: - "@babel/helper-module-imports" "^7.12.5" - "@babel/helper-plugin-utils" "^7.10.4" - semver "^5.5.1" + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.7.tgz#1da184cb83a2287a01956c10c60e66dd503c18aa" + integrity sha512-2FoHiSAWkdq4L06uaDN3rS43i6x28desUVxq+zAFuE6kbWYQeiLPJI5IC7Sg9xKYVcrBKSQkVUfH6aeQYbl9QA== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.4.0" + babel-plugin-polyfill-regenerator "^0.3.0" + semver "^6.3.0" -"@babel/plugin-transform-shorthand-properties@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" - integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== +"@babel/plugin-transform-shorthand-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" + integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-spread@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" - integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== +"@babel/plugin-transform-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" + integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" -"@babel/plugin-transform-sticky-regex@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" - integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== +"@babel/plugin-transform-sticky-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" + integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-template-literals@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" - integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== +"@babel/plugin-transform-template-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" + integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-typeof-symbol@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" - integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== +"@babel/plugin-transform-typeof-symbol@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" + integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-unicode-escapes@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" - integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== +"@babel/plugin-transform-unicode-escapes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" + integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-unicode-regex@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" - integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== +"@babel/plugin-transform-unicode-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" + integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/preset-env@^7.10.4": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" - integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== - dependencies: - "@babel/compat-data" "^7.12.7" - "@babel/helper-compilation-targets" "^7.12.5" - "@babel/helper-module-imports" "^7.12.5" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-option" "^7.12.11" - "@babel/plugin-proposal-async-generator-functions" "^7.12.1" - "@babel/plugin-proposal-class-properties" "^7.12.1" - "@babel/plugin-proposal-dynamic-import" "^7.12.1" - "@babel/plugin-proposal-export-namespace-from" "^7.12.1" - "@babel/plugin-proposal-json-strings" "^7.12.1" - "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-numeric-separator" "^7.12.7" - "@babel/plugin-proposal-object-rest-spread" "^7.12.1" - "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.7" - "@babel/plugin-proposal-private-methods" "^7.12.1" - "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.12.1" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.7.tgz#c491088856d0b3177822a2bf06cb74d76327aa56" + integrity sha512-urX3Cee4aOZbRWOSa3mKPk0aqDikfILuo+C7qq7HY0InylGNZ1fekq9jmlr3pLWwZHF4yD7heQooc2Pow2KMyQ== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions" "^7.16.7" + "@babel/plugin-proposal-class-properties" "^7.16.7" + "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-proposal-dynamic-import" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.16.7" + "@babel/plugin-proposal-json-strings" "^7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-numeric-separator" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.7" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.12.1" - "@babel/plugin-transform-arrow-functions" "^7.12.1" - "@babel/plugin-transform-async-to-generator" "^7.12.1" - "@babel/plugin-transform-block-scoped-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.11" - "@babel/plugin-transform-classes" "^7.12.1" - "@babel/plugin-transform-computed-properties" "^7.12.1" - "@babel/plugin-transform-destructuring" "^7.12.1" - "@babel/plugin-transform-dotall-regex" "^7.12.1" - "@babel/plugin-transform-duplicate-keys" "^7.12.1" - "@babel/plugin-transform-exponentiation-operator" "^7.12.1" - "@babel/plugin-transform-for-of" "^7.12.1" - "@babel/plugin-transform-function-name" "^7.12.1" - "@babel/plugin-transform-literals" "^7.12.1" - "@babel/plugin-transform-member-expression-literals" "^7.12.1" - "@babel/plugin-transform-modules-amd" "^7.12.1" - "@babel/plugin-transform-modules-commonjs" "^7.12.1" - "@babel/plugin-transform-modules-systemjs" "^7.12.1" - "@babel/plugin-transform-modules-umd" "^7.12.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" - "@babel/plugin-transform-new-target" "^7.12.1" - "@babel/plugin-transform-object-super" "^7.12.1" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-transform-property-literals" "^7.12.1" - "@babel/plugin-transform-regenerator" "^7.12.1" - "@babel/plugin-transform-reserved-words" "^7.12.1" - "@babel/plugin-transform-shorthand-properties" "^7.12.1" - "@babel/plugin-transform-spread" "^7.12.1" - "@babel/plugin-transform-sticky-regex" "^7.12.7" - "@babel/plugin-transform-template-literals" "^7.12.1" - "@babel/plugin-transform-typeof-symbol" "^7.12.10" - "@babel/plugin-transform-unicode-escapes" "^7.12.1" - "@babel/plugin-transform-unicode-regex" "^7.12.1" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.11" - core-js-compat "^3.8.0" - semver "^5.5.0" - -"@babel/preset-modules@^0.1.3": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.16.7" + "@babel/plugin-transform-async-to-generator" "^7.16.7" + "@babel/plugin-transform-block-scoped-functions" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.16.7" + "@babel/plugin-transform-classes" "^7.16.7" + "@babel/plugin-transform-computed-properties" "^7.16.7" + "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-dotall-regex" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-exponentiation-operator" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-function-name" "^7.16.7" + "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-member-expression-literals" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.16.7" + "@babel/plugin-transform-modules-commonjs" "^7.16.7" + "@babel/plugin-transform-modules-systemjs" "^7.16.7" + "@babel/plugin-transform-modules-umd" "^7.16.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.7" + "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-object-super" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-property-literals" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.16.7" + "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-shorthand-properties" "^7.16.7" + "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-sticky-regex" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.16.7" + "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-unicode-escapes" "^7.16.7" + "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.7" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.4.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.19.1" + semver "^6.3.0" + +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -800,74 +883,87 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@^7.14.6": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" - integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== +"@babel/runtime@^7.16.0": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" + integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== dependencies: regenerator-runtime "^0.13.4" "@babel/runtime@^7.8.4": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" - integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" + integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.4", "@babel/template@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" - integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.12.7" - "@babel/types" "^7.12.7" - -"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" - integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== - dependencies: - "@babel/code-frame" "^7.12.11" - "@babel/generator" "^7.12.11" - "@babel/helper-function-name" "^7.12.11" - "@babel/helper-split-export-declaration" "^7.12.11" - "@babel/parser" "^7.12.11" - "@babel/types" "^7.12.12" +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.7.tgz#dac01236a72c2560073658dd1a285fe4e0865d76" + integrity sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.19" -"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" - integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== +"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.4.4": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.7.tgz#4ed19d51f840ed4bd5645be6ce40775fecf03159" + integrity sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg== dependencies: - "@babel/helper-validator-identifier" "^7.12.11" - lodash "^4.17.19" + "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" "@discoveryjs/json-ext@^0.5.0": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz#8f03a22a04de437254e8ce8cc84ba39689288752" - integrity sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg== + version "0.5.6" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" + integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== -"@eslint/eslintrc@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" - integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== dependencies: ajv "^6.12.4" debug "^4.1.1" espree "^7.3.0" - globals "^12.1.0" + globals "^13.9.0" ignore "^4.0.6" import-fresh "^3.2.1" js-yaml "^3.13.1" - lodash "^4.17.20" minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -880,56 +976,125 @@ resolve-from "^5.0.0" "@istanbuljs/schema@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" - integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== - -"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": - version "2.1.8-no-fsevents" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b" - integrity sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@tensorflow/tfjs-backend-cpu@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.11.0.tgz#01d5d68b91faf12bee4854adae56bc956b794f1a" - integrity sha512-ShLkrZ4/rmhZwzGKenMFDfQnaEbyZgWA5F8JRa52Iob/vptlZeuOzjq87CZKmZMUmDswR9A2kjzovT/H1bJdWQ== +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" + integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@mapbox/node-pre-gyp@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.4.tgz#6c76e7a40138eac39e1a4dc869a083e43e236c00" + integrity sha512-M669Qo4nRT7iDmQEjQYC7RU8Z6dpz9UmSbkJ1OFEja3uevCdLKh7IZZki7L1TZj02kRyl82snXFY8QqkyfowrQ== + dependencies: + detect-libc "^1.0.3" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.1" + nopt "^5.0.0" + npmlog "^4.1.2" + rimraf "^3.0.2" + semver "^7.3.4" + tar "^6.1.0" + +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": + version "2.1.8-no-fsevents.3" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" + integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@socket.io/base64-arraybuffer@~1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#568d9beae00b0d835f4f8c53fd55714986492e61" + integrity sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ== + +"@tensorflow/tfjs-backend-cpu@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.13.0.tgz#2a141256fe0a5de0670c31a9ba6990465708dee4" + integrity sha512-POmzUoAP8HooYYTZ72O1ZYkpVZB0f+8PeAkbTxIG0oahcJccj6a0Vovp1A6xWKfljUoPlJb3jWVC++S603ZL8w== dependencies: "@types/seedrandom" "2.4.27" seedrandom "2.4.3" -"@tensorflow/tfjs-backend-webgl@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.11.0.tgz#fbd7f24c164d17c11d964206b4b075b073b1a3bc" - integrity sha512-rNnc/dZ7LIl9O/Pn9W24I1h8kgpJ+XvG8NrdNSfIoWPCW4fvPSlU7B3yMeZXvRneny+z+T3xRs96nWyU2mZBJw== +"@tensorflow/tfjs-backend-webgl@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.13.0.tgz#f99df51253de21e20dae195991d332195ab30b4b" + integrity sha512-ZuJS11tCoZx2F1Eq7wqiqu8euJpPW/JV0qOKBehlRpV2qQrR+wHMpBT1hhDl4qU4LdgFTtSggKIRg/L8b0ScUQ== dependencies: - "@tensorflow/tfjs-backend-cpu" "3.11.0" + "@tensorflow/tfjs-backend-cpu" "3.13.0" "@types/offscreencanvas" "~2019.3.0" "@types/seedrandom" "2.4.27" "@types/webgl-ext" "0.0.30" "@types/webgl2" "0.0.6" seedrandom "2.4.3" -"@tensorflow/tfjs-converter@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.11.0.tgz#0842269a83599b52fd167a8a05372018a9a1ca6a" - integrity sha512-rTRIKvBoqL0qdPYpm8UXauZycOiaBHZB2E2v3OoXoHnjvle/Xn/09uZJdrixgGhR+Kahs3Vz27BEEFz6RI5j2w== +"@tensorflow/tfjs-converter@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.13.0.tgz#3affc86d94c3948b01673a91309a35feb10e5eac" + integrity sha512-H2VpDTv9Ve0HBt7ttzz46DmnsPaiT0B+yJjVH3NebGZbgY9C8boBgJIsdyqfiqEWBS3WxF8h4rh58Hv5XXMgaQ== -"@tensorflow/tfjs-core@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.11.0.tgz#1e3986533faaed922bbfc2fe86da506d0e9e5c79" - integrity sha512-JOp+1+LCd0Xg3hu7fu6iQPWZnN8Hc6ssfP7B+625XH5GYY1/OhVASa7Ahe2mJr9gZovY2lw8FUejLh1jMmBb1Q== +"@tensorflow/tfjs-core@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.13.0.tgz#0cfd707c668250969564991c5c101fb52e51e1aa" + integrity sha512-18qBEVIB/4u2OUK9nA5P1XT3e3LyarElD1UKNSNDpnMLxhLTUVZaCR71eHJcpl9wP2Q0cciaTJCTpJdPv1tNDQ== dependencies: "@types/long" "^4.0.1" "@types/offscreencanvas" "~2019.3.0" @@ -939,95 +1104,212 @@ node-fetch "~2.6.1" seedrandom "2.4.3" -"@tensorflow/tfjs-data@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-3.11.0.tgz#90dd23a7181f0a744f2882a12c3442b27047383d" - integrity sha512-+cUHUHzjM/zs0JVOwHQm9wP15Y+BZdRcUpMoYWia8r3kaGSyvoz6WqzacEP1PeXgJVnr2gtU3D+bF32th8fZfQ== +"@tensorflow/tfjs-data@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-3.13.0.tgz#55ae81957b7ed51cb0ce4e82edc63c5b3de152e6" + integrity sha512-n50+lxPK0CU72nlFt4dzMCCNV44CQsQU3sSP9zdR2bYHeoFqjjy1ISp+UV5N5DNLj7bsEMs73kGS1EuJ7YcdqQ== dependencies: "@types/node-fetch" "^2.1.2" node-fetch "~2.6.1" -"@tensorflow/tfjs-layers@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-3.11.0.tgz#456d8dc3fe93937ced329d5d06310da294d3758c" - integrity sha512-BtLgLucJZHv5te1K3yjT3iZdHXgMJArrLuOb/oRPOtTp4R2ad5N0V2m5RtuZJ3sI5/ah0h72xtmTWNyTv3/5dw== - -"@tensorflow/tfjs@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-3.11.0.tgz#63d5231f41d57ca11b910664632a8e349eba3967" - integrity sha512-TTYrKdkoh1sHnt4vn6MboLbpi1Es4U1Aw+L3PqwadRvXW4+7ySUtc00McrQ+ooK0q3Qhl3N7cvgchgM7nED3Mg== - dependencies: - "@tensorflow/tfjs-backend-cpu" "3.11.0" - "@tensorflow/tfjs-backend-webgl" "3.11.0" - "@tensorflow/tfjs-converter" "3.11.0" - "@tensorflow/tfjs-core" "3.11.0" - "@tensorflow/tfjs-data" "3.11.0" - "@tensorflow/tfjs-layers" "3.11.0" +"@tensorflow/tfjs-layers@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-3.13.0.tgz#bc311664eba4f46802ffe3b05bea7df795cae10d" + integrity sha512-kTWJ/+9fbNCMDA9iQjDMYHmWivsiWz8CKNSOZdeCW7tiBwF1EiREBVQXMk1JI11ngQa8f+rYSLs7rkhp3SYl5Q== + +"@tensorflow/tfjs-node@^3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node/-/tfjs-node-3.13.0.tgz#cb5270efd171d8893654f7037bc308cba2912ef8" + integrity sha512-LYM3ck/TyipxMFD23moX9qC3F23UBC3zbiw85HTxZ9FPlE1QNLP1UNlfFGeUTnPvY6CUcvPyQsrG9fBTvtwB1A== + dependencies: + "@mapbox/node-pre-gyp" "1.0.4" + "@tensorflow/tfjs" "3.13.0" + adm-zip "^0.5.2" + google-protobuf "^3.9.2" + https-proxy-agent "^2.2.1" + progress "^2.0.0" + rimraf "^2.6.2" + tar "^4.4.6" + +"@tensorflow/tfjs@3.13.0", "@tensorflow/tfjs@^3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-3.13.0.tgz#ea0597e0208d403278e2ccbaa5faa479083a04d3" + integrity sha512-B5HvNH+6hHhQQkn+AG+u4j5sxZBMYdsq4IWXlBZzioJcVygtZhBWXkxp01boSwngjqUBgi8S2DopBE7McAUKqQ== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.13.0" + "@tensorflow/tfjs-backend-webgl" "3.13.0" + "@tensorflow/tfjs-converter" "3.13.0" + "@tensorflow/tfjs-core" "3.13.0" + "@tensorflow/tfjs-data" "3.13.0" + "@tensorflow/tfjs-layers" "3.13.0" argparse "^1.0.10" chalk "^4.1.0" core-js "3" regenerator-runtime "^0.13.5" yargs "^16.0.3" -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@types/caseless@*": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" + integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== + +"@types/chai@^4.2.19": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" + integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== + +"@types/component-emitter@^1.2.10": + version "1.2.11" + resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" + integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== + +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.12" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" + integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== + +"@types/d3@^3": + version "3.5.46" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.46.tgz#8b890138ea035b703ef4cdd2de0d86f8619c1c69" + integrity sha512-jNHfiGd41+JUV43LTMzQNidyp4Hn0XfhoSmy8baE0d/N5pGYpD+yX03JacY/MH+smFxYOQGXlz4HxkRZOuRNOQ== "@types/eslint-scope@^3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86" - integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw== + version "3.7.2" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.2.tgz#11e96a868c67acf65bf6f11d10bb89ea71d5e473" + integrity sha512-TzgYCWoPiTeRg6RQYgtuW7iODtVoKu3RVL72k3WohqhjfaOLK5Mg2T4Tg1o2bSfu0vPkoI48wdQFv5b/Xe04wQ== dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "7.2.6" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.6.tgz#5e9aff555a975596c03a98b59ecd103decc70c3c" - integrity sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw== + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.2.2.tgz#b64dbdb64b1957cfc8a698c68297fcf8983e94c7" + integrity sha512-nQxgB8/Sg+QKhnV8e0WzPpxjIGT3tuJDDzybkDi8ItE/IgTlHo07U0shaIjzhcvQxlq9SDRE42lsJ23uvEgJ2A== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.46": +"@types/estree@*": + version "0.0.50" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" + integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== + +"@types/estree@^0.0.46": version "0.0.46" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg== -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": - version "7.0.7" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" - integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== "@types/long@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== +"@types/mocha@^8.2.2": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323" + integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== + "@types/node-fetch@^2.1.2": - version "2.5.8" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" - integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== dependencies: "@types/node" "*" form-data "^3.0.0" "@types/node@*": - version "14.14.22" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" - integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw== + version "16.11.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.0.tgz#4b95f2327bacd1ef8f08d8ceda193039c5d7f52e" + integrity sha512-8MLkBIYQMuhRBQzGN9875bYsOhPnf/0rgXGo66S2FemHkhbn9qtsz9ywV1iCG+vbjigE4WUNVvw37Dx+L0qsPg== + +"@types/node@>=10.0.0": + version "17.0.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c" + integrity sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw== + +"@types/node@^15.12.5": + version "15.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.14.9.tgz#bc43c990c3c9be7281868bbc7b8fdd6e2b57adfa" + integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== "@types/offscreencanvas@~2019.3.0": version "2019.3.0" resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553" integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q== +"@types/papaparse@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-5.3.1.tgz#fb5c613a64473c33b08fb9bc2a5ddbf25e54784e" + integrity sha512-1lbngk9wty2kCyQB42LjqSa12SEop3t9wcEC7/xYr3ujTSTmv7HWKjKYXly0GkMfQ42PRb2lFPFEibDOiMXS0g== + dependencies: + "@types/node" "*" + +"@types/plotly.js-dist-min@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@types/plotly.js-dist-min/-/plotly.js-dist-min-2.3.0.tgz#b1b86b94b86e4628d97beca95cc7dd26c2f30758" + integrity sha512-MPvZbG2RA3zuU+AYgsVysJvNLyf3bvi1nt3ywHARwMW2TB38VQuYhQFD1pTRzBuqiV5ieYif7mLY5bHWGUVZqw== + dependencies: + "@types/plotly.js" "*" + +"@types/plotly.js@*": + version "1.54.18" + resolved "https://registry.yarnpkg.com/@types/plotly.js/-/plotly.js-1.54.18.tgz#533ea4502620fe9a80e3dece8b2ece14d215497a" + integrity sha512-mtDRoEAD23rFJnTt/eKAIGAJ2QS5lVOycmXkWyol0rAalejrXnlEouHfqoA5imGusyovBjort4pEfT+TjFAJvA== + dependencies: + "@types/d3" "^3" + +"@types/request@^2.48.7": + version "2.48.8" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.8.tgz#0b90fde3b655ab50976cb8c5ac00faca22f5a82c" + integrity sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + "@types/seedrandom@2.4.27": version "2.4.27" resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41" integrity sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE= +"@types/stream-chain@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stream-chain/-/stream-chain-2.0.1.tgz#4d3cc47a32609878bc188de0bae420bcfd3bf1f5" + integrity sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg== + dependencies: + "@types/node" "*" + +"@types/stream-json@^1.7.1": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@types/stream-json/-/stream-json-1.7.2.tgz#8d7f1cc3a37a9a402a4af284348499cdf5e28248" + integrity sha512-i4LE2aWVb1R3p/Z6S6Sw9kmmOs4Drhg0SybZUyfM499I1c8p7MUKZHs4Sg9jL5eu4mDmcgfQ6eGIG3+rmfUWYw== + dependencies: + "@types/node" "*" + "@types/stream-chain" "*" + +"@types/table@^6.3.2": + version "6.3.2" + resolved "https://registry.yarnpkg.com/@types/table/-/table-6.3.2.tgz#e18ad2594400d81c3da28c31b342eb5a0d87a8e7" + integrity sha512-GJ82z3vQbx2BhiUo12w2A3lyBpXPJrGHjQ7iS5aH925098w8ojqiWBhgOUy97JS2PKLmRCTLT0sI+gJI4futig== + dependencies: + table "*" + +"@types/tough-cookie@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.1.tgz#8f80dd965ad81f3e1bc26d6f5c727e132721ff40" + integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg== + "@types/webgl-ext@0.0.30": version "0.0.30" resolved "https://registry.yarnpkg.com/@types/webgl-ext/-/webgl-ext-0.0.30.tgz#0ce498c16a41a23d15289e0b844d945b25f0fb9d" @@ -1038,6 +1320,76 @@ resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.6.tgz#1ea2db791362bd8521548d664dbd3c5311cdf4b6" integrity sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ== +"@typescript-eslint/eslint-plugin@^4.30.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== + dependencies: + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@^4.30.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== + dependencies: + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + debug "^4.3.1" + +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + "@ungap/promise-all-settled@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" @@ -1165,21 +1517,21 @@ "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.0.1.tgz#241aecfbdc715eee96bed447ed402e12ec171935" - integrity sha512-B+4uBUYhpzDXmwuo3V9yBH6cISwxEI4J+NO5ggDaGEEHb0osY/R7MzeKc0bHURXQuZjMM4qD+bSJCKIuI3eNBQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.1.0.tgz#8342bef0badfb7dfd3b576f2574ab80c725be043" + integrity sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg== "@webpack-cli/info@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.2.2.tgz#ef3c0cd947a1fa083e174a59cb74e0b6195c236c" - integrity sha512-5U9kUJHnwU+FhKH4PWGZuBC1hTEPYyxGSL5jjoBI96Gx8qcYJGOikpiIpFoTq8mmgX3im2zAo2wanv/alD74KQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.4.0.tgz#b9179c3227ab09cbbb149aa733475fcf99430223" + integrity sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw== dependencies: envinfo "^7.7.3" "@webpack-cli/serve@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.3.0.tgz#2730c770f5f1f132767c63dcaaa4ec28f8c56a6c" - integrity sha512-k2p2VrONcYVX1wRRrf0f3X2VGltLWcv+JzXRBDmvCxGlCeESx4OXw91TsWeKOkp784uNoVQo313vxJFHXPPwfw== + version "1.6.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.0.tgz#2c275aa05c895eccebbfc34cfb223c6e8bd591a2" + integrity sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA== "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -1199,11 +1551,16 @@ JSONStream@^1.0.3: jsonparse "^1.2.0" through ">=2.2.7 <3" -abab@^2.0.3, abab@^2.0.5: +abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + accepts@~1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -1212,18 +1569,10 @@ accepts@~1.3.4: mime-types "~2.1.24" negotiator "0.6.2" -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" - integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - acorn-jsx@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: version "1.8.2" @@ -1234,45 +1583,25 @@ acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: acorn-walk "^7.0.0" xtend "^4.0.2" -acorn-walk@^7.0.0, acorn-walk@^7.1.1: +acorn-walk@^7.0.0: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: +acorn@^7.0.0, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4: - version "8.0.5" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.5.tgz#a3bfb872a74a6a7f661bc81b9849d9cac12601b7" - integrity sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg== - -acorn@^8.2.4: - version "8.5.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" - integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== +acorn@^8.0.4, acorn@^8.5.0: + version "8.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== -adler-32@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.2.0.tgz#6a3e6bf0a63900ba15652808cb15c6813d1a5f25" - integrity sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU= - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -adler-32@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.3.0.tgz#3cad1b71cdfa69f6c8a91f3e3615d31a4fdedc72" - integrity sha512-f5nltvjl+PRUh6YNfUstRaXwJxtfnKEWhAWWlmKvh+Y3J2+98a0KKVYDEhz6NdKGqswLhjNGznxfSsZGOvOd9g== - dependencies: - printj "~1.2.2" - -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= +adm-zip@^0.5.2: + version "0.5.9" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.9.tgz#b33691028333821c0cf95c31374c5462f2905a83" + integrity sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg== agent-base@6: version "6.0.2" @@ -1281,6 +1610,13 @@ agent-base@6: dependencies: debug "4" +agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1304,20 +1640,10 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.3.tgz#13ae747eff125cafb230ac504b2406cf371eece2" - integrity sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ajv@^8.0.1: - version "8.6.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" - integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw== + version "8.8.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" + integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -1329,15 +1655,20 @@ ansi-colors@4.1.1, ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^3.2.1: version "3.2.1" @@ -1353,18 +1684,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== +anymatch@~3.1.1, anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -1376,11 +1699,24 @@ append-transform@^2.0.0: dependencies: default-require-extensions "^3.0.0" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= +are-we-there-yet@~1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1408,16 +1744,16 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -arraybuffer.slice@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" - integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== - asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -1429,9 +1765,9 @@ asn1.js@^5.2.0: safer-buffer "^2.1.0" asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" @@ -1463,11 +1799,6 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1478,6 +1809,20 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +awesome-typescript-loader@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz#a41daf7847515f4925cdbaa3075d61f289e913fc" + integrity sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g== + dependencies: + chalk "^2.4.1" + enhanced-resolve "^4.0.0" + loader-utils "^1.1.0" + lodash "^4.17.5" + micromatch "^3.1.9" + mkdirp "^0.5.1" + source-map-support "^0.5.3" + webpack-log "^1.2.0" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -1489,9 +1834,9 @@ aws4@^1.8.0: integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== babel-loader@^8.1.0: - version "8.2.2" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" - integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== + version "8.2.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" + integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== dependencies: find-cache-dir "^3.3.1" loader-utils "^1.4.0" @@ -1505,27 +1850,41 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz#407082d0d355ba565af24126fb6cb8e9115251fd" + integrity sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA== + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.0" + semver "^6.1.1" -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +babel-plugin-polyfill-corejs3@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.4.0.tgz#0b571f4cf3d67f911512f5c04842a7b8e8263087" + integrity sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.0" + core-js-compat "^3.18.0" -base64-arraybuffer@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812" - integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz#9ebbcd7186e1a33e21c5e20cae4e7983949533be" + integrity sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-js@^1.0.2: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64id@2.0.0: +base64id@2.0.0, base64id@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== @@ -1555,20 +1914,18 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -blob@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" - integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" @@ -1576,25 +1933,25 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== bn.js@^5.0.0, bn.js@^5.1.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" - integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== body-parser@^1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + version "1.19.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" + integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== dependencies: - bytes "3.1.0" + bytes "3.1.1" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" - http-errors "1.7.2" + http-errors "1.8.1" iconv-lite "0.4.24" on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" + qs "6.9.6" + raw-body "2.4.2" + type-is "~1.6.18" brace-expansion@^1.1.7: version "1.1.11" @@ -1604,7 +1961,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: +braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -1620,7 +1977,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1644,11 +2001,6 @@ browser-pack@^6.0.1: through2 "^2.0.0" umd "^3.0.0" -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== - browser-resolve@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-2.0.0.tgz#99b7304cb392f8d73dba741bb2d7da28c6d7842b" @@ -1776,21 +2128,21 @@ browserify@16.5.2: vm-browserify "^1.0.0" xtend "^4.0.0" -browserslist@^4.14.5, browserslist@^4.16.1: - version "4.16.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" - integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== +browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== dependencies: - caniuse-lite "^1.0.30001219" - colorette "^1.2.2" - electron-to-chromium "^1.3.723" + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" escalade "^3.1.1" - node-releases "^1.1.71" + node-releases "^2.0.1" + picocolors "^1.0.0" buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer-xor@^1.0.3: version "1.0.3" @@ -1810,10 +2162,10 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +bytes@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" + integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== cache-base@^1.0.1: version "1.0.1" @@ -1831,9 +2183,9 @@ cache-base@^1.0.1: unset-value "^1.0.0" cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" - integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.1.0.tgz#865576dfef39c0d6a7defde794d078f5308e3ef3" + integrity sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA== caching-transform@^4.0.0: version "4.0.0" @@ -1864,51 +2216,33 @@ camelcase@^5.0.0, camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001219: - version "1.0.30001230" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" - integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ== +caniuse-lite@^1.0.30001286: + version "1.0.30001297" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001297.tgz#ea7776ccc4992956582cae5b8fea127fbebde430" + integrity sha512-6bbIbowYG8vFs/Lk4hU9jFt7NknGDleVAciK916tp6ft1j+D//ZwwL6LbF1wXMQ32DMSjeuUV8suhh6dlmFjcA== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -cfb@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/cfb/-/cfb-1.2.0.tgz#6a4d0872b525ed60349e1ef51fb4b0bf73eca9a8" - integrity sha512-sXMvHsKCICVR3Naq+J556K+ExBo9n50iKl6LGarlnvuA2035uMlGA/qVrc0wQtow5P1vJEw9UyrKLCbtIKz+TQ== - dependencies: - adler-32 "~1.2.0" - crc-32 "~1.2.0" - printj "~1.1.2" - -cfb@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/cfb/-/cfb-1.2.1.tgz#209429e4c68efd30641f6fc74b2d6028bd202402" - integrity sha512-wT2ScPAFGSVy7CY+aauMezZBnNrfnaLSrxHUHdea+Td/86vrk6ZquggV+ssBR88zNs0OnBkL2+lf9q0K+zVGzQ== - dependencies: - adler-32 "~1.3.0" - crc-32 "~1.2.0" - printj "~1.3.0" - chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" deep-eql "^3.0.1" get-func-name "^2.0.0" - pathval "^1.1.0" + pathval "^1.1.1" type-detect "^4.0.5" -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1918,9 +2252,9 @@ chalk@^2.0.0: supports-color "^5.3.0" chalk@^4.0.0, chalk@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" @@ -1930,7 +2264,7 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= -chokidar@3.5.1, chokidar@^3.4.0, chokidar@^3.4.2: +chokidar@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== @@ -1945,12 +2279,35 @@ chokidar@3.5.1, chokidar@^3.4.0, chokidar@^3.4.2: optionalDependencies: fsevents "~2.3.1" -chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== +chokidar@^3.4.0, chokidar@^3.5.1: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: - tslib "^1.9.0" + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -2002,10 +2359,10 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -codepage@~1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab" - integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= collection-visit@^1.0.0: version "1.0.0" @@ -2039,16 +2396,21 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.2.1, colorette@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" - integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== +colorette@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== -colors@^1.4.0: +colors@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +colors@~0.6.0-1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" + integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w= + combine-source-map@^0.8.0, combine-source-map@~0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" @@ -2077,14 +2439,14 @@ commander@^4.0.1: integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== commander@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.0.0.tgz#3e2bbfd8bb6724760980988fb5b22b7ee6b71ab2" - integrity sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA== + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@~2.17.1: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== +commander@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" + integrity sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E= commondir@^1.0.1: version "1.0.1" @@ -2096,26 +2458,11 @@ complex.js@^2.0.15: resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.15.tgz#7add6848b4c1d12aa9262f7df925ebe7a51a7406" integrity sha512-gDBvQU8IG139ZBQTSo2qvDFP+lANMGluM779csXOr6ny1NUtA3wkUnCFjlDNH/moAVfXtvClYt6G0zarFbtz5w== -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - component-emitter@^1.2.1, component-emitter@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2146,6 +2493,11 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + constants-browserify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -2157,9 +2509,9 @@ content-type@~1.0.4: integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.1.0, convert-source-map@^1.1.3, convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== dependencies: safe-buffer "~5.1.1" @@ -2178,28 +2530,41 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.8.0: - version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" - integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== +core-js-compat@^3.18.0, core-js-compat@^3.19.1: + version "3.20.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.20.2.tgz#d1ff6936c7330959b46b2e08b122a8b14e26140b" + integrity sha512-qZEzVQ+5Qh6cROaTPFLNS4lkvQ6mBzE3R6A6EEpssj7Zr2egMHgsy4XapdifqJDGC9CBiNv7s+ejI96rLNQFdg== dependencies: - browserslist "^4.16.1" + browserslist "^4.19.1" semver "7.0.0" core-js@3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" - integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== + version "3.18.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.3.tgz#86a0bba2d8ec3df860fefcc07a8d119779f01509" + integrity sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw== -core-util-is@1.0.2, core-util-is@~1.0.0: +core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + coveralls@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" - integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== + version "3.1.1" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" + integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== dependencies: js-yaml "^3.13.1" lcov-parse "^1.0.0" @@ -2207,14 +2572,6 @@ coveralls@^3.1.0: minimist "^1.2.5" request "^2.88.2" -crc-32@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" - integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -2272,28 +2629,19 @@ crypto-browserify@^3.0.0: randombytes "^2.0.0" randomfill "^1.0.3" -cssom@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" - integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== - dependencies: - cssom "~0.3.6" - custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + dash-ast@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" @@ -2306,24 +2654,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -data-urls@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" - integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== - dependencies: - abab "^2.0.3" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.0.0" - -date-format@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf" - integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA== - -date-format@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-3.0.0.tgz#eb8780365c7d2b1511078fb491e6479780f3ad95" - integrity sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w== +date-format@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.3.tgz#f63de5dc08dc02efd8ef32bf2a6918e486f35873" + integrity sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ== debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" @@ -2332,31 +2666,24 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@4: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@~4.3.1, debug@~4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: ms "2.1.2" -debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" -debug@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== +debug@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" @@ -2370,11 +2697,6 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -decimal.js@^10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" - integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== - decimal.js@^10.3.1: version "10.3.1" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" @@ -2393,11 +2715,6 @@ deep-eql@^3.0.1: type-detect "^4.0.0" deep-is@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -2448,6 +2765,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -2471,6 +2793,11 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + detective@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" @@ -2499,6 +2826,13 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -2521,12 +2855,10 @@ domain-browser@^1.2.0: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domexception@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" - integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== - dependencies: - webidl-conversions "^5.0.0" +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" @@ -2548,10 +2880,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.723: - version "1.3.739" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz#f07756aa92cabd5a6eec6f491525a64fe62f98b9" - integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A== +electron-to-chromium@^1.4.17: + version "1.4.37" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.37.tgz#eedd53cad229ae2d1632b958a92a3d7d7b27f553" + integrity sha512-XIvFB1omSAxYgHYX48sC+HR8i/p7lx7R+0cX9faElg1g++h9IilCrJ12+bQuY+d96Wp7zkBiJwMOv+AhLtLrTg== elliptic@^6.5.3: version "6.5.4" @@ -2581,50 +2913,42 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -engine.io-client@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.5.0.tgz#fc1b4d9616288ce4f2daf06dcf612413dec941c7" - integrity sha512-12wPRfMrugVw/DNyJk34GQ5vIVArEcVMXWugQGGuw2XxUSztFNmJggZmv8IZlLyEdnpO1QB9LkcjeWewO2vxtA== - dependencies: - component-emitter "~1.3.0" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.2.0" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.6" - parseuri "0.0.6" - ws "~7.4.2" - xmlhttprequest-ssl "~1.5.4" - yeast "0.1.2" - -engine.io-parser@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7" - integrity sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg== +engine.io-parser@~5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.3.tgz#ca1f0d7b11e290b4bfda251803baea765ed89c09" + integrity sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg== dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.4" - blob "0.0.5" - has-binary2 "~1.0.2" + "@socket.io/base64-arraybuffer" "~1.0.2" -engine.io@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.5.0.tgz#9d6b985c8a39b1fe87cd91eb014de0552259821b" - integrity sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA== +engine.io@~6.1.0: + version "6.1.2" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.1.2.tgz#e7b9d546d90c62246ffcba4d88594be980d3855a" + integrity sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ== dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" accepts "~1.3.4" base64id "2.0.0" cookie "~0.4.1" - debug "~4.1.0" - engine.io-parser "~2.2.0" - ws "~7.4.2" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.0" + ws "~8.2.3" + +enhanced-resolve@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" -enhanced-resolve@^5.7.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz#525c5d856680fbd5052de453ac83e32049958b5c" - integrity sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw== +enhanced-resolve@^5.0.0, enhanced-resolve@^5.7.0: + version "5.8.3" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" + integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -2642,20 +2966,65 @@ ent@~2.2.0: integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= envinfo@^7.7.3: - version "7.7.4" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.4.tgz#c6311cdd38a0e86808c1c9343f667e4267c4a320" - integrity sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ== + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +errno@^0.1.3: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" es-module-lexer@^0.3.26: version "0.3.26" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b" integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA== +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + es6-error@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -2671,7 +3040,7 @@ escape-latex@^1.2.0: resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1" integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== -escape-string-regexp@4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -2681,18 +3050,6 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -2708,39 +3065,49 @@ eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint@^7.1.0: - version "7.18.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" - integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: - "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.3.0" + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" enquirer "^2.3.5" + escape-string-regexp "^4.0.0" eslint-scope "^5.1.1" eslint-utils "^2.1.0" eslint-visitor-keys "^2.0.0" espree "^7.3.1" - esquery "^1.2.0" + esquery "^1.4.0" esutils "^2.0.2" - file-entry-cache "^6.0.0" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" + glob-parent "^5.1.2" + globals "^13.6.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" @@ -2748,7 +3115,7 @@ eslint@^7.1.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.20" + lodash.merge "^4.6.2" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -2757,7 +3124,7 @@ eslint@^7.1.0: semver "^7.2.1" strip-ansi "^6.0.0" strip-json-comments "^3.1.0" - table "^6.0.4" + table "^6.0.9" text-table "^0.2.0" v8-compile-cache "^2.0.3" @@ -2770,15 +3137,15 @@ espree@^7.3.0, espree@^7.3.1: acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" - integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: estraverse "^5.1.0" @@ -2795,9 +3162,9 @@ estraverse@^4.1.1: integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" @@ -2815,9 +3182,9 @@ events@^2.0.0: integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== events@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" - integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" @@ -2828,9 +3195,9 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: safe-buffer "^5.1.1" execa@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376" - integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ== + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" get-stream "^6.0.0" @@ -2842,10 +3209,12 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" - integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== +executioner@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/executioner/-/executioner-2.0.1.tgz#add328e03bc45dd598f358fbb529fc0be0ec6fcd" + integrity sha1-rdMo4DvEXdWY81j7tSn8C+Dsb80= + dependencies: + mixly "^1.0.0" expand-brackets@^2.1.4: version "2.1.4" @@ -2860,6 +3229,13 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -2900,44 +3276,57 @@ extsprintf@1.3.0: integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-glob@^3.1.1: + version "3.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fast-safe-stringify@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" - integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== fastest-levenshtein@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== -fflate@^0.3.8: - version "0.3.11" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.3.11.tgz#2c440d7180fdeb819e64898d8858af327b042a5d" - integrity sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A== +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" -file-entry-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" - integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" @@ -2972,9 +3361,9 @@ finalhandler@1.1.2: unpipe "~1.0.0" find-cache-dir@^3.2.0, find-cache-dir@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== dependencies: commondir "^1.0.1" make-dir "^3.0.2" @@ -2996,6 +3385,14 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +findup@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb" + integrity sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs= + dependencies: + colors "~0.6.0-1" + commander "~2.1.0" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -3009,20 +3406,15 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - -flatted@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" - integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== +flatted@^3.1.0, flatted@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" + integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== follow-redirects@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7" - integrity sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg== + version "1.14.8" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" + integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== for-in@^1.0.2: version "1.0.2" @@ -3042,10 +3434,19 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + form-data@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" - integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" @@ -3060,15 +3461,10 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -frac@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b" - integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== - fraction.js@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff" - integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg== + version "4.1.2" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8" + integrity sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA== fragment-cache@^0.2.1: version "0.2.1" @@ -3077,19 +3473,48 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +from2-array@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/from2-array/-/from2-array-0.0.4.tgz#eafc16b65f6e2719bcd57fdc1869005ac1332cd6" + integrity sha1-6vwWtl9uJxm81X/cGGkAWsEzLNY= + dependencies: + from2 "^2.0.3" + +from2@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + fromentries@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== +fs-extra@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" + integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== dependencies: graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" fs-readdir-recursive@^1.1.0: version "1.1.0" @@ -3101,10 +3526,15 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" - integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw== +fsevents@~2.3.1, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +fulcon@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fulcon/-/fulcon-1.0.2.tgz#8a4dfda4c73fcd9cc62a79d5045c392b45547320" + integrity sha1-ik39pMc/zZzGKnnVBFw5K0VUcyA= function-bind@^1.1.1: version "1.1.1" @@ -3116,7 +3546,21 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gensync@^1.0.0-beta.1: +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -3132,14 +3576,14 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== get-intrinsic@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" - integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -3151,9 +3595,9 @@ get-package-type@^0.1.0: integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== get-stream@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718" - integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg== + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" @@ -3167,18 +3611,10 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.0.0, glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== +glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -3187,7 +3623,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.1.6, glob@^7.0.0, glob@^7.1.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3199,22 +3635,51 @@ glob@7.1.6, glob@^7.0.0, glob@^7.1.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.0.0, glob@^7.1.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== +globals@^13.6.0, globals@^13.9.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" + integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== + dependencies: + type-fest "^0.20.2" + +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== dependencies: - type-fest "^0.8.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +google-protobuf@^3.9.2: + version "3.18.1" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.18.1.tgz#31de10b65e833aa5bbd44680e8a748fa54c920f6" + integrity sha512-cDqSamZ8rGs+pOzhIsBte7wpezUKg/sggeptDWN5odhnRY/eDLa5VWLeNeQvcfiqjS3yUwgM+6OePCJMB7aWZA== -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== growl@1.10.5: version "1.10.5" @@ -3234,18 +3699,6 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -has-binary2@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" - integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== - dependencies: - isarray "2.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -3257,9 +3710,14 @@ has-flag@^4.0.0: integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" @@ -3343,12 +3801,10 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -html-encoding-sniffer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" - integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== - dependencies: - whatwg-encoding "^1.0.5" +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== html-escaper@^2.0.0: version "2.0.2" @@ -3360,25 +3816,16 @@ htmlescape@^1.1.0: resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== dependencies: depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" + inherits "2.0.4" + setprototypeof "1.2.0" statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" + toidentifier "1.0.1" http-proxy@^1.18.1: version "1.18.1" @@ -3403,6 +3850,14 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -3423,16 +3878,41 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ify-loader@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ify-loader/-/ify-loader-1.1.0.tgz#abe0654c919b48483cf075fe4a0ed2aad2da6a8b" + integrity sha512-EiyC45FRIs+z4g98+jBzuYCfoM6TKG9p7Ek5YZUeM7rucNucaMZIseRj/5Q3I4ypkZXyC2wnU1RcYrVmshe2xw== + dependencies: + bl "^1.0.0" + findup "^0.1.5" + from2-array "0.0.4" + map-limit "0.0.1" + multipipe "^0.3.0" + read-package-json "^2.0.2" + resolve "^1.1.6" + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.4, ignore@^5.1.8: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -3442,9 +3922,9 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: resolve-from "^4.0.0" import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -3459,11 +3939,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3472,7 +3947,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3510,6 +3985,13 @@ insert-module-globals@^7.0.0: undeclared-identifiers "^1.1.2" xtend "^4.0.0" +install-peers@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/install-peers/-/install-peers-1.0.3.tgz#6348f8f67e6bc23c19ee78adb819c43f8d1dd7d7" + integrity sha512-MAlSHlrn4p+g3fhx8ZVxQZXX+MkeinKLu/ThfAmrVnN5c2L8Vof7myb0UsgowJEiGcFNHYnTvo37r3uap5asYA== + dependencies: + executioner "^2.0.1" + interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" @@ -3529,13 +4011,6 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -3548,10 +4023,10 @@ is-buffer@^1.1.0, is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-core-module@^2.1.0, is-core-module@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" - integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== +is-core-module@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== dependencies: has "^1.0.3" @@ -3599,11 +4074,18 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^2.1.0, is-extglob@^2.1.1: +is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -3614,17 +4096,10 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" @@ -3652,15 +4127,10 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-potential-custom-element-name@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" - integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== - is-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" - integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" @@ -3677,15 +4147,10 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= - -isbinaryfile@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b" - integrity sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg== +isbinaryfile@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.8.tgz#5d34b94865bd4946633ecc78a026fc76c5b11fcf" + integrity sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w== isexe@^2.0.0: version "2.0.0" @@ -3710,9 +4175,9 @@ isstream@~0.1.2: integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== istanbul-lib-hook@^3.0.0: version "3.0.0" @@ -3754,18 +4219,18 @@ istanbul-lib-report@^3.0.0: supports-color "^7.1.0" istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" - integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" source-map "^0.6.1" istanbul-reports@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" - integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + version "3.1.3" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.3.tgz#4bcae3103b94518117930d51283690960b50d3c2" + integrity sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -3775,14 +4240,14 @@ javascript-natural-sort@^0.7.1: resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= -jest-worker@^26.6.2: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" - integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== +jest-worker@^27.4.1: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" + integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== dependencies: "@types/node" "*" merge-stream "^2.0.0" - supports-color "^7.0.0" + supports-color "^8.0.0" js-string-escape@^1.0.0: version "1.0.1" @@ -3814,39 +4279,6 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^16.2.2: - version "16.7.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" - integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== - dependencies: - abab "^2.0.5" - acorn "^8.2.4" - acorn-globals "^6.0.0" - cssom "^0.4.4" - cssstyle "^2.3.0" - data-urls "^2.0.0" - decimal.js "^10.2.1" - domexception "^2.0.1" - escodegen "^2.0.0" - form-data "^3.0.0" - html-encoding-sniffer "^2.0.1" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" - symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.1.0" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.5.0" - ws "^7.4.6" - xml-name-validator "^3.0.0" - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -3862,6 +4294,11 @@ json-parse-better-errors@^1.0.2: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -3872,10 +4309,10 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" @@ -3902,16 +4339,18 @@ json5@^1.0.1: minimist "^1.2.0" json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== dependencies: minimist "^1.2.5" -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" @@ -3926,13 +4365,13 @@ jsonparse@^1.2.0: integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: assert-plus "1.0.0" extsprintf "1.3.0" - json-schema "0.2.3" + json-schema "0.4.0" verror "1.10.0" karma-browserify@7.0.0: @@ -3966,34 +4405,35 @@ karma-mocha@^2.0.1: dependencies: minimist "^1.2.3" -karma@5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/karma/-/karma-5.2.3.tgz#3264024219bad2728e92542e0058a2492d7a46e4" - integrity sha512-tHdyFADhVVPBorIKCX8A37iLHxc6RBRphkSoQ+MLKdAtFn1k97tD8WUGi1KlEtDZKL3hui0qhsY9HXUfSNDYPQ== +karma@6.3.16: + version "6.3.16" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.16.tgz#76d1a705fd1cf864ee5ed85270b572641e0958ef" + integrity sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ== dependencies: body-parser "^1.19.0" braces "^3.0.2" - chokidar "^3.4.2" - colors "^1.4.0" + chokidar "^3.5.1" + colors "1.4.0" connect "^3.7.0" di "^0.0.1" dom-serialize "^2.2.1" - glob "^7.1.6" - graceful-fs "^4.2.4" + glob "^7.1.7" + graceful-fs "^4.2.6" http-proxy "^1.18.1" - isbinaryfile "^4.0.6" - lodash "^4.17.19" - log4js "^6.2.1" - mime "^2.4.5" + isbinaryfile "^4.0.8" + lodash "^4.17.21" + log4js "^6.4.1" + mime "^2.5.2" minimatch "^3.0.4" + mkdirp "^0.5.5" qjobs "^1.2.0" range-parser "^1.2.1" rimraf "^3.0.2" - socket.io "^2.3.0" + socket.io "^4.2.0" source-map "^0.6.1" - tmp "0.2.1" - ua-parser-js "0.7.22" - yargs "^15.3.1" + tmp "^0.2.1" + ua-parser-js "^0.7.30" + yargs "^16.1.1" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" @@ -4040,20 +4480,12 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - loader-runner@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== -loader-utils@^1.4.0: +loader-utils@^1.1.0, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -4081,6 +4513,11 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" @@ -4091,12 +4528,17 @@ lodash.memoize@~3.0.3: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.truncate@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= -lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.7.0: +lodash@^4.17.14, lodash@^4.17.21, lodash@^4.17.5: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4113,16 +4555,31 @@ log-symbols@4.0.0: dependencies: chalk "^4.0.0" -log4js@^6.2.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.3.0.tgz#10dfafbb434351a3e30277a00b9879446f715bcb" - integrity sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw== +log-symbols@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: - date-format "^3.0.0" - debug "^4.1.1" - flatted "^2.0.1" - rfdc "^1.1.4" - streamroller "^2.2.4" + chalk "^2.0.1" + +log4js@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.4.1.tgz#9d3a8bf2c31c1e213fe3fc398a6053f7a2bc53e8" + integrity sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg== + dependencies: + date-format "^4.0.3" + debug "^4.3.3" + flatted "^3.2.4" + rfdc "^1.3.0" + streamroller "^3.0.2" + +loglevelnext@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" + integrity sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A== + dependencies: + es6-symbol "^3.1.1" + object.assign "^4.1.0" long@4.0.0: version "4.0.0" @@ -4156,6 +4613,13 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= +map-limit@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/map-limit/-/map-limit-0.0.1.tgz#eb7961031c0f0e8d001bf2d56fab685d58822f38" + integrity sha1-63lhAxwPDo0AG/LVb6toXViCLzg= + dependencies: + once "~1.3.0" + map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -4163,12 +4627,12 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -mathjs@9.4.4: - version "9.4.4" - resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-9.4.4.tgz#29acd67563c1e720910213062824c3faf61bc858" - integrity sha512-5EEJXnWOzLDgMHSFyw623nH+MTBZxquWwXtrzTsingOouJJ6UZG2VNO1lwH31IMt9aMno1axO6TYleIP4YSDaQ== +mathjs@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.0.0.tgz#872e8e5c0d23a383760cb84e16542fad5093c6a5" + integrity sha512-PZcQ73mVvVG2GZXvE47q+j7P3ALVxWUM51wTmlVX3F/3IJMLNziNIqStwyIDAO64ZGB8u3iFlQwxT7DIijtNlw== dependencies: - "@babel/runtime" "^7.14.6" + "@babel/runtime" "^7.16.0" complex.js "^2.0.15" decimal.js "^10.3.1" escape-latex "^1.2.0" @@ -4192,12 +4656,25 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -micromatch@^3.1.10, micromatch@^3.1.4: +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^3.1.9: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -4216,6 +4693,14 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.0, micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -4224,22 +4709,34 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.45.0: - version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +mime-db@1.50.0: + version "1.50.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" + integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + +mime-types@^2.1.12: + version "2.1.33" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" + integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== dependencies: - mime-db "1.45.0" + mime-db "1.50.0" -mime@^2.4.5: - version "2.5.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.0.tgz#2b4af934401779806ee98026bb42e8c1ae1876b1" - integrity sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag== +mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + +mime@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== mimic-fn@^2.1.0: version "2.1.0" @@ -4264,9 +4761,39 @@ minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.4: brace-expansion "^1.1.7" minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minipass@^3.0.0: + version "3.1.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + dependencies: + yallist "^4.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" mixin-deep@^1.2.0: version "1.3.2" @@ -4276,15 +4803,34 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mixly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mixly/-/mixly-1.0.0.tgz#9b5a2e1f63e6dfba0d30e6797ffae62ab1dc24ef" + integrity sha1-m1ouH2Pm37oNMOZ5f/rmKrHcJO8= + dependencies: + fulcon "^1.0.1" + mkdirp-classic@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== +mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mocha@^8.3.0: - version "8.3.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.3.1.tgz#b9eda6da1eb8cb8d29860a9c2205de5b8a076560" - integrity sha512-5SBMxANWqOv5bw3Hx+HVgaWlcWcFEQDUdaUAr1AUU+qwtx6cowhn7gEDT/DwQP7uYxnvShdUOVLbTYAHOEGfDQ== + version "8.4.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.4.0.tgz#677be88bf15980a3cae03a73e10a0fc3997f0cff" + integrity sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ== dependencies: "@ungap/promise-all-settled" "1.1.2" ansi-colors "4.1.1" @@ -4348,6 +4894,13 @@ ms@2.1.3, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multipipe@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.3.1.tgz#92625525761ba04feaa09605b6382bce2c91f11f" + integrity sha1-kmJVJXYboE/qoJYFtjgrziyR8R8= + dependencies: + duplexer2 "^0.1.2" + nanoid@3.1.20: version "3.1.20" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" @@ -4385,10 +4938,17 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -node-fetch@~2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@~2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-preload@^0.2.1: version "0.2.1" @@ -4397,23 +4957,38 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" -node-releases@^1.1.71: - version "1.1.72" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" - integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== +node-releases@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" + integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +normalize-package-data@^2.0.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: - remove-trailing-separator "^1.0.1" + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-normalize-package-bin@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -4421,10 +4996,20 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== +npmlog@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= nyc@^15.1.0: version "15.1.0" @@ -4464,7 +5049,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -4521,6 +5106,13 @@ once@^1.3.0: dependencies: wrappy "1" +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + integrity sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA= + dependencies: + wrappy "1" + onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -4528,18 +5120,6 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -4569,7 +5149,7 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -4647,21 +5227,6 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse5@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - -parseqs@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5" - integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w== - -parseuri@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a" - integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow== - parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -4677,11 +5242,6 @@ path-browserify@~0.0.0: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -4697,7 +5257,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -4707,15 +5267,20 @@ path-platform@~0.11.15: resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== pbkdf2@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" - integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -4728,10 +5293,15 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pify@^4.0.1: version "4.0.1" @@ -4745,6 +5315,11 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +plotly.js-dist-min@^2.8.0: + version "2.8.3" + resolved "https://registry.yarnpkg.com/plotly.js-dist-min/-/plotly.js-dist-min-2.8.3.tgz#0ffa317de10dd48f0c32d15c83c41f60230f50b3" + integrity sha512-TjovBrqIbedUfjGWNMMs++az3lF4hsIAB8EjqM/mC0cPrO7Wg86lBkHAsRbMra5aWyXA+M52yiQUUKBfThqwzg== + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -4755,26 +5330,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -printj@~1.1.0, printj@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" - integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== - -printj@~1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.2.3.tgz#2cfb2b192a1e5385dbbe5b46658ac34aa828508a" - integrity sha512-sanczS6xOJOg7IKDvi4sGOUOe7c1tsEzjwlLFH/zgwx/uyImVM9/rgBkc8AfiQa/Vg54nRd8mkm9yI7WV/O+WA== - -printj@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.0.tgz#9018a918a790e43707f10625d6e10187a367cff6" - integrity sha512-017o8YIaz8gLhaNxRB9eBv2mWXI2CtzhPJALnQTP+OPpuUfP0RMWqr/mHCzqVeu1AQxfzSfAtAq66vKB8y7Lzg== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -4797,7 +5352,12 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -psl@^1.1.28, psl@^1.1.33: +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== @@ -4834,10 +5394,10 @@ qjobs@^1.2.0: resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@6.9.6: + version "6.9.6" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" + integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== qs@~6.5.2: version "6.5.2" @@ -4854,6 +5414,11 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -4874,13 +5439,13 @@ range-parser@^1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== +raw-body@2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" + integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== dependencies: - bytes "3.1.0" - http-errors "1.7.2" + bytes "3.1.1" + http-errors "1.8.1" iconv-lite "0.4.24" unpipe "1.0.0" @@ -4891,7 +5456,17 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@~2.3.6: +read-package-json@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.2.tgz#6992b2b66c7177259feb8eaac73c3acd28b9222a" + integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA== + dependencies: + glob "^7.1.1" + json-parse-even-better-errors "^2.3.0" + normalize-package-data "^2.0.0" + npm-normalize-package-bin "^1.0.0" + +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -4913,15 +5488,6 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" @@ -4929,29 +5495,36 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + rechoir@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca" - integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== dependencies: resolve "^1.9.0" -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== +regenerate-unicode-properties@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" + integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== dependencies: - regenerate "^1.4.0" + regenerate "^1.4.2" -regenerate@^1.4.0: +regenerate@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5: - version "0.13.7" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" - integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== regenerator-transform@^0.14.2: version "0.14.5" @@ -4969,31 +5542,31 @@ regex-not@^1.0.0, regex-not@^1.0.2: safe-regex "^1.1.0" regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== regexpu-core@^4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" - integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: + version "4.8.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" + integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^9.0.0" + regjsgen "^0.5.2" + regjsparser "^0.7.0" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + +regjsgen@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== -regjsparser@^0.6.4: - version "0.6.6" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.6.tgz#6d8c939d1a654f78859b08ddcc4aa777f3fa800a" - integrity sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ== +regjsparser@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" + integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== dependencies: jsesc "~0.5.0" @@ -5004,15 +5577,10 @@ release-zalgo@^1.0.0: dependencies: es6-error "^4.0.1" -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== repeat-string@^1.6.1: version "1.6.1" @@ -5087,31 +5655,36 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.4, resolve@^1.17.0, resolve@^1.4.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - -resolve@^1.9.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== +resolve@^1.1.4, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.4.0, resolve@^1.9.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f" + integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.8.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rfdc@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.2.0.tgz#9e9894258f48f284b43c3143c68070a4f373b949" - integrity sha512-ijLyszTMmUrXvjSooucVQwimGUk84eRcmCuLV8Xghe3UO85mjUtRAHRyoMM6XtyqbECaXuBWx18La3523sXINA== +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" @@ -5128,7 +5701,14 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5145,18 +5725,11 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== - dependencies: - xmlchars "^2.2.0" - schema-utils@^2.6.5: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" @@ -5166,12 +5739,12 @@ schema-utils@^2.6.5: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" - integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== +schema-utils@^3.0.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== dependencies: - "@types/json-schema" "^7.0.6" + "@types/json-schema" "^7.0.8" ajv "^6.12.5" ajv-keywords "^3.5.2" @@ -5180,41 +5753,53 @@ seedrandom@2.4.3: resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.3.tgz#2438504dad33917314bff18ac4d794f16d6aaecc" integrity sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw= +seedrandom@^2.4.3: + version "2.4.4" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.4.tgz#b25ea98632c73e45f58b77cfaa931678df01f9ba" + integrity sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA== + seedrandom@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== +"semver@2 || 3 || 4 || 5", semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1: - version "7.3.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" - integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== +semver@^7.2.1, semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== dependencies: lru-cache "^6.0.0" -serialize-javascript@5.0.1, serialize-javascript@^5.0.1: +serialize-javascript@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== dependencies: randombytes "^2.1.0" -set-blocking@^2.0.0: +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -5229,10 +5814,10 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: version "2.4.11" @@ -5277,14 +5862,19 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" - integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + +signal-exit@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" + integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== simple-concat@^1.0.0: version "1.0.1" @@ -5296,6 +5886,11 @@ slash@^2.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -5335,63 +5930,51 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -socket.io-adapter@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9" - integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== +socket.io-adapter@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz#4d6111e4d42e9f7646e365b4f578269821f13486" + integrity sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ== -socket.io-client@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.4.0.tgz#aafb5d594a3c55a34355562fc8aea22ed9119a35" - integrity sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ== +socket.io-parser@~4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0" + integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g== dependencies: - backo2 "1.0.2" - component-bind "1.0.0" + "@types/component-emitter" "^1.2.10" component-emitter "~1.3.0" - debug "~3.1.0" - engine.io-client "~3.5.0" - has-binary2 "~1.0.2" - indexof "0.0.1" - parseqs "0.0.6" - parseuri "0.0.6" - socket.io-parser "~3.3.0" - to-array "0.1.4" - -socket.io-parser@~3.3.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6" - integrity sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg== + debug "~4.3.1" + +socket.io@^4.2.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.4.1.tgz#cd6de29e277a161d176832bb24f64ee045c56ab8" + integrity sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg== dependencies: - component-emitter "~1.3.0" - debug "~3.1.0" - isarray "2.0.1" - -socket.io-parser@~3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.4.1.tgz#b06af838302975837eab2dc980037da24054d64a" - integrity sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A== - dependencies: - component-emitter "1.2.1" - debug "~4.1.0" - isarray "2.0.1" - -socket.io@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.4.1.tgz#95ad861c9a52369d7f1a68acf0d4a1b16da451d2" - integrity sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w== - dependencies: - debug "~4.1.0" - engine.io "~3.5.0" - has-binary2 "~1.0.2" - socket.io-adapter "~1.1.0" - socket.io-client "2.4.0" - socket.io-parser "~3.4.0" + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.1.0" + socket.io-adapter "~2.3.3" + socket.io-parser "~4.0.4" source-list-map@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +source-map-js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" + integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== + +source-map-loader@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.1.tgz#9ae5edc7c2d42570934be4c95d1ccc6352eba52d" + integrity sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA== + dependencies: + abab "^2.0.5" + iconv-lite "^0.6.3" + source-map-js "^1.0.1" + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -5403,34 +5986,29 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@~0.5.19: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== +source-map-support@^0.5.3, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - spawn-wrap@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" @@ -5443,6 +6021,32 @@ spawn-wrap@^2.0.0: signal-exit "^3.0.2" which "^2.0.1" +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -5455,13 +6059,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -ssf@~0.11.2: - version "0.11.2" - resolved "https://registry.yarnpkg.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c" - integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== - dependencies: - frac "~1.1.2" - sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -5512,9 +6109,9 @@ stream-combiner2@^1.1.1: readable-stream "^2.0.2" stream-http@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" - integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" + integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.4" @@ -5536,14 +6133,23 @@ stream-splicer@^2.0.0: inherits "^2.0.1" readable-stream "^2.0.2" -streamroller@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-2.2.4.tgz#c198ced42db94086a6193608187ce80a5f2b0e53" - integrity sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ== +streamroller@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.0.2.tgz#30418d0eee3d6c93ec897f892ed098e3a81e68b7" + integrity sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA== dependencies: - date-format "^2.1.0" + date-format "^4.0.3" debug "^4.1.1" - fs-extra "^8.1.0" + fs-extra "^10.0.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" "string-width@^1.0.2 || 2": version "2.1.1" @@ -5553,14 +6159,14 @@ streamroller@^2.2.4: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" string_decoder@^1.1.1: version "1.3.0" @@ -5576,6 +6182,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -5583,12 +6196,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^5.0.0" + ansi-regex "^5.0.1" strip-bom@^4.0.0: version "4.0.0" @@ -5612,7 +6225,7 @@ subarg@^1.0.0: dependencies: minimist "^1.1.0" -supports-color@8.1.1: +supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -5626,17 +6239,17 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0, supports-color@^7.1.0: +supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" -symbol-tree@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== syntax-error@^1.1.1: version "1.4.0" @@ -5645,6 +6258,17 @@ syntax-error@^1.1.1: dependencies: acorn-node "^1.2.0" +table@*, table@^6.0.9: + version "6.8.0" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" + integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + table@6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" @@ -5657,41 +6281,61 @@ table@6.7.1: string-width "^4.2.0" strip-ansi "^6.0.0" -table@^6.0.4: - version "6.0.7" - resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" - integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== - dependencies: - ajv "^7.0.2" - lodash "^4.17.20" - slice-ansi "^4.0.0" - string-width "^4.2.0" +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== tapable@^2.1.1, tapable@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" - integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +tar@^4.4.6: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + +tar@^6.1.0: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" terser-webpack-plugin@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz#7effadee06f7ecfa093dbbd3e9ab23f5f3ed8673" - integrity sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q== + version "5.3.0" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz#21641326486ecf91d8054161c816e464435bae9f" + integrity sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ== dependencies: - jest-worker "^26.6.2" - p-limit "^3.1.0" - schema-utils "^3.0.0" - serialize-javascript "^5.0.1" + jest-worker "^27.4.1" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" source-map "^0.6.1" - terser "^5.5.1" + terser "^5.7.2" -terser@^5.5.1: - version "5.6.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.0.tgz#138cdf21c5e3100b1b3ddfddf720962f88badcd2" - integrity sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA== +terser@^5.7.2: + version "5.14.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" + integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.19" + source-map-support "~0.5.20" test-exclude@^6.0.0: version "6.0.0" @@ -5732,18 +6376,13 @@ tiny-emitter@^2.1.0: resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== -tmp@0.2.1: +tmp@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== dependencies: rimraf "^3.0.0" -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -5781,19 +6420,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== tough-cookie@~2.5.0: version "2.5.0" @@ -5803,18 +6433,33 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -tr46@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" - integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +ts-loader@^9.2.6: + version "9.2.6" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" + integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== dependencies: - punycode "^2.1.1" + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" -tslib@^1.9.0: +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + tty-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" @@ -5839,24 +6484,22 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.8.0, type-fest@^0.8.1: +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.8.0: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.17: +type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -5864,6 +6507,16 @@ type-is@~1.6.17: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== + typed-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-2.0.0.tgz#15ab3825845138a8b1113bd89e60cd6a435739e8" @@ -5881,10 +6534,15 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -ua-parser-js@0.7.22: - version "0.7.22" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.22.tgz#960df60a5f911ea8f1c818f3747b99c6e177eae3" - integrity sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q== +typescript@^4.4.2: + version "4.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" + integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== + +ua-parser-js@^0.7.30: + version "0.7.31" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" + integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== umd@^3.0.0: version "3.0.3" @@ -5902,28 +6560,28 @@ undeclared-identifiers@^1.1.2: simple-concat "^1.0.0" xtend "^4.0.1" -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== +unicode-match-property-value-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" + integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== +unicode-property-aliases-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" + integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== union-value@^1.0.0: version "1.0.1" @@ -5935,10 +6593,10 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -universalify@^0.1.0, universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" @@ -5953,11 +6611,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -6007,15 +6660,28 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.3.2, uuid@^3.3.3: +uuid@^3.1.0, uuid@^3.3.2, uuid@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" - integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@^1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" @@ -6036,37 +6702,18 @@ void-elements@^2.0.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" - integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" - integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== - dependencies: - xml-name-validator "^3.0.0" - watchpack@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.1.1.tgz#e99630550fca07df9f90a06056987baa40a689c7" - integrity sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -webidl-conversions@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" - integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== - -webidl-conversions@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" - integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= webpack-cli@4.5.0: version "4.5.0" @@ -6088,18 +6735,28 @@ webpack-cli@4.5.0: v8-compile-cache "^2.2.0" webpack-merge "^5.7.3" +webpack-log@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" + integrity sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA== + dependencies: + chalk "^2.1.0" + log-symbols "^2.1.0" + loglevelnext "^1.0.1" + uuid "^3.1.0" + webpack-merge@^5.7.3: - version "5.7.3" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213" - integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA== + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== dependencies: clone-deep "^4.0.1" wildcard "^2.0.0" webpack-sources@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac" - integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w== + version "2.3.1" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" + integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== dependencies: source-list-map "^2.0.1" source-map "^0.6.1" @@ -6133,26 +6790,13 @@ webpack@5.21.2: watchpack "^2.0.0" webpack-sources "^2.1.1" -whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== - dependencies: - iconv-lite "0.4.24" - -whatwg-mimetype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" - integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== - -whatwg-url@^8.0.0, whatwg-url@^8.5.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" - integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= dependencies: - lodash "^4.7.0" - tr46 "^2.1.0" - webidl-conversions "^6.1.0" + tr46 "~0.0.3" + webidl-conversions "^3.0.0" which-module@^2.0.0: version "2.0.0" @@ -6180,28 +6824,22 @@ wide-align@1.1.3: dependencies: string-width "^1.0.2 || 2" +wide-align@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + wildcard@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== -wmf@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da" - integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -word@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/word/-/word-0.4.0.tgz#691272aaecb9da96388fc873d2ecb48a17cbee54" - integrity sha512-Aq84KjS7Z9HSU14qf4l/NEouaqfJAZtE9zEz7TIvw9V/3oJeUbjQwhz7ggqbL7I7REt4Bz+9HuCWsBO5N7xChw== - dependencies: - cfb "^1.2.0" - jsdom "^16.2.2" +word-wrap@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f" + integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA== workerpool@6.1.0: version "6.1.0" @@ -6241,46 +6879,14 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -ws@^7.4.6: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== - -ws@~7.4.2: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - -xlsx@^0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.17.2.tgz#032bcca02ca01b5ebf7da93dcb035891f2c092af" - integrity sha512-RIhN6/oc/ZqYZqY4jz4AX92yNfULhtNrcZP1lknIcsyR+Ra8Zu/9F1lAZWncYbDex95iYQX/XNNNzNFXZjlNOQ== - dependencies: - adler-32 "~1.2.0" - cfb "^1.1.4" - codepage "~1.15.0" - commander "~2.17.1" - crc-32 "~1.2.0" - exit-on-epipe "~1.0.1" - fflate "^0.3.8" - ssf "~0.11.2" - wmf "~1.0.1" - word "~0.4.0" - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - -xmlchars@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +ws@~8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" + integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== -xmlhttprequest-ssl@~1.5.4: - version "1.5.5" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" - integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= +"xlsx@https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz": + version "0.19.3" + resolved "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz#f804c1850e2da5260165db0a059dc2a6099d55f3" xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" @@ -6288,14 +6894,19 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" - integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== y18n@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" - integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.0, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" @@ -6316,9 +6927,9 @@ yargs-parser@^18.1.2: decamelize "^1.2.0" yargs-parser@^20.2.2: - version "20.2.5" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.5.tgz#5d37729146d3f894f39fc94b6796f5b239513186" - integrity sha512-jYRGS3zWy20NtDtK2kBgo/TlAoy5YUuhD9/LZ7z7W4j1Fdw2cqD0xEEclf8fxc8xjD6X5Qr+qQQwCEsP8iRiYg== + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== yargs-unparser@2.0.0: version "2.0.0" @@ -6330,7 +6941,7 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0, yargs@^16.0.3: +yargs@16.2.0, yargs@^16.0.3, yargs@^16.1.1: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -6343,7 +6954,7 @@ yargs@16.2.0, yargs@^16.0.3: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^15.0.2, yargs@^15.3.1: +yargs@^15.0.2: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== @@ -6361,14 +6972,9 @@ yargs@^15.0.2, yargs@^15.3.1: yargs-parser "^18.1.2" yarn@^1.22.10: - version "1.22.10" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" - integrity sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA== - -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + version "1.22.17" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.17.tgz#bf910747d22497b573131f7341c0e1d15c74036c" + integrity sha512-H0p241BXaH0UN9IeH//RT82tl5PfNraVpSpEoW+ET7lmopNC61eZ+A+IDvU8FM6Go5vx162SncDL8J1ZjRBriQ== yocto-queue@^0.1.0: version "0.1.0" diff --git a/danfojs-browser/.babelrc b/src/danfojs-browser/.babelrc similarity index 100% rename from danfojs-browser/.babelrc rename to src/danfojs-browser/.babelrc diff --git a/danfojs-browser/.coveralls.yml b/src/danfojs-browser/.coveralls.yml similarity index 100% rename from danfojs-browser/.coveralls.yml rename to src/danfojs-browser/.coveralls.yml diff --git a/src/danfojs-browser/.eslintrc b/src/danfojs-browser/.eslintrc new file mode 100644 index 00000000..66ee5d14 --- /dev/null +++ b/src/danfojs-browser/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": ["plugin:@typescript-eslint/recommended"] + } \ No newline at end of file diff --git a/danfojs-node/.eslintrc.json b/src/danfojs-browser/.eslintrc.json similarity index 92% rename from danfojs-node/.eslintrc.json rename to src/danfojs-browser/.eslintrc.json index 6ad974ec..f247ca42 100644 --- a/danfojs-node/.eslintrc.json +++ b/src/danfojs-browser/.eslintrc.json @@ -23,11 +23,16 @@ "before": false, "after": true } ], + "indent": [ "error", + 2 + ], "keyword-spacing": [ "error", { "before": true } ], + "array-bracket-spacing": [ "error", "always" + ], "space-infix-ops": "error", "object-curly-spacing": [ "error", "always" ], @@ -53,6 +58,7 @@ ], "comma-style": "error", "no-unused-vars": [ "off"] // Use @typescript-eslint/no-unused-vars instead, otherwise there will be checked twice - } + +} } diff --git a/danfojs-browser/.gitignore b/src/danfojs-browser/.gitignore similarity index 84% rename from danfojs-browser/.gitignore rename to src/danfojs-browser/.gitignore index 9bee3b89..3e6fe8d0 100644 --- a/danfojs-browser/.gitignore +++ b/src/danfojs-browser/.gitignore @@ -6,5 +6,6 @@ danfojs/data .DS_Store .idea/ -dist/ -lib/ \ No newline at end of file +dist +build +lib \ No newline at end of file diff --git a/danfojs-browser/.npmignore b/src/danfojs-browser/.npmignore similarity index 100% rename from danfojs-browser/.npmignore rename to src/danfojs-browser/.npmignore diff --git a/danfojs-browser/README.md b/src/danfojs-browser/README.md similarity index 72% rename from danfojs-browser/README.md rename to src/danfojs-browser/README.md index 08c9aede..aefc337f 100644 --- a/danfojs-browser/README.md +++ b/src/danfojs-browser/README.md @@ -47,70 +47,85 @@ easy and intuitive. It is heavily inspired by [Pandas](https://pandas.pydata.org - Robust data preprocessing functions like [OneHotEncoders](https://danfo.jsdata.org/api-reference/general-functions/danfo.onehotencoder), [LabelEncoders](https://danfo.jsdata.org/api-reference/general-functions/danfo.labelencoder), and scalers like [StandardScaler](https://danfo.jsdata.org/api-reference/general-functions/danfo.standardscaler) and [MinMaxScaler](https://danfo.jsdata.org/api-reference/general-functions/danfo.minmaxscaler) are supported on DataFrame and Series +## Installation +There are three ways to install and use Danfo.js in your application +* For Nodejs applications, you can install the [__danfojs-node__]() version via package managers like yarn and/or npm: -To use Danfo.js via script tags, copy and paste the CDN below to the body of your HTML file +```bash +npm install danfojs-node + +or + +yarn add danfojs-node +``` +For client-side applications built with frameworks like React, Vue, Next.js, etc, you can install the [__danfojs__]() version: + +```bash +npm install danfojs + +or + +yarn add danfojs +``` + +For use directly in HTML files, you can add the latest script tag from [JsDelivr](https://www.jsdelivr.com/package/npm/danfojs) to your HTML file: ```html - + ``` +See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) ### Example Usage in the Browser -> See the example below in [Code Sandbox](https://codepen.io/risingodegua/pen/bGwPGMG) +> Run in [Code Sandbox](https://codepen.io/risingodegua/pen/bGwPGMG) ```html - - - - - + + + + Document - - - + +
- - - + + ``` Output in Browser: ![](assets/browser-out.gif) -## How to install -Danfo.js is hosted on NPM, and can installed via package managers like npm and yarn - -```sh -npm install danfojs-node -``` - ### Example usage in Nodejs ```javascript @@ -118,7 +133,7 @@ npm install danfojs-node const dfd = require("danfojs-node") const file_url = "https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv" -dfd.read_csv(file_url) +dfd.readCSV(file_url) .then(df => { //prints the first five columns df.head().print() @@ -145,8 +160,8 @@ dfd.read_csv(file_url) //select columns by dtypes - let str_cols = df_drop.select_dtypes(["string"]) - let num_cols = df_drop.select_dtypes(["int32", "float32"]) + let str_cols = df_drop.selectDtypes(["string"]) + let num_cols = df_drop.selectDtypes(["int32", "float32"]) str_cols.print() num_cols.print() @@ -154,19 +169,19 @@ dfd.read_csv(file_url) //add new column to Dataframe let new_vals = df['Fare'].round(1) - df_drop.addColumn({ column: "fare_round", values: new_vals, inplace: true }) + df_drop.addColumn("fare_round", new_vals, { inplace: true }) df_drop.print() df_drop['fare_round'].round(2).print(5) //prints the number of occurence each value in the column - df_drop['Survived'].value_counts().print() + df_drop['Survived'].valueCounts().print() //print the last ten elementa of a DataFrame df_drop.tail(10).print() //prints the number of missing values in a DataFrame - df_drop.isna().sum().print() + df_drop.isNa().sum().print() }).catch(err => { console.log(err); @@ -177,18 +192,24 @@ dfd.read_csv(file_url) Output in Node Console: ![](assets/node-rec.gif) - -> If you want to use Danfo in frontend frameworks like React/Vue, read this [guide](https://danfo.jsdata.org/examples/using-danfojs-in-react) - -#### You can play with Danfo.js on Dnotebooks playground [here](https://playnotebook.jsdata.org/demo) +## Notebook support +* You can use Danfo.js on Dnotebooks playground [here](https://playnotebook.jsdata.org/demo) +* VsCode nodejs notebook extension now supports Danfo.js. See guide [here](https://marketplace.visualstudio.com/items?itemName=donjayamanne.typescript-notebook) #### [See the Official Getting Started Guide](https://danfo.jsdata.org/getting-started) ## Documentation The official documentation can be found [here](https://danfo.jsdata.org) +## Danfo.js Official Book + +![image](https://user-images.githubusercontent.com/29900845/134811659-25ff6b05-8e0d-415f-a60c-03ab1d33fd71.jpeg) + + +We recently published a book titled "Building Data Driven Applications with Danfo.js". Read more about it [here](https://danfo.jsdata.org/building-data-driven-applications-with-danfo.js-book) + ## Discussion and Development -Development discussions take place on our [issues](https://github.com/opensource9ja/danfojs/issues) tab. +Development discussions take place [here](https://github.com/opensource9ja/danfojs/discussions). ## Contributing to Danfo All contributions, bug reports, bug fixes, documentation improvements, enhancements, and ideas are welcome. A detailed overview on how to contribute can be found in the [contributing guide](https://danfo.jsdata.org/contributing-guide). diff --git a/src/danfojs-browser/babel.config.json b/src/danfojs-browser/babel.config.json new file mode 100644 index 00000000..a57b8e37 --- /dev/null +++ b/src/danfojs-browser/babel.config.json @@ -0,0 +1,18 @@ + +{ + "presets": [ + [ + "@babel/env", + { + "targets": { + "edge": "17", + "firefox": "60", + "chrome": "67", + "safari": "11.1" + }, + "useBuiltIns": "usage", + "corejs": "3.6.5" + } + ] + ] +} \ No newline at end of file diff --git a/danfojs-browser/karma.conf.js b/src/danfojs-browser/karma.conf.js similarity index 94% rename from danfojs-browser/karma.conf.js rename to src/danfojs-browser/karma.conf.js index d4e213dd..922b7d82 100644 --- a/danfojs-browser/karma.conf.js +++ b/src/danfojs-browser/karma.conf.js @@ -8,7 +8,7 @@ module.exports = function (config) { frameworks: [ "mocha", "chai", "browserify" ], // list of files / patterns to load in the browser - files: [ "lib/bundle.js", "tests/**/*.js" ], + files: [ "lib/bundle.js", "tests/**/*.test.js" ], // list of files / patterns to exclude exclude: [], @@ -16,7 +16,7 @@ module.exports = function (config) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { - "tests/**/*.js": [ "browserify" ] + "tests/**/*.test.js": [ "browserify" ] }, // test results reporter to use diff --git a/src/danfojs-browser/nodemon.json b/src/danfojs-browser/nodemon.json new file mode 100644 index 00000000..5131f099 --- /dev/null +++ b/src/danfojs-browser/nodemon.json @@ -0,0 +1,6 @@ +{ + "watch": ["src"], + "ext": ".ts,.js", + "ignore": [], + "exec": "ts-node ./src/index.ts" + } \ No newline at end of file diff --git a/danfojs-browser/package.json b/src/danfojs-browser/package.json similarity index 54% rename from danfojs-browser/package.json rename to src/danfojs-browser/package.json index a952996e..47bf9286 100644 --- a/danfojs-browser/package.json +++ b/src/danfojs-browser/package.json @@ -1,9 +1,14 @@ { "name": "danfojs", - "version": "0.3.4", + "version": "1.2.0", "description": "JavaScript library providing high performance, intuitive, and easy to use data structures for manipulating and processing structured data.", - "main": "dist/index.js", - "types": "types/index.d.ts", + "exports": { + ".": { + "types": "./dist/danfojs-browser/src/index.d.ts", + "node": "./dist/danfojs-browser/src/index.js", + "default": "./lib/bundle.esm.js" + } + }, "directories": { "test": "tests" }, @@ -17,25 +22,25 @@ ], "files": [ "lib/", - "dist/", - "types" + "dist/" ], "dependencies": { - "@tensorflow/tfjs": "3.11.0", + "@tensorflow/tfjs": "^3.13.0", "mathjs": "9.4.4", "papaparse": "^5.3.1", - "request": "^2.88.2", - "stream-json": "^1.7.3", "table": "6.7.1", - "xlsx": "^0.17.2" + "plotly.js-dist-min": "2.8.0", + "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz" }, "scripts": { "test": "karma start --single-run --browsers ChromeHeadless karma.conf.js", - "test:clean": "yarn run build:clean && yarn run test", - "build": "babel ./src -d ./dist --no-comments && yarn run bundle", - "build:clean": "rimraf ./dist && rimraf ./lib && yarn run build", + "test:clean": "yarn build:clean && yarn run test", + "build": "node ./scripts/prebuild.js && tsc && yarn run build:es5-bundle && yarn run build:esm-bundle", + "build:es5-bundle": "webpack --mode production", + "build:esm-bundle": "esbuild src/index.ts --bundle --format=esm --platform=browser --target=esnext --minify --legal-comments=none --outfile=lib/bundle.esm.js", + "build:clean": "rimraf ./dist && rimraf ./lib && node ./scripts/prebuild.js && yarn run build", + "dev": "nodemon", "lint": "eslint ./src", - "bundle": "webpack --mode production", "coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls", "coverage": "nyc report --reporter=text-lcov | coveralls && nyc report --reporter=lcov", "patch": "npm version patch" @@ -67,20 +72,39 @@ "@babel/core": "^7.10.5", "@babel/plugin-transform-runtime": "^7.12.10", "@babel/preset-env": "^7.10.4", + "@types/chai": "^4.2.19", + "@types/mocha": "^8.2.2", + "@types/node": "^15.12.5", + "@types/papaparse": "^5.2.6", + "@types/plotly.js-dist-min": "^2.3.0", + "@types/request": "^2.48.7", + "@types/stream-json": "^1.7.1", + "@types/table": "^6.3.2", + "@typescript-eslint/eslint-plugin": "^4.30.0", + "@typescript-eslint/parser": "^4.30.0", + "awesome-typescript-loader": "^5.2.1", "babel-loader": "^8.1.0", "browserify": "16.5.2", "chai": "^4.2.0", "coveralls": "^3.1.0", + "dotenv": "^10.0.0", + "esbuild": "^0.14.38", "eslint": "^7.1.0", - "karma": "5.2.3", + "ify-loader": "^1.1.0", + "install-peers": "^1.0.3", + "json-loader": "^0.5.7", + "karma": "6.3.16", "karma-browserify": "7.0.0", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^3.1.0", "karma-mocha": "^2.0.1", "mocha": "^8.3.0", "nyc": "^15.1.0", - "webpack": "5.21.2", - "webpack-cli": "4.5.0", + "source-map-loader": "^3.0.0", + "ts-loader": "^9.2.6", + "typescript": "^4.4.2", + "webpack": "5.69.1", + "webpack-cli": "4.9.2", "yarn": "^1.22.10" }, "nyc": { @@ -90,4 +114,4 @@ ] }, "sideEffects": false -} \ No newline at end of file +} diff --git a/src/danfojs-browser/scripts/prebuild.js b/src/danfojs-browser/scripts/prebuild.js new file mode 100644 index 00000000..2cc91ece --- /dev/null +++ b/src/danfojs-browser/scripts/prebuild.js @@ -0,0 +1,32 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +/** + * Danfojs-node version uses Tensorflowjs-node package. Hence on bundling, we set the tensorflow lib + * to use the Tensorflowjs-node package, and vice-versa for browser. + * */ + +/* eslint-disable no-undef */ +const fs = require('fs'); + +function updateTensorflowLib(tensorflowLibPath) { + const importStatement = ` + // This file is auto-generated by prebuild.js. Do not edit! + const tf = require("@tensorflow/tfjs")\nexport default tf + `; + fs.writeFileSync(tensorflowLibPath, importStatement); +} + +updateTensorflowLib('../danfojs-base/shared/tensorflowlib.ts'); diff --git a/src/danfojs-browser/src/core/frame.ts b/src/danfojs-browser/src/core/frame.ts new file mode 100644 index 00000000..7190ad93 --- /dev/null +++ b/src/danfojs-browser/src/core/frame.ts @@ -0,0 +1,33 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import BaseDataFrame from "../../../danfojs-base/core/frame" +import { BaseDataOptionType } from "../../../danfojs-base/shared/types"; + +/** + * Two-dimensional ndarray with axis labels. + * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. + * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. + * @param data 2D Array, JSON, Tensor, Block of data. + * @param options.index Array of numeric or string names for subseting array. If not specified, indexes are auto generated. + * @param options.columns Array of column names. If not specified, column names are auto generated. + * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. + * @param options.config General configuration object for extending or setting NDframe behavior. + */ +export default class DataFrame extends BaseDataFrame { + [key: string]: any + constructor(data?: any, options: BaseDataOptionType = {}) { + super(data, options) + } +} \ No newline at end of file diff --git a/src/danfojs-browser/src/core/series.ts b/src/danfojs-browser/src/core/series.ts new file mode 100644 index 00000000..f117bf3b --- /dev/null +++ b/src/danfojs-browser/src/core/series.ts @@ -0,0 +1,33 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import BaseSeries from "../../../danfojs-base/core/series" +import { BaseDataOptionType } from "../../../danfojs-base/shared/types"; + +/** + * One-dimensional ndarray with axis labels. + * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. + * Operations between Series (+, -, /, , *) align values based on their associated index values – they need not be the same length. + * @param data 1D Array, JSON, Tensor, Block of data. + * @param options.index Array of numeric or string index for subseting array. If not specified, indices are auto generated. + * @param options.columns Column name. This is like the name of the Series. If not specified, column name is set to 0. + * @param options.dtypes Data types of the Series data. If not specified, dtypes is inferred. + * @param options.config General configuration object for extending or setting Series behavior. + */ +export default class Series extends BaseSeries { + [key: string]: any + constructor(data?: any, options: BaseDataOptionType = {}) { + super(data, options) + } +} \ No newline at end of file diff --git a/src/danfojs-browser/src/index.ts b/src/danfojs-browser/src/index.ts new file mode 100644 index 00000000..91a0d01e --- /dev/null +++ b/src/danfojs-browser/src/index.ts @@ -0,0 +1,73 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { + NDframe, + Config, + Utils, + Str, + Dt, + MinMaxScaler, + StandardScaler, + LabelEncoder, + OneHotEncoder, + getDummies, + concat, + merge, + toDateTime, + dateRange, + tensorflow, + __version, +} from "../../danfojs-base"; + +import { + readCSVBrowser as readCSV, + streamCSVBrowser as streamCSV, + toCSVBrowser as toCSV, + readJSONBrowser as readJSON, + toJSONBrowser as toJSON, + readExcelBrowser as readExcel, + toExcelBrowser as toExcel, +} from "../../danfojs-base/io/browser" + +import DataFrame from "./core/frame" +import Series from "./core/series" + +export { + NDframe, + Config, + Utils, + Str, + Dt, + toDateTime, + Series, + DataFrame, + readCSV, + streamCSV, + toCSV, + readJSON, + toJSON, + readExcel, + toExcel, + MinMaxScaler, + StandardScaler, + LabelEncoder, + OneHotEncoder, + getDummies, + concat, + merge, + dateRange, + tensorflow, + __version, +} diff --git a/danfojs-browser/tests/core/groupby.js b/src/danfojs-browser/tests/aggregators/groupby.test.js similarity index 56% rename from danfojs-browser/tests/core/groupby.js rename to src/danfojs-browser/tests/aggregators/groupby.test.js index ab391bcf..d9932697 100644 --- a/danfojs-browser/tests/core/groupby.js +++ b/src/danfojs-browser/tests/aggregators/groupby.test.js @@ -2,21 +2,20 @@ describe("groupby", function () { it("Check group by One column data", function () { - let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; let cols = [ "A", "B", "C" ]; let df = new dfd.DataFrame(data, { columns: cols }); - let group_df = df.groupby([ "A" ]); + let groupDf = df.groupby([ "A" ]); - let group_dict = { - '1': [ [ 1, 2, 3 ] ], - '4': [ [ 4, 5, 6 ] ], - '20': [ [ 20, 30, 40 ] ], - '39': [ [ 39, 89, 78 ] ] + let groupDict = { + '1': { A: [ 1 ], B: [ 2 ], C: [ 3 ] }, + '4': { A: [ 4 ], B: [ 5 ], C: [ 6 ] }, + '20': { A: [ 20 ], B: [ 30 ], C: [ 40 ] }, + '39': { A: [ 39 ], B: [ 89 ], C: [ 78 ] } }; - - assert.deepEqual(group_df.col_dict, group_dict); + assert.deepEqual(groupDf.colDict, groupDict); }); + it("Obtain the DataFrame of one of the group", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; @@ -24,9 +23,9 @@ describe("groupby", function () { let df = new dfd.DataFrame(data, { columns: cols }); let group_df = df.groupby([ "A" ]); let new_data = [ [ 1, 2, 3 ] ]; - - assert.deepEqual(group_df.get_groups([ 1 ]).values, new_data); + assert.deepEqual(group_df.getGroup([ 1 ]).values, new_data); }); + it("Check group by Two column data", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; @@ -34,13 +33,12 @@ describe("groupby", function () { let df = new dfd.DataFrame(data, { columns: cols }); let group_df = df.groupby([ "A", "B" ]); let new_data = { - '1': { '2': [ [ 1, 2, 3 ] ] }, - '4': { '5': [ [ 4, 5, 6 ] ] }, - '20': { '30': [ [ 20, 30, 40 ] ] }, - '39': { '89': [ [ 39, 89, 78 ] ] } + '1-2': { A: [ 1 ], B: [ 2 ], C: [ 3 ] }, + '4-5': { A: [ 4 ], B: [ 5 ], C: [ 6 ] }, + '20-30': { A: [ 20 ], B: [ 30 ], C: [ 40 ] }, + '39-89': { A: [ 39 ], B: [ 89 ], C: [ 78 ] } }; - - assert.deepEqual(group_df.col_dict, new_data); + assert.deepEqual(group_df.colDict, new_data); }); it("Obtain the DataFrame of one of the group, grouped by two column", function () { @@ -51,7 +49,7 @@ describe("groupby", function () { let group_df = df.groupby([ "A", "B" ]); let new_data = [ [ 1, 2, 3 ] ]; - assert.deepEqual(group_df.get_groups([ 1, 2 ]).values, new_data); + assert.deepEqual(group_df.getGroup([ 1, 2 ]).values, new_data); }); it("Count column in group", function () { @@ -69,6 +67,7 @@ describe("groupby", function () { assert.deepEqual(group_df.col([ "C" ]).count().values, new_data); }); + it("sum column element in group", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; @@ -84,7 +83,7 @@ describe("groupby", function () { assert.deepEqual(group_df.col([ "C" ]).sum().values, new_data); }); - it("sum column element group by one column", function () { + it("sum column element group by two column", function () { let data = [ [ 1, 2, 3 ], [ 1, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; let cols = [ "A", "B", "C" ]; @@ -114,8 +113,9 @@ describe("groupby", function () { [ 39, 89, 89, 1 ] ]; - assert.deepEqual(group_df.agg({ "B": "mean", "C": "count" }).values, new_data); + assert.deepEqual(group_df.agg({ B: "mean", C: "count" }).values, new_data); }); + it("cummulative sum for groupby", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; @@ -128,8 +128,9 @@ describe("groupby", function () { [ 20, 30, 30, 40 ], [ 39, 89, 89, 78 ] ]; - assert.deepEqual(group_df.col([ "B", "C" ]).cumsum().values, new_data); + assert.deepEqual(group_df.col([ "B", "C" ]).cumSum().values, new_data); }); + it("cummulative max for groupby", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; @@ -139,8 +140,9 @@ describe("groupby", function () { let new_data = [ [ 1, 3 ], [ 4, 6 ], [ 20, 40 ], [ 39, 78 ] ]; - assert.deepEqual(group_df.col([ "C" ]).cummax().values, new_data); + assert.deepEqual(group_df.col([ "C" ]).cumMax().values, new_data); }); + it("cummulative min for groupby", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; @@ -149,7 +151,7 @@ describe("groupby", function () { let group_df = df.groupby([ "A" ]); let new_data = [ [ 1, 3 ], [ 4, 6 ], [ 20, 40 ], [ 39, 78 ] ]; - assert.deepEqual(group_df.col([ "C" ]).cummin().values, new_data); + assert.deepEqual(group_df.col([ "C" ]).cumMin().values, new_data); }); it("cummulative prod for groupby", function () { @@ -160,8 +162,9 @@ describe("groupby", function () { let group_df = df.groupby([ "A" ]); let new_data = [ [ 1, 3 ], [ 4, 6 ], [ 20, 40 ], [ 39, 78 ] ]; - assert.deepEqual(group_df.col([ "C" ]).cumprod().values, new_data); + assert.deepEqual(group_df.col([ "C" ]).cumProd().values, new_data); }); + it("mean for groupby", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; @@ -178,118 +181,191 @@ describe("groupby", function () { assert.deepEqual(group_df.col([ "B", "C" ]).mean().values, new_data); }); - it("printing multiindex table, example with cumsum operation for dataframe group by one column", function(){ + it("should apply grouby operation to all column", function(){ let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo' ], 'B': [ 'one', 'one', 'two', 'three', 'two', 'two', 'one', 'three' ], 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - - + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; let df = new dfd.DataFrame(data); - - let grp = df.groupby([ "A" ]); + let grp = df.groupby([ "A", "B" ]); let rslt = [ - [ 'foo', 1 ], - [ 'foo', 3 ], - [ 'foo', 8 ], - [ 'foo', 14 ], - [ 'foo', 21 ], - [ 'bar', 3 ], - [ 'bar', 7 ], - [ 'bar', 9 ] + [ 'foo', 'one', 2, 2 ], + [ 'foo', 'two', 2, 2 ], + [ 'foo', 'three', 1, 1 ], + [ 'bar', 'one', 1, 1 ], + [ 'bar', 'three', 1, 1 ], + [ 'bar', 'two', 1, 1 ] ]; - assert.deepEqual(grp.col([ "C" ]).cumsum().values, rslt); + assert.deepEqual(grp.count().values, rslt); }); - it("printing multiindex table, example with cumsum operation for dataframe group by one column", function(){ + it("should apply function to specific column", function () { + let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo' ], 'B': [ 'one', 'one', 'two', 'three', 'two', 'two', 'one', 'three' ], 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; let df = new dfd.DataFrame(data); + let group_df = df.groupby([ "A" ]); + let rslt = [ + [ 'foo', 5, 3 ], + [ 'foo', 6, 4 ], + [ 'foo', 7, 7 ], + [ 'foo', 9, 8 ], + [ 'foo', 10, 9 ], + [ 'bar', 4, 5 ], + [ 'bar', 3, 6 ], + [ 'bar', 8, 4 ] + ]; + assert.deepEqual(group_df.col([ 'D', 'C' ]).apply((x) => x.add(2)).values, rslt); + }); - - let grp = df.groupby([ "A", "B" ]); + it("should apply function to group column", function () { + let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo' ], + 'B': [ 'one', 'one', 'two', 'three', + 'two', 'two', 'one', 'three' ], + 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; + let df = new dfd.DataFrame(data); + let group_df = df.groupby([ "A", "B" ]); let rslt = [ - [ 'foo', 'one', 1, 3 ], - [ 'foo', 'one', 7, 10 ], - [ 'foo', 'two', 2, 4 ], - [ 'foo', 'two', 7, 9 ], - [ 'foo', 'three', 7, 8 ], - [ 'bar', 'one', 3, 2 ], - [ 'bar', 'two', 2, 6 ], - [ 'bar', 'three', 4, 1 ] + [ 'foo', 'one', 2, 2, 2, 2 ], + [ 'foo', 'two', 2, 2, 2, 2 ], + [ 'foo', 'three', 1, 1, 1, 1 ], + [ 'bar', 'one', 1, 1, 1, 1 ], + [ 'bar', 'three', 1, 1, 1, 1 ], + [ 'bar', 'two', 1, 1, 1, 1 ] ]; - assert.deepEqual(grp.col([ "C", "D" ]).cumsum().values, rslt); + assert.deepEqual(group_df.apply((x) => x.count({ axis:0 })).values, rslt); + }); + it("should obtain the number of groups", function () { + let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo' ], + 'B': [ 'one', 'one', 'two', 'three', + 'two', 'two', 'one', 'three' ], + 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; + let df = new dfd.DataFrame(data); + let group_df = df.groupby([ "A", "B" ]); + let rslt = 6; + assert.equal(group_df.ngroups, rslt); }); - it("should apply grouby operation to all column", function(){ + it("should obtain all groups", function () { let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo' ], 'B': [ 'one', 'one', 'two', 'three', 'two', 'two', 'one', 'three' ], 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; - + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; let df = new dfd.DataFrame(data); + let group_df = df.groupby([ "A", "B" ]); + let rslt = { + 'foo-one': { + A: [ 'foo', 'foo' ], + B: [ 'one', 'one' ], + C: [ 1, 6 ], + D: [ 3, 7 ] + }, + 'bar-one': { A: [ 'bar' ], B: [ 'one' ], C: [ 3 ], D: [ 2 ] }, + 'foo-two': { + A: [ 'foo', 'foo' ], + B: [ 'two', 'two' ], + C: [ 2, 5 ], + D: [ 4, 5 ] + }, + 'bar-three': { A: [ 'bar' ], B: [ 'three' ], C: [ 4 ], D: [ 1 ] }, + 'bar-two': { A: [ 'bar' ], B: [ 'two' ], C: [ 2 ], D: [ 6 ] }, + 'foo-three': { A: [ 'foo' ], B: [ 'three' ], C: [ 7 ], D: [ 8 ] } + }; + assert.deepEqual(group_df.groups, rslt); + }); - let grp = df.groupby([ "A", "B" ]); + it("should obtain the first row of all groups", function () { + let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo' ], + 'B': [ 'one', 'one', 'one', 'three', + 'two', 'two', 'one', 'three' ], + 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; + let df = new dfd.DataFrame(data); + let group_df = df.groupby([ "A", "B" ]); let rslt = [ - [ 'foo', 'one', 2, 2 ], - [ 'foo', 'two', 2, 2 ], - [ 'foo', 'three', 1, 1 ], - [ 'bar', 'one', 1, 1 ], - [ 'bar', 'two', 1, 1 ], - [ 'bar', 'three', 1, 1 ] + [ 'foo', 'one', 'foo', 'one', 1, 3 ], + [ 'foo', 'two', 'foo', 'two', 5, 5 ], + [ 'foo', 'three', 'foo', 'three', 7, 8 ], + [ 'bar', 'one', 'bar', 'one', 3, 2 ], + [ 'bar', 'three', 'bar', 'three', 4, 1 ], + [ 'bar', 'two', 'bar', 'two', 2, 6 ] ]; - - assert.deepEqual(grp.count().values, rslt); + assert.deepEqual(group_df.first().values, rslt); }); - it("should apply function to specific column", function () { + it("should obtain the last row of all groups", function () { let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo' ], - 'B': [ 'one', 'one', 'two', 'three', + 'B': [ 'one', 'one', 'one', 'three', 'two', 'two', 'one', 'three' ], 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; let df = new dfd.DataFrame(data); - let group_df = df.groupby([ "A"]); + let group_df = df.groupby([ "A", "B" ]); let rslt = [ - [ 'foo', 5, 3 ], - [ 'foo', 6, 4 ], - [ 'foo', 7, 7 ], - [ 'foo', 9, 8 ], - [ 'foo', 10, 9 ], - [ 'bar', 4, 5 ], - [ 'bar', 3, 6 ], - [ 'bar', 8, 4 ] + [ 'foo', 'one', 'foo', 'one', 6, 7 ], + [ 'foo', 'two', 'foo', 'two', 5, 5 ], + [ 'foo', 'three', 'foo', 'three', 7, 8 ], + [ 'bar', 'one', 'bar', 'one', 3, 2 ], + [ 'bar', 'three', 'bar', 'three', 4, 1 ], + [ 'bar', 'two', 'bar', 'two', 2, 6 ] ]; - assert.deepEqual(group_df.col(['D', 'C']).apply((x) => x.add(2)).values, rslt); + assert.deepEqual(group_df.last().values, rslt); }); - it("should apply function to group column", function () { + it("should obtain the number of rows of each groups", function () { let data = { 'A': [ 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo' ], - 'B': [ 'one', 'one', 'two', 'three', + 'B': [ 'one', 'one', 'one', 'three', 'two', 'two', 'one', 'three' ], 'C': [ 1, 3, 2, 4, 5, 2, 6, 7 ], - 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] }; + 'D': [ 3, 2, 4, 1, 5, 6, 7, 8 ] + }; let df = new dfd.DataFrame(data); - let group_df = df.groupby([ "A", "B"]); + let group_df = df.groupby([ "A", "B" ]); let rslt = [ - [ 'foo', 'one', 2, 2 ], - [ 'foo', 'two', 2, 2 ], - [ 'foo', 'three', 1, 1 ], - [ 'bar', 'one', 1, 1 ], - [ 'bar', 'two', 1, 1 ], - [ 'bar', 'three', 1, 1 ] + [ 'foo', 'one', 3 ], + [ 'foo', 'two', 1 ], + [ 'foo', 'three', 1 ], + [ 'bar', 'one', 1 ], + [ 'bar', 'three', 1 ], + [ 'bar', 'two', 1 ] + ]; + assert.deepEqual(group_df.size().values, rslt); + }); + it("issue 396: fix groupby when first column is int", function () { + let data = { + 'hours': [5, 6, 2, 8, 4, 3], + 'worker': ["david", "david", "john", "alice", "john", "david"], + 'day': ["monday", "tuesday", "wednesday", "thursday", "friday", "friday"] + }; + let df = new dfd.DataFrame(data); + let group_df = df.groupby(["worker"]); + let rslt = [ + ["david", 3, 3], + ["john", 2, 2], + ["alice", 1, 1] ]; - assert.deepEqual(group_df.apply((x) => x.count()).values, rslt); + assert.deepEqual(group_df.count().values, rslt); }); }); diff --git a/danfojs-browser/tests/core/date_range.js b/src/danfojs-browser/tests/core/daterange.test.js similarity index 52% rename from danfojs-browser/tests/core/date_range.js rename to src/danfojs-browser/tests/core/daterange.test.js index 65aa5d16..78cec7f8 100644 --- a/danfojs-browser/tests/core/date_range.js +++ b/src/danfojs-browser/tests/core/daterange.test.js @@ -1,25 +1,19 @@ /* eslint-disable no-undef */ -describe("date_range", function(){ +describe("dfd.dateRange", function(){ // it("Obtain date between start and end specified", function(){ - - // let d = new dfd.date_range({"start":'2018-04-24',"end":'2018-04-27'}) - // let rslt = [ - // '4/24/2018, 12:00:00 AM', - // '4/25/2018, 12:00:00 AM', - // '4/26/2018, 12:00:00 AM', - // '4/27/2018, 12:00:00 AM' - // ] - - // assert.deepEqual(d,rslt) - - + // let d = dfd.dateRange({start:'2018-04-24',end:'2018-04-27'}) + // let rslt = [ + // '4/24/2018, 1:00:00 AM', + // '4/25/2018, 1:00:00 AM', + // '4/26/2018, 1:00:00 AM', + // '4/27/2018, 1:00:00 AM' + // ] + // assert.deepEqual(d,rslt) // }); it("Obtain date between start with end not specified, but period and freq specified", function(){ - - - let d = new dfd.date_range({ "start":'1/1/2018', period:5, freq:'M' }); + let d = dfd.dateRange({ start:'1/1/2018', period:5, freq:'M' }); let rslt = [ '1/1/2018, 12:00:00 AM', '2/1/2018, 12:00:00 AM', @@ -27,14 +21,10 @@ describe("date_range", function(){ '4/1/2018, 12:00:00 AM', '5/1/2018, 12:00:00 AM' ]; - assert.deepEqual(d, rslt); - - }); it("Obtain date between start with end not specified, but period and freq specified, plus offset", function(){ - - let d = new dfd.date_range({ start:'1/1/2018', period:5, freq:'3M' }); + let d = dfd.dateRange({ start:'1/1/2018', period:5, freq:'3M' }); let rslt = [ '1/1/2018, 12:00:00 AM', '4/1/2018, 12:00:00 AM', @@ -42,14 +32,10 @@ describe("date_range", function(){ '10/1/2018, 12:00:00 AM', '1/1/2019, 12:00:00 AM' ]; - assert.deepEqual(d, rslt); - - }); it("Obtain date between start with end not specified, but period and freq specified, plus offset, longer freq", function(){ - - let d = new dfd.date_range({ start:'1/1/2018', period:5, freq:'35m' }); + let d = dfd.dateRange({ start:'1/1/2018', period:5, freq:'35m' }); let rslt = [ "1/1/2018, 12:00:00 AM", "1/1/2018, 12:35:00 AM", @@ -57,14 +43,10 @@ describe("date_range", function(){ "1/1/2018, 1:45:00 AM", "1/1/2018, 2:20:00 AM" ]; - assert.deepEqual(d, rslt); - - }); it("Obtain date range with start not specified but end and period is given", function(){ - - let d = new dfd.date_range({ end:'1/1/2018', period:8 }); + let d = dfd.dateRange({ end:'1/1/2018', period:8 }); let rslt = [ '12/25/2017, 12:00:00 AM', '12/26/2017, 12:00:00 AM', @@ -75,18 +57,33 @@ describe("date_range", function(){ '12/31/2017, 12:00:00 AM', '1/1/2018, 12:00:00 AM' ]; - assert.deepEqual(d, rslt); - - }); it("inputing wrong freq", function(){ - assert.throws(function () { new dfd.date_range({ end:'1/1/2018', period:8, freq:"d" }); }, Error, 'invalid freq d'); + assert.throws(function () { dfd.dateRange({ end:'1/1/2018', period:8, freq:"d" }); }, Error, 'invalid freq d'); }); it("inputing wrong freq with offset", function(){ - assert.throws(function () { new dfd.date_range({ end:'1/1/2018', period:8, freq:"4d" }); }, Error, 'invalid freq d'); + assert.throws(function () { dfd.dateRange({ end:'1/1/2018', period:8, freq:"4d" }); }, Error, 'invalid freq d'); }); it("inputing wrong freq offset", function(){ - assert.throws(function () { new dfd.date_range({ end:'1/1/2018', period:8, freq:"abcm" }); }, Error, 'invalid freq offset abc'); + assert.throws(function () { dfd.dateRange({ end:'1/1/2018', period:8, freq:"abcm" }); }, Error, 'invalid freq offset abc'); }); + // it("Obtain date between start and end specified with different month", function(){ + + // let d = dfd.dateRange({start:'2018-04-24',end:'2018-05-27'}) + // let rslt = [ + // '4/24/2018, 1:00:00 AM', + // '4/25/2018, 1:00:00 AM', + // '4/26/2018, 1:00:00 AM', + // '4/27/2018, 1:00:00 AM', + // '4/28/2018, 1:00:00 AM', + // '4/29/2018, 1:00:00 AM', + // '4/30/2018, 1:00:00 AM', + // '5/1/2018, 1:00:00 AM', + // '5/2/2018, 1:00:00 AM', + // '5/3/2018, 1:00:00 AM', + // '5/27/2018, 1:00:00 AM' + // ] + // assert.deepEqual(d,rslt) + // }); }); diff --git a/danfojs-browser/tests/core/timeseries.js b/src/danfojs-browser/tests/core/datetime.test.js similarity index 66% rename from danfojs-browser/tests/core/timeseries.js rename to src/danfojs-browser/tests/core/datetime.test.js index 5a669e01..e89bb97d 100644 --- a/danfojs-browser/tests/core/timeseries.js +++ b/src/danfojs-browser/tests/core/datetime.test.js @@ -19,22 +19,22 @@ describe("TimeSeries", function () { it("Return month name generated", function () { const data = [ "06-30-02019", "07-29-2019", "08-28-2019" ]; const dateTime = dfd.toDateTime(data); - const expected = [ "Jun", "Jul", "Aug" ]; - assert.deepEqual(dateTime.month_name().values, expected); + const expected = [ "June", "July", "August" ]; + assert.deepEqual(dateTime.monthName().values, expected); }); it("Return day of the week generated", function () { const data = [ "06-30-02019", "07-29-2019", "08-28-2019" ]; const dateTime = dfd.toDateTime(data); - const expected = [ "Sun", "Mon", "Wed" ]; - assert.deepEqual(dateTime.weekdays().values, expected); + const expected = [ "Sunday", "Monday", "Wednesday" ]; + assert.deepEqual(dateTime.dayOfWeekName().values, expected); }); it("Return day of the month generated", function () { const data = [ "06-30-02019", "07-29-2019", "08-28-2019" ]; const dateTime = dfd.toDateTime(data); const expected = [ 30, 29, 28 ]; - assert.deepEqual(dateTime.monthday().values, expected); + assert.deepEqual(dateTime.dayOfMonth().values, expected); }); it("Return seconds generated", function () { @@ -65,12 +65,12 @@ describe("TimeSeries", function () { const expectedMonth = [ 11, 11, 10 ]; const expectedYear = [ 2019, 2019, 2020 ]; const expectedDayOfMonth = [ 30, 29, 12 ]; - const expectedMonthName = [ "Dec", "Dec", "Nov" ]; + const expectedMonthName = [ "December", "December", "November" ]; assert.deepEqual(dateTime.month().values, expectedMonth); assert.deepEqual(dateTime.year().values, expectedYear); - assert.deepEqual(dateTime.monthday().values, expectedDayOfMonth); - assert.deepEqual(dateTime.month_name().values, expectedMonthName); + assert.deepEqual(dateTime.dayOfMonth().values, expectedDayOfMonth); + assert.deepEqual(dateTime.monthName().values, expectedMonthName); }); it("Return correct date from Series format 2", function () { @@ -79,13 +79,33 @@ describe("TimeSeries", function () { const expectedMonth = [ 11, 11, 10 ]; const expectedYear = [ 2019, 2019, 2020 ]; - const expectedDay = [ 'Mon', 'Sun', 'Sun' ]; - const expectedMonthName = [ "Dec", "Dec", "Nov" ]; + const expectedDay = [ 1, 0, 0 ]; + const expectedMonthName = [ "December", "December", "November" ]; assert.deepEqual(dateTime.month().values, expectedMonth); assert.deepEqual(dateTime.year().values, expectedYear); - assert.deepEqual(dateTime.weekdays().values, expectedDay); - assert.deepEqual(dateTime.month_name().values, expectedMonthName); + assert.deepEqual(dateTime.dayOfWeek().values, expectedDay); + assert.deepEqual(dateTime.monthName().values, expectedMonthName); }); + + it("Returns date string in standard JS format", function () { + const data = [ "02Sep2019", "03Aug2019", "04July2019" ]; + const dateTime = dfd.toDateTime(data); + const expected = [ + '9/2/2019, 12:00:00 AM', + '8/3/2019, 12:00:00 AM', + '7/4/2019, 12:00:00 AM' + ]; + + const data2 = new dfd.Series([ "12.30.19", "12.22.19", "11.01.20" ]); + const dateTime2 = dfd.toDateTime(data2); + const expected2 = [ + '12/30/2019, 12:00:00 AM', + '12/22/2019, 12:00:00 AM', + '11/1/2020, 12:00:00 AM' + ]; + assert.deepEqual(dateTime.date().values, expected); + assert.deepEqual(dateTime2.date().values, expected2); + }); }); diff --git a/src/danfojs-browser/tests/core/frame.test.js b/src/danfojs-browser/tests/core/frame.test.js new file mode 100644 index 00000000..edcd1e31 --- /dev/null +++ b/src/danfojs-browser/tests/core/frame.test.js @@ -0,0 +1,3058 @@ +/* eslint-disable no-undef */ + +describe("DataFrame", function () { + + describe("Subsetting by column names", function () { + it("retrieves the col data created from an df with two columns", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ] }; + let df = new dfd.DataFrame(data); + assert.deepEqual(df["alpha"].values, [ "A", "B", "C", "D" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + }); + it("retrieves the column data from an df with three columns", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + assert.deepEqual(df["alpha"].values, [ "A", "B", "C", "D" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["sum"].values, [ 20.3, 30.456, 40.90, 90.1 ]); + }); + + it("Set column count by subseting", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + df["alpha"] = [ "E", "F", "G", "H" ]; + assert.deepEqual(df["alpha"].values, [ "E", "F", "G", "H" ]); + assert.deepEqual(df.values[0], [ 'E', 1, 20.3 ]); + assert.deepEqual(df.dtypes, [ "string", "int32", "float32" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["sum"].values, [ 20.3, 30.456, 40.90, 90.1 ]); + }); + + it("Correct dtype is set after setting a column by subseting", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + df["alpha"] = [ 2.4, 5.6, 32.5, 1 ]; + + assert.deepEqual(df["alpha"].values, [ 2.4, 5.6, 32.5, 1 ]); + assert.deepEqual(df.values[0], [ 2.4, 1, 20.3 ]); + assert.deepEqual(df.values[1], [ 5.6, 2, 30.456 ]); + assert.deepEqual(df.values[2], [ 32.5, 3, 40.90 ]); + assert.deepEqual(df.values[3], [ 1, 4, 90.1 ]); + + df["count"] = [ "A", "B", "C", "D" ]; + assert.deepEqual(df["count"].values, [ "A", "B", "C", "D" ]); + assert.deepEqual(df.dtypes, [ "float32", "string", "float32" ]); + }); + + it("retrieves the col data created from an df with two columns in low memory mode", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ] }; + let df = new dfd.DataFrame(data, { lowMemoryMode: true }); + assert.deepEqual(df["alpha"].values, [ "A", "B", "C", "D" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + }); + it("retrieves the column data from an df with threee columns in low memory mode", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data, { lowMemoryMode: true }); + assert.deepEqual(df["alpha"].values, [ "A", "B", "C", "D" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["sum"].values, [ 20.3, 30.456, 40.90, 90.1 ]); + }); + + it("Set column count by subseting (low memory mode) ", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data, { lowMemoryMode: true }); + df["alpha"] = [ "E", "F", "G", "H" ]; + assert.deepEqual(df["alpha"].values, [ "E", "F", "G", "H" ]); + assert.deepEqual(df.values[0], [ 'E', 1, 20.3 ]); + assert.deepEqual(df.dtypes, [ "string", "int32", "float32" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["sum"].values, [ 20.3, 30.456, 40.90, 90.1 ]); + }); + + it("Correct dtype is set after setting a column by subseting (low memory mode) ", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data, { lowMemoryMode: true }); + df["alpha"] = [ 2.4, 5.6, 32.5, 1 ]; + assert.deepEqual(df["alpha"].values, [ 2.4, 5.6, 32.5, 1 ]); + assert.deepEqual(df.values[0], [ 2.4, 1, 20.3 ]); + assert.deepEqual(df.values[1], [ 5.6, 2, 30.456 ]); + assert.deepEqual(df.values[2], [ 32.5, 3, 40.90 ]); + assert.deepEqual(df.values[3], [ 1, 4, 90.1 ]); + assert.deepEqual(df.dtypes, [ "float32", "int32", "float32" ]); + }); + }); + + describe("addColumn", function () { + it("Add new array values to DataFrame works", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + const newdf = df.addColumn("new_column", [ "a", "b", "c", "d" ]); + assert.deepEqual(newdf["new_column"].values, [ "a", "b", "c", "d" ]); + assert.deepEqual(newdf.columns, [ "alpha", "count", "sum", "new_column" ]); + assert.deepEqual(newdf.dtypes, [ "string", "int32", "float32", "string" ]); + assert.deepEqual(newdf.index, [ 0, 1, 2, 3 ]); + }); + it("Add new array values to DataFrame inplace works", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + df.addColumn("new_column", [ "a", "b", "c", "d" ], { inplace: true }); + assert.deepEqual(df["new_column"].values, [ "a", "b", "c", "d" ]); + assert.deepEqual(df.columns, [ "alpha", "count", "sum", "new_column" ]); + assert.deepEqual(df.dtypes, [ "string", "int32", "float32", "string" ]); + assert.deepEqual(df.index, [ 0, 1, 2, 3 ]); + }); + it("Add new Series to DataFrame works", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + const newdf = df.addColumn("new_column", new dfd.Series([ "a", "b", "c", "d" ])); + assert.deepEqual(newdf["new_column"].values, [ "a", "b", "c", "d" ]); + assert.deepEqual(newdf.columns, [ "alpha", "count", "sum", "new_column" ]); + assert.deepEqual(newdf.dtypes, [ "string", "int32", "float32", "string" ]); + assert.deepEqual(newdf.index, [ 0, 1, 2, 3 ]); + }); + it("Correct column data is set", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + df.addColumn("new_column", [ "a", "b", "c", "d" ], { inplace: true }); + assert.deepEqual(df["new_column"].values, [ "a", "b", "c", "d" ]); + assert.deepEqual(df["alpha"].values, [ "A", "B", "C", "D" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["sum"].values, [ 20.3, 30.456, 40.90, 90.1 ]); + }); + it("throw error for wrong column length", function () { + const data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + const df = new dfd.DataFrame(data); + + assert.throws( + () => df.addColumn("new_column", new dfd.Series([ "a", "b", "c" ])), + Error, + 'ParamError: Column data length mismatch. You provided data with length 3 but Ndframe has column of length 4' + ); + + }); + it("Ensure add column does not mutate parent when not in place", function () { + const data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + const df = new dfd.DataFrame(data); + const dfNew = df.addColumn("new_column", [ "a", "b", "c", "d" ]); + assert.notDeepEqual(df, dfNew); + assert.deepEqual(dfNew["new_column"].values, [ "a", "b", "c", "d" ]); + assert.deepEqual(df["alpha"].values, [ "A", "B", "C", "D" ]); + assert.deepEqual(df["count"].values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["sum"].values, [ 20.3, 30.456, 40.90, 90.1 ]); + }); + + it("Add new array values to DataFrame works", function () { + let data = { alpha: [ "A", "B", "C", "D" ], val_count: [ 1, 2, 3, 4 ], val_sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + const newdf = df.addColumn("new_column", [ "a", "b", "c", "d" ], { atIndex: 0 }); + assert.deepEqual(newdf["new_column"].values, [ "a", "b", "c", "d" ]); + assert.deepEqual(newdf.columns, [ "new_column", "alpha", "val_count", "val_sum" ]); + assert.deepEqual(newdf.dtypes, [ "string", "int32", "float32", "string" ]); + assert.deepEqual(newdf.index, [ 0, 1, 2, 3 ]); + }); + + it("Add new array values to specific column index", function () { + let data = { alpha: [ "A", "B", "C", "D" ], val_count: [ 1, 2, 3, 4 ], val_sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let df = new dfd.DataFrame(data); + const newdf = df.addColumn("new_column", [ "a", "b", "c", "d" ], { atIndex: 'alpha' }); + assert.deepEqual(newdf["new_column"].values, [ "a", "b", "c", "d" ]); + assert.deepEqual(newdf.columns, [ "new_column", "alpha", "val_count", "val_sum" ]); + assert.deepEqual(newdf.dtypes, [ "string", "int32", "float32", "string" ]); + assert.deepEqual(newdf.index, [ 0, 1, 2, 3 ]); + }); + }); + + describe("drop", function () { + it("throw error for wrong column name", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(function () { + df.drop({ columns: [ 3 ] }); + }, + Error, + 'ParamError: specified column "3" not found in columns'); + }); + it("throw error for wrong row index", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(function () { df.drop({ index: [ 10 ] }); }, + Error, 'ParamError: specified index "10" not found in indices'); + }); + + it("drop a column inplace", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + df.drop({ columns: [ "C", "B" ], inplace: true }); + assert.deepEqual(df.columns, [ "A" ]); + assert.deepEqual(df.values, [ [ 1 ], [ 4 ] ]); + assert.deepEqual(df["A"].values, [ 1, 4 ]); + assert.deepEqual(df.dtypes, [ "int32" ]); + }); + it("drop a column inplace in low memory mode", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, config: { lowMemoryMode: true } }); + df.drop({ columns: [ "C", "B" ], inplace: true }); + assert.deepEqual(df.columns, [ "A" ]); + assert.deepEqual(df.values, [ [ 1 ], [ 4 ] ]); + assert.deepEqual(df["A"].values, [ 1, 4 ]); + assert.deepEqual(df.dtypes, [ "int32" ]); + }); + it("drop a scalar column inplace", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + df.drop({ columns: "C", inplace: true }); + assert.deepEqual(df.columns, [ "A", "B" ]); + assert.deepEqual(df.values, [ [ 1, 2 ], [ 4, 5 ] ]); + assert.deepEqual(df["A"].values, [ 1, 4 ]); + assert.deepEqual(df["B"].values, [ 2, 5 ]); + }); + it("check if data is updated after column is dropped", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + df.drop({ columns: [ "C" ], axis: 1, inplace: true }); + const new_data = [ [ 1, 2 ], [ 4, 5 ] ]; + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.dtypes.length, 2); + + }); + + it("check if data is updated after row is dropped", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const dfNew = new dfd.DataFrame(data, { columns: cols }); + const df = dfNew.drop({ index: [ 0 ] }); + const new_data = [ [ 4, 5, 6 ] ]; + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.dtypes, [ "int32", "int32", "int32" ]); + assert.deepEqual(df["A"].values, [ 4 ]); + assert.deepEqual(df["B"].values, [ 5 ]); + assert.deepEqual(df["C"].values, [ 6 ]); + assert.deepEqual(df.columns, cols); + assert.notDeepEqual(dfNew, df); + }); + it("check if data is updated after row is dropped (inplace)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + df.drop({ index: [ 0 ], inplace: true }); + const new_data = [ [ 4, 5, 6 ] ]; + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.dtypes, [ "int32", "int32", "int32" ]); + assert.deepEqual(df["A"].values, [ 4 ]); + assert.deepEqual(df["B"].values, [ 5 ]); + assert.deepEqual(df["C"].values, [ 6 ]); + assert.deepEqual(df.columns, cols); + }); + it("check if new dfd.dataframe is properly created after column is dropped (not-in-inplace)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const df_drop = df.drop({ columns: [ "C" ], axis: 1, inplace: false }); + + const expected_data = [ [ 1, 2 ], [ 4, 5 ] ]; + const expected_cols = [ "A", "B" ]; + const expected_df = new dfd.DataFrame(expected_data, { columns: expected_cols }); + assert.deepEqual(df_drop.values, expected_df.values); + }); + it("check that the dtype is updated after column drop", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + df.drop({ columns: [ "A" ], axis: 1, inplace: true }); + const dtype = [ 'int32', 'int32' ]; + assert.deepEqual(df.dtypes, dtype); + }); + it("drop row by single string labels", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 34, 5 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "a", "b", "c" ] }); + df.drop({ index: [ "a" ], inplace: true }); + const new_data = [ [ 4, 5, 6 ], [ 20, 34, 5 ] ]; + assert.deepEqual(df.values, new_data); + }); + it("drop row by two or more string labels", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 34, 5 ], [ 2, 3.4, 5 ], [ 2.0, 340, 5 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "a", "b", "c", "d", "e" ] }); + df.drop({ index: [ "a", "b" ], inplace: true }); + const new_data = [ [ 20, 34, 5 ], [ 2, 3.4, 5 ], [ 2.0, 340, 5 ] ]; + assert.deepEqual(df.values, new_data); + + }); + it("drop row by two or more string labels with numeric index", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 34, 5 ], [ 2, 3.4, 5 ], [ 2.0, 340, 5 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "a", "b", 1, "d", "e" ] }); + df.drop({ index: [ 1, "b" ], inplace: true }); + const new_data = [ [ 1, 2, 3 ], [ 2, 3.4, 5 ], [ 2.0, 340, 5 ] ]; + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.index, [ "a", "d", "e" ]); + + }); + }); + + describe("head", function () { + it("Gets the first n rows in a DataFrame", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.deepEqual(df.head(2).values, [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]); + }); + it("Throws error if row specified is less than 0", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(() => df.head(-1), Error, + "ParamError: Number of rows cannot be less than 1"); + }); + + it("Returns all rows when size of DataFrame is less than default (5)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.deepEqual(df.head().values, data); + }); + + }); + + describe("tail", function () { + it("Prints the last n rows of a DataFrame", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.deepEqual(df.tail(2).values, [ [ 20, 30, 40 ], [ 39, 89, 78 ] ]); + }); + it("Throws error if row specified is less than 0", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(() => df.tail(-1), Error, + "ParamError: Number of rows cannot be less than 1"); + }); + it("Return last 3 row index in a DataFrame", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.deepEqual(df.tail(2).index, [ 2, 3 ]); + }); + it("Check print format on head call", function () { + const data = [ [ 1, 2, 34, 5, 0, 6, 4, 5, 6, 7 ], [ 20, 30, 40, 39, 89, 78, 45, 56, 56, 45 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.tail(2).values, [ [ 1, 2, 34, 5, 0, 6, 4, 5, 6, 7 ], [ 20, 30, 40, 39, 89, 78, 45, 56, 56, 45 ] ]); + }); + it("Returns all rows when size of DataFrame is less than default (5)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.deepEqual(df.tail().values, data); + }); + }); + + describe("sample", function () { + it("Samples n number of random elements from a DataFrame", async function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ], [ 100, 200, 300 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const expected = [ [ 1, 2, 3 ], [ 20, 30, 40 ] ]; + const values = (await df.sample(2)).values; + assert.deepEqual(values, expected); + }); + it("Throw error if n is greater than length of Dataframe", async function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ], [ 100, 200, 300 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + try { + await df.sample(100); + } catch (e) { + expect(e).to.be.instanceOf(Error); + expect(e.message).to.eql('ParamError: Sample size cannot be bigger than number of rows'); + } + }); + it("Throw error if n is less than 0", async function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ], [ 100, 200, 300 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + try { + await df.sample(-2); + } catch (e) { + expect(e).to.be.instanceOf(Error); + expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); + } + }); + it("Throw error if n is 0", async function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ], [ 100, 200, 300 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + try { + await df.sample(0); + } catch (e) { + expect(e).to.be.instanceOf(Error); + expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); + } + }); + it("Seed works and random number is reproducible", async function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ], [ 100, 200, 300 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const values1 = (await df.sample(2, { seed: 453 })).values; + const values2 = (await df.sample(2, { seed: 453 })).values; + const values3 = (await df.sample(2, { seed: 1 })).values; + + assert.deepEqual(values1, values2); + assert.notDeepEqual(values1, values3); + + }); + }); + + describe("loc", function () { + + it("throw error for wrong column name", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(function () { + df.loc({ "rows": [ 0, 1 ], "columns": [ "A", "D" ] }); + }, + Error, + "IndexError: Specified column (D) not found"); + }); + + it(`check data after selecting { "rows": ["0", "1"], "columns": ["B", "C"] }`, function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "0", "1" ] }); + + const colDf = df.loc({ "rows": [ "0", "1" ], "columns": [ "B", "C" ] }); + const expected = [ [ 2, 3 ], [ 5, 6 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after selecting row index", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ 0, 1 ] }); + + const colDf = df.loc({ "rows": [ "1" ], "columns": [ "B" ] }); + const expected = [ [ 5 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after selecting with single row index", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "0", "1" ] }); + + const colDf = df.loc({ "rows": [ `"1"` ], "columns": [ "B", "C" ] }); + const expected = [ [ 5, 6 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after selecting with single column index", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "0", "1" ] }); + + const colDf = df.loc({ "rows": [ `"0"` ], "columns": [ "A" ] }); + const expected = [ [ 1 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row and column slice", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "0", "1", "2", "3" ] }); + + const colDf = df.loc({ "rows": [ `'0':'2'` ], "columns": [ "B:C" ] }); + const expected = [ [ 2 ], [ 5 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row slice", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.loc({ "rows": [ `0:2` ], "columns": [ "B", "C" ] }); + const expected = [ [ 2, 3 ], [ 5, 6 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it(`check data after column slice ["A:C"]`, function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols, index: [ "0", "1", "2", "3" ] }); + + const colDf = df.loc({ "rows": [ "0", "1" ], "columns": [ "A:C" ] }); + const expected = [ [ 1, 2 ], [ 4, 5 ] ]; + assert.deepEqual(colDf.values, expected); + + }); + it("check data after numeric row slice", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.loc({ "rows": [ 0, 1 ], "columns": [ "A:C" ] }); + const expected = [ [ 1, 2 ], [ 4, 5 ] ]; + assert.deepEqual(colDf.values, expected); + + }); + it("loc by single string index", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + + const df = new dfd.DataFrame(data, { index: [ "a", "b", "c", "d" ] }); + const subDf = df.loc({ rows: [ `"a"` ], columns: [ "Name", "Count" ] }); + const expected = [ [ 'Apples', 21 ] ]; + assert.deepEqual(subDf.values, expected); + + }); + + it("loc by slice string index", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + + const df = new dfd.DataFrame(data, { index: [ "a", "b", "c", "d" ] }); + const subDf = df.loc({ rows: [ `"a":"c"` ], columns: [ "Name", "Count" ] }); + const expected = [ [ "Apples", 21 ], [ "Mango", 5 ] ]; + assert.deepEqual(subDf.values, expected); + + }); + + + }); + + describe("DataFrame iloc", function () { + + it("throw error for wrong row index (array format)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "rows": [ 0, 1, 3 ] }); + }, + Error, + "Invalid row parameter: Specified index 3 cannot be bigger than index length 2"); + }); + + it("throw error for wrong row index (string slice format)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "rows": [ "1:5" ] }); + }, + Error, + "row slice [end] index cannot be bigger than 2"); + }); + + it("throw error for wrong column index (array format)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "columns": [ 1, 4 ] }); + }, + Error, + "Invalid column parameter: Specified index 4 cannot be bigger than index length 3"); + }); + + it("throw error for wrong column index (string slice format)", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "columns": [ "A:C" ] }); + }, + Error, + "Invalid column split parameter. Split parameter must be a number"); + }); + + it("iloc works for {row: [0, 1], column: [1, 2]}", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [ 0, 1 ], "columns": [ 1, 2 ] }); + const expected = [ [ 2, 3 ], [ 5, 6 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + + it(`iloc works for { "rows": [1], "columns": [1, 2] }`, function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const colDf = df.iloc({ "rows": [ 1 ], "columns": [ 1, 2 ] }); + const expected = [ [ 5, 6 ] ]; + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row and column slice", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [ "0:2" ], "columns": [ "1:2" ] }); + const expected = [ [ 2 ], [ 5 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row slice", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [ "0:2" ], "columns": [ 1, 2 ] }); + const expected = [ [ 2, 3 ], [ 5, 6 ] ]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after column slice", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [ 0, 1, 2 ], "columns": [ "1:2" ] }); + const expected = [ [ 2 ], [ 5 ], [ 30 ] ]; + assert.deepEqual(colDf.values, expected); + + }); + it("Return all columns if columns parameter is not specified", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [ 0, 1, 2 ] }); + const expected = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ] ]; + assert.deepEqual(colDf.values, expected); + + }); + it("Return all rows if rows parameter is not specified", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "columns": [ "1:2" ] }); + const expected = [ [ 2 ], [ 5 ], [ 30 ], [ 89 ] ]; + assert.deepEqual(colDf.values, expected); + + }); + it("column slice starting with 0 and returning a single result works", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ], + "index": [ 1, 2, 3, 4 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: [ "2:3" ], columns: [ "0:1" ] }); + const result = [ [ "Banana" ] ]; + assert.deepEqual(subDf.values, result); + + }); + it("column slice with format '0:' works", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: [ "2:3" ], columns: [ "0:" ] }); + const result = [ [ "Banana", 30, 40 ] ]; + assert.deepEqual(subDf.values, result); + + }); + it("column slice with format ':2' works", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: [ "2:3" ], columns: [ ":2" ] }); + const result = [ [ "Banana", 30 ] ]; + assert.deepEqual(subDf.values, result); + + }); + it("row slice with format ':2' works", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: [ ":2" ], columns: [ ":1" ] }); + const result = [ [ 'Apples' ], [ 'Mango' ] ]; + assert.deepEqual(subDf.values, result); + + }); + it("row slice with format '1:' works", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: [ ":2" ], columns: [ ":2" ] }); + const result = [ [ 'Apples', 21 ], [ 'Mango', 5 ] ]; + assert.deepEqual(subDf.values, result); + + }); + + }); + + describe("toString", function () { + it("Prints a DataFrame to console", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + df.print(); + }); + it("User config works when printing a DataFrame to console", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data, { + config: { + tableDisplayConfig: { + header: { + alignment: 'center', + content: 'THE HEADER\nThis is the table about something' + } + } + } + }); + df.print(); + }); + it("Long columns are properly truncated before printing", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ], + "Name2": [ "Apples", "Mango", "Banana", "Pear" ], + "Count2": [ 21, 5, 30, 10 ], + "Price2": [ 200, 300, 40, 250 ], + "Name3": [ "Apples", "Mango", "Banana", "Pear" ], + "Count3": [ 21, 5, 30, 10 ], + "Price3": [ 200, 300, 40, 250 ], + "Name4": [ "Apples", "Mango", "Banana", "Pear" ], + "Count4": [ 21, 5, 30, 10 ], + "Price4": [ 200, 300, 40, 250 ], + "Name5": [ "Apples", "Mango", "Banana", "Pear" ], + "Count5": [ 21, 5, 30, 10 ], + "Price6": [ 200, 300, 40, 250 ], + "Name7": [ "Apples", "Mango", "Banana", "Pear" ], + "Count7": [ 21, 5, 30, 10 ], + "Price7": [ 200, 300, 40, 250 ], + "Name8": [ "Apples", "Mango", "Banana", "Pear" ], + "Count8": [ 21, 5, 30, 10 ], + "Price8": [ 200, 300, 40, 250 ], + "Name9": [ "Apples", "Mango", "Banana", "Pear" ], + "Count9": [ 21, 5, 30, 10 ], + "Price9": [ 200, 300, 40, 250 ], + "Name10": [ "Apples", "Mango", "Banana", "Pear" ], + "Count10": [ 21, 5, 30, 10 ], + "Price10": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + df.print(); + }); + + it("Long rows are automatically truncated", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear", "Apples", "Mango", "Banana", "Pear", "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10, 21, 5, 30, 10, 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250, 200, 300, 40, 250, 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + df.print(); + }); + }); + + describe("add", function () { + it("Return Addition of DataFrame with a single Number", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.add(2).values, [ [ 2, 4, 6 ], [ 362, 182, 362 ] ]); + }); + it("Return addition of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.add(sf).values, [ [ 1, 4, 5 ], [ 361, 182, 361 ] ]); + }); + it("Return addition of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = [ 1, 2, 1 ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.add(sf).values, [ [ 1, 4, 5 ], [ 361, 182, 361 ] ]); + }); + it("Return addition of a DataFrame with a Series along axis 0", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.add(sf, { axis: 0 }).values, [ [ 1, 3, 5 ], [ 362, 182, 362 ] ]); + }); + it("Return addition of a DataFrame with a Array along axis 0", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ] ]; + const sf = [ 1, 2 ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.add(sf, { axis: 0 }).values, [ [ 1, 3, 5 ], [ 362, 182, 362 ] ]); + }); + it("Return addition of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.add(df2).values, [ [ 1, 4, 8 ], [ 370, 185, 360 ] ]); + }); + it("Return addition of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.add(df2).values, [ [ 1, 4, 8 ], [ 370, 185, 360 ] ]); + }); + it("Return addition of a DataFrame with a Series along default axis 1 (inplace)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + df.add(sf, { axis: 1, inplace: true }); + assert.deepEqual(df.values, [ [ 1, 4, 5 ], [ 361, 182, 361 ] ]); + }); + + it("Return addition of a DataFrame with a DataFrame along axis 0 (inplace)", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + df1.add(df2, { axis: 0, inplace: true }); + assert.deepEqual(df1.values, [ [ 1, 4, 8 ], [ 370, 185, 360 ] ]); + }); + it("Adds work for DataFrame with undefined and null values", function () { + const df1 = new dfd.DataFrame([ [ undefined, 2, 4 ], [ 360, NaN, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + df1.add(df2, { axis: 0, inplace: true }); + assert.deepEqual(df1.values, [ [ NaN, 4, 8 ], [ 370, NaN, 360 ] ]); + }); + + }); + + describe("sub", function () { + it("Return subtraction of DataFrame with a single Number", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.sub(2).values, [ [ -2, 0, 2 ], [ 358, 178, 358 ] ]); + }); + it("Return subtraction of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.sub(sf).values, [ [ -1, 0, 3 ], [ 359, 178, 359 ] ]); + }); + it("Return subtraction of a DataFrame with a Series along axis 0", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.sub(sf, { axis: 0 }).values, [ [ -1, 1, 3 ], [ 358, 178, 358 ] ]); + }); + it("Return subtraction of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.sub(df2).values, [ [ -1, 0, 0 ], [ 350, 175, 360 ] ]); + }); + it("Return subtraction of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.sub(df2).values, [ [ -1, 0, 0 ], [ 350, 175, 360 ] ]); + }); + + }); + + describe("mul", function () { + it("Return multiplication of DataFrame with a single Number", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mul(2).values, [ [ 0, 4, 8 ], [ 720, 360, 720 ] ]); + }); + it("Return multiplication of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mul(sf).values, [ [ 0, 4, 4 ], [ 360, 360, 360 ] ]); + }); + it("Return multiplication of a DataFrame with a Series along axis 0", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mul(sf, { axis: 0 }).values, [ [ 0, 2, 4 ], [ 720, 360, 720 ] ]); + }); + it("Return multiplication of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.mul(df2).values, [ [ 0, 4, 16 ], [ 3600, 900, 0 ] ]); + }); + it("Return multiplication of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.mul(df2, { axis: 0 }).values, [ [ 0, 4, 16 ], [ 3600, 900, 0 ] ]); + }); + + }); + + describe("div", function () { + it("Return division of DataFrame with a single Number", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.div(2).values, [ [ 0, 1, 2 ], [ 180, 90, 180 ] ]); + }); + it("Return division of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.div(sf).values, [ [ 0, 1, 4 ], [ 360, 90, 360 ] ]); + }); + it("Return division of a DataFrame with a Series along axis 0", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const sf = new dfd.Series([ 1, 2 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.div(sf, { axis: 0 }).values, [ [ 0, 2, 4 ], [ 180, 90, 180 ] ]); + }); + it("Return division of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.div(df2).values, [ [ 0, 1, 1 ], [ 36, 36, Infinity ] ]); + }); + it("Return division of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.div(df2).values, [ [ 0, 1, 1 ], [ 36, 36, Infinity ] ]); + }); + + }); + + //So CI test result varies depending on where it is run. This is difficult to test. + //so I'm commenting it out. See https://github.com/javascriptdata/danfojs/issues/329 + // describe("pow", function () { + // it("Return exponential of DataFrame with a single Number", function () { + // const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + // const df = new dfd.DataFrame(data); + // assert.deepEqual(df.pow(2).values, [ [ 0, 4, 16 ], [ 129600, 32400, 129600 ] ]); + // }); + // it("Return exponential of a DataFrame with a Series along default axis 1", function () { + // const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + // const sf = new dfd.Series([ 1, 2, 1 ]); + // const df = new dfd.DataFrame(data); + // assert.deepEqual(df.pow(sf).values, [ [ 0, 4, 4 ], [ 360, 32400, 360 ] ]); + // }); + // it("Return exponential of a DataFrame with a Series along axis 0", function () { + // const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + // const sf = new dfd.Series([ 1, 2 ]); + // const df = new dfd.DataFrame(data); + // assert.deepEqual(df.pow(sf, { axis: 0 }).values, [ [ 0, 2, 4 ], [ 129600, 32400, 129600 ] ]); + // }); + // it("Return exponential of a DataFrame with another DataFrame along default axis 1", function () { + // const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 3, 10, 4 ] ]); + // const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + // assert.deepEqual(df1.pow(df2).values, [ [ 0, 4, 256 ], [ 59049, 100000, 1 ] ]); + // }); + // it("Return exponential of a DataFrame with another DataFrame along axis 0", function () { + // const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 3, 10, 4 ] ]); + // const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + // assert.deepEqual(df1.pow(df2, { axis: 0 }).values, [ [ 0, 4, 256 ], [ 59049, 100000, 1 ] ]); + // }); + + // }); + + describe("mod", function () { + it("Return modulus of DataFrame with a single Number", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mod(2).values, [ [ 0, 0, 0 ], [ 0, 0, 0 ] ]); + }); + it("Return modulus of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 31, 15, 360 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mod(sf).values, [ [ 0, 0, 0 ], [ 0, 1, 0 ] ]); + }); + it("Return modulus of a DataFrame with a Series along axis 0", function () { + const data = [ [ 0, 2, 4 ], [ 31, 15, 360 ] ]; + const sf = new dfd.Series([ 1, 2 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mod(sf, { axis: 0 }).values, [ [ 0, 0, 0 ], [ 1, 1, 0 ] ]); + }); + it("Return modulus of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 31, 15, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.mod(df2).values, [ [ 0, 0, 0 ], [ 1, 0, NaN ] ]); + }); + it("Return modulus of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + const df2 = new dfd.DataFrame([ [ 1, 2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual(df1.mod(df2).values, [ [ 0, 0, 0 ], [ 0, 0, NaN ] ]); + }); + + }); + + describe("pctChange", function () { + it("Return same DataFrame if other === 0", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.pctChange(0)).values, [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]); + }); + it("Return difference in percentage of DataFrame with previous row", function () { + const data = [ [ 90 ], [ 900 ], [ 900 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.pctChange(1)).values, [ [ NaN ], [ 9 ], [ 0 ] ]); + }); + it("Return difference in percentage of DataFrame with following row", function () { + const data = [ [ 0, 5, 15 ], [ 10, 10, 10 ], [ 1, 2, 5 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.pctChange(-1)).values, [ [ -1, -0.5, 0.5 ], [ 9, 4, 1 ], [ NaN, NaN, NaN ] ]); + }); + it("Return difference in percentage of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual((df.pctChange(sf)).values, [ [ -1, 0, 3 ], [ 9, 4, 9 ], [ 0, 0, 2 ] ]); + }); + it("Return difference in percentage of a DataFrame with a Series along axis 0", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual((df.pctChange(sf, { axis: 0 })).values, [ [ -1, 1, 3 ], [ 4, 4, 4 ], [ 0, 1, 2 ] ]); + }); + it("Return difference in percentage of a DataFrame with along axis 0 (column-wise), previous column", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.pctChange(1, { axis: 0 })).values, [ [ NaN, -1, 1 ], [ NaN, 0, 0 ], [ NaN, 1, 0.5 ] ]); + }); + it("Return difference in percentage of a DataFrame with along axis 0 (column-wise), following column", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 8 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.pctChange(-1, { axis: 0 })).values, [ [ -1, -0.5, NaN ], [ 0, 0, NaN ], [ -0.5, -0.75, NaN ] ]); + }); + it("Return difference in percentage of a DataFrame with another DataFrame along default axis 1", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 3, 10, 4 ] ]); + const df2 = new dfd.DataFrame([ [ -1, -2, 4 ], [ 6, 5, 0 ] ]); + assert.deepEqual((df1.pctChange(df2)).values, [ [ -1, -2, 0 ], [ -0.5, 1, -1 ] ]); + }); + it("Throw error if DataFrame for pctChange contains string", function () { + const df = new dfd.DataFrame([ [ "words", "words", "words" ], [ "words", "words", "words" ] ]); + assert.throws(() => { + df.pctChange(1); + }, Error, "TypeError: pctChange operation is not supported for string dtypes"); + }); + }); + + describe("diff", function () { + it("Return same DataFrame if other === 0", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.diff(0)).values, [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]); + }); + it("Return difference of DataFrame with previous row", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.diff(1)).values, [ [ NaN, NaN, NaN ], [ 10, 8, 6 ], [ -9, -8, -7 ] ]); + }); + it("Return difference of DataFrame with following row", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.diff(-1)).values, [ [ -10, -8, -6 ], [ 9, 8, 7 ], [ NaN, NaN, NaN ] ]); + }); + it("Return difference of a DataFrame with a Series along default axis 1", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual((df.diff(sf)).values, [ [ -1, 0, 3 ], [ 9, 8, 9 ], [ 0, 0, 2 ] ]); + }); + it("Return difference of a DataFrame with a Series along axis 0", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const sf = new dfd.Series([ 1, 2, 1 ]); + const df = new dfd.DataFrame(data); + assert.deepEqual((df.diff(sf, { axis: 0 })).values, [ [ -1, 1, 3 ], [ 8, 8, 8 ], [ 0, 1, 2 ] ]); + }); + it("Return difference of a DataFrame with along axis 0 (column-wise), previous column", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.diff(1, { axis: 0 })).values, [ [ NaN, 2, 2 ], [ NaN, 0, 0 ], [ NaN, 1, 1 ] ]); + }); + it("Return difference of a DataFrame with along axis 0 (column-wise), following column", function () { + const data = [ [ 0, 2, 4 ], [ 10, 10, 10 ], [ 1, 2, 3 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual((df.diff(-1, { axis: 0 })).values, [ [ -2, -2, NaN ], [ 0, 0, NaN ], [ -1, -1, NaN ] ]); + }); + it("Return difference of a DataFrame with another DataFrame along default axis 1", function () { + const df1 = new dfd.DataFrame([ [ 0, 2, 4 ], [ 3, 10, 4 ] ]); + const df2 = new dfd.DataFrame([ [ -1, -2, 4 ], [ 10, 5, 0 ] ]); + assert.deepEqual((df1.diff(df2)).values, [ [ 1, 4, 0 ], [ -7, 5, 4 ] ]); + }); + it("Throw error if DataFrame for diff contains string", function () { + const df = new dfd.DataFrame([ [ "words", "words", "words" ], [ "words", "words", "words" ] ]); + assert.throws(() => { + df.diff(1); + }, Error, "TypeError: diff operation is not supported for string dtypes"); + }); + }); + + describe("mean", function () { + it("Returns the mean of a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data, { columns: [ "col1", "col2", "col3" ], index: [ "row1", "row2" ] }); + assert.deepEqual(df.mean().values, [ 2, 300 ]); + assert.deepEqual(df.mean().index, [ "row1", "row2" ]); + }); + it("Return mean of a DataFrame along axis 1 (column)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mean({ "axis": 1 }).values, [ 2, 300 ]); + }); + it("Removes NaN before calculating mean of a DataFrame", function () { + const data = [ [ 11, 20, 3 ], + [ NaN, 15, 6 ], + [ 2, 30, 40 ], + [ 2, 89, 78 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mean({ "axis": 1 }).values, [ 11.333333333333334, 10.5, 24, 56.333333333333336 ]); + }); + it("Return mean of a DataFrame along axis 0 (column)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mean({ "axis": 0 }).values, [ 180, 91, 182 ]); + }); + it("Removes NaN before calculating mean of a DataFrame along axis 0 (column)", function () { + const data = [ [ 11, 20, 3 ], + [ NaN, 15, 6 ], + [ 2, 30, 40 ], + [ 2, 89, 78 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mean({ "axis": 0 }).values, [ 5, 38.5, 31.75 ]); + }); + it("Throws error on wrong axis specified", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.throws(() => df.mean({ "axis": 2 }), Error, "ParamError: Axis must be 0 or 1"); + }); + }); + + describe("median", function () { + it("Returns the median of a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.median().values, [ 2, 360 ]); + }); + it("Return median of a DataFrame along axis 0 (row)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.median({ "axis": 0 }).values, [ 180, 91, 182 ]); + }); + + }); + + describe("mode", function () { + it("Returns the mode of a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4, 2 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mode().values, [ 2, 360 ]); + }); + it("Returns the mode of a DataFrame with keep set to 1", function () { + const data = [ [ 0, 2, 4, 2, 4 ], [ 360, 180, 360, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mode({ keep: 1 }).values, [ 4, 360 ]); + }); + it("Returns mode of a DataFrame along axis 0 (row)", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ], + [ 0, 2, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mode({ "axis": 0 }).values, [ 0, 2, 360 ]); + }); + it("Returns mode of a DataFrame along axis 0 for objects", function () { + const data = { "col1": [ 0, 2, 4, 0 ], "col2": [ 360, 180, 360, 360 ] }; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.mode({ "axis": 0 }).values, [ 0, 360 ]); + }); + + }); + + describe("min", function () { + it("Returns the minimum values in a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.min().values, [ 0, 180 ]); + }); + it("Returns the minimum values of a DataFrame along axis 0 (row)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.min({ "axis": 0 }).values, [ 0, 2, 4 ]); + }); + it("Returns the minimum values of a DataFrame along axis 0 (row) using TFJS", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data, { config: { useTfjsMathFunctions: true } }); + assert.deepEqual(df.min({ "axis": 0 }).values, [ 0, 2, 4 ]); + }); + it("Returns the minimum values in a DataFrame-Default axis 1 using TFJS", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data, { config: { useTfjsMathFunctions: true } }); + assert.deepEqual(df.min().values, [ 0, 180 ]); + }); + + }); + + describe("max", function () { + it("Returns the maximum values in a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.max().values, [ 4, 360 ]); + }); + it("Returns the maximum values of a DataFrame along axis 0 (row)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.max({ "axis": 0 }).values, [ 360, 180, 360 ]); + }); + + }); + + describe("std", function () { + it("Returns the standard deviations of values in a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.std().values, [ 2, 103.92304845413264 ]); + }); + it("Return the standard deviations of values of a DataFrame along axis 0 (row)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.std({ axis: 0 }).values, [ 254.55844122715712, 125.86500705120545, 251.7300141024109 ]); + }); + + + }); + + describe("var", function () { + it("Returns the variance of values in a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.var().values, [ 4, 10800 ]); + }); + it("Return the variance of values of a DataFrame along axis 0 (row)", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.var({ axis: 0 }).values, [ 64800, 15842, 63368 ]); + }); + + + }); + + describe("describe", function () { + it("Returns descriptive statistics of columns in a DataFrame created from an array", function () { + const data = [ [ 0, 2, 4, "a" ], + [ 360, 180, 360, "b" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data); + const res = [ [ 3, 3, 3 ], [ 120.66666666666667, 62, 123.33333333333333 ], + [ 207.27115895206774, 102.19589032832974, 204.961785055979 ], + [ 0, 2, 4 ], [ 2, 4, 6 ], + [ 360, 180, 360 ], + [ 42961.33333333333, 10444, 42009.333333333336 ] ]; + assert.deepEqual(df.describe().values, res); + }); + it("Returns descriptive statistics of columns in a DataFrame created from an Object", function () { + const data = { + "col1": [ 0, 2, 4 ], + "col2": [ 360, 180, 360 ], + "col3": [ 2, 4, 6 ], + "col4": [ "boy", "girl", "man" ], + "col5": [ "apple", "car", "bee" ] + }; + const df = new dfd.DataFrame(data); + + const res = [ [ 3, 3, 3 ], [ 2, 300, 4 ], + [ 2, 103.92304845413264, 2 ], + [ 0, 180, 2 ], [ 2, 360, 4 ], + [ 4, 360, 6 ], + [ 4, 10800, 4 ] ]; + assert.deepEqual(df.describe().values, res); + }); + + }); + + describe("count", function () { + it("Returns the count of non-nan values in a DataFrame (Default axis is [1:column])", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180.1, 360.11 ], + [ NaN, 2, 4 ], + [ 360, undefined, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.count().values, [ 3, 3, 2, 2 ]); + }); + it("Return the count of non NaN values of a DataFrame along axis 0", function () { + const data = [ [ 0, 2, 4, NaN ], + [ 360, undefined, 360, 70 ] ]; + const df = new dfd.DataFrame(data); + assert.deepEqual(df.count({ axis: 0 }).values, [ 2, 1, 2, 1 ]); + }); + + }); + + describe("round", function () { + it("Rounds values in a DataFrame to 3dp", function () { + const data = [ [ 10.1, 2.092, 4.23 ], [ 360.232244, 180.0190290, 36.902612 ] ]; + const df = new dfd.DataFrame(data); + const expected = [ [ 10.1, 2.092, 4.23 ], [ 360.232, 180.0190, 36.903 ] ]; + assert.deepEqual(df.round(3).values, expected); + }); + it("Rounds values in a DataFrame to 1dp, inplace", function () { + const data = [ [ 10.1, 2.092, 4.23 ], [ 360.232244, 180.0190290, 36.902612 ] ]; + const df = new dfd.DataFrame(data); + const expected = [ [ 10.1, 2.1, 4.2 ], [ 360.2, 180.0, 36.9 ] ]; + df.round(1, { inplace: true }); + assert.deepEqual(df.values, expected); + }); + it("Rounds values in a DataFrame to 3dp with missing values", function () { + const data = [ [ 10.1, 2.092, NaN ], [ 360.232244, undefined, 36.902612 ] ]; + const df = new dfd.DataFrame(data); + const expected = [ [ 10.1, 2.092, NaN ], [ 360.232, undefined, 36.903 ] ]; + assert.deepEqual(df.round(3, { axis: 0 }).values, expected); + }); + + }); + + describe("sortValues", function () { + it("Sort values in DataFrame by specified column in ascending order (Default)", function () { + const data = [ [ 0, 2, 4, "a" ], + [ 360, 180, 360, "b" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ], index: [ "a", 1, "c" ] }); + df.sortValues("col1", { inplace: true }); + const expected = [ [ 0, 2, 4, "a" ], [ 2, 4, 6, "c" ], [ 360, 180, 360, "b" ] ]; + assert.deepEqual(df.values, expected); + assert.deepEqual(df.index, [ "a", "c", 1 ]); + + }); + + it("Sort values in DataFrame by specified column in ascending order (Default)", function () { + const data = [ [ 0, 2, 4, "a" ], + [ 360, 180, 1, "b" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ] }); + const df_sort = df.sortValues("col3"); + const expected = [ [ 360, 180, 1, "b" ], [ 0, 2, 4, "a" ], [ 2, 4, 6, "c" ] ]; + assert.deepEqual(df_sort.values, expected); + assert.deepEqual(df_sort.index, [ 1, 0, 2 ]); + + }); + it("Sort values in DataFrame by specified column in descending order", function () { + const data = [ [ 0, 2, 4, "a" ], + [ 360, 180, 360, "b" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ] }); + const expected = [ [ 360, 180, 360, "b" ], [ 2, 4, 6, "c" ], [ 0, 2, 4, "a" ] ]; + assert.deepEqual(df.sortValues("col1", { "ascending": false }).values, expected); + }); + + it("Sort values in DataFrame by specified column in descending order (second col)", function () { + const data = [ [ 0, 2, 4, "a" ], + [ 360, 180, 1, "b" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ] }); + const expected = [ [ 2, 4, 6, "c" ], [ 0, 2, 4, "a" ], [ 360, 180, 1, "b" ] ]; + assert.deepEqual(df.sortValues("col3", { "ascending": false }).values, expected); + }); + it("Sort values in DataFrame by specified column containing alpha(numeric) values", function () { + const data = [ [ 0, 2, 4, "a" ], + [ 360, 180, 1, "b" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ] }); + const expected = [ [ 2, 4, 6, 'c' ], [ 360, 180, 1, 'b' ], [ 0, 2, 4, 'a' ] ]; + assert.deepEqual(df.sortValues("col4", { "ascending": false }).values, expected); + }); + it("Sort duplicate DataFrame with duplicate columns", function () { + + const data = { + "A": [ 1, 2, 3, 4, 5, 3, 5, 6, 4, 5, 3, 4 ], + "B": [ 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4 ] + }; + + const df = new dfd.DataFrame(data); + const expected = [ [ 1, 2 ], + [ 2, 3 ], + [ 3, 4 ], + [ 3, 7 ], + [ 3, 3 ], + [ 4, 5 ], + [ 4, 1 ], + [ 4, 4 ], + [ 5, 6 ], + [ 5, 8 ], + [ 5, 2 ], + [ 6, 9 ] ]; + assert.deepEqual(df.sortValues("A", { "ascending": true }).values, expected); + }); + + it("sort index in descending order and retains index", function () { + let data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + let df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ], index: [ "b", "a", "c" ] }); + let df2 = df.sortIndex({ ascending: false }); + let rslt = [ "c", "b", "a" ]; + assert.deepEqual(df2.index, rslt); + }); + }); + + describe("copy", function () { + it("Makes a deep copy of DataFrame", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + const df_copy = df.copy(); + assert.deepEqual(df_copy.values, [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]); + }); + it("Confirms child copy modification does not affect parent DataFrame", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + const df_copy = df.copy(); + df_copy.addColumn("col_new", [ "boy", "girl" ], { inplace: true }); + assert.notDeepEqual(df_copy.values, df.values); + assert.notDeepEqual(df_copy, df); + }); + + }); + + + describe("setIndex", function () { + it("Sets the index of a DataFrame created from an Object inplace", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const df = new dfd.DataFrame(data); + df.setIndex({ index: [ "one", "two", "three" ], inplace: true }); + assert.deepEqual(df.index, [ "one", "two", "three" ]); + }); + it("Sets the index of a DataFrame from column name", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const df = new dfd.DataFrame(data); + const df_new = df.setIndex({ column: "alpha" }); + assert.deepEqual(df_new.index, [ "A", "B", "C" ]); + }); + it("Sets the index of a DataFrame from column name", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const df = new dfd.DataFrame(data); + const df_new = df.setIndex({ column: "alpha" }); + assert.deepEqual(df_new.index, [ "A", "B", "C" ]); + }); + it("Sets the index of a DataFrame from column name and drop column data (inplace)", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const df = new dfd.DataFrame(data); + df.setIndex({ column: "alpha", drop: true, inplace: true }); + assert.deepEqual(df.index, [ "A", "B", "C" ]); + assert.deepEqual(df.columns, [ "count" ]); + assert.deepEqual(df.values, [ [ 1 ], [ 2 ], [ 3 ] ]); + assert.throws(() => df["alpha"], Error, + "ParamError: Column not found!. Column name must be one of count" + ); + }); + it("Throw error if index and column not passed", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const df = new dfd.DataFrame(data); + assert.throws(() => df.setIndex({ drop: true, inplace: true }), Error, + "ParamError: must specify either index or column" + ); + }); + + it("Sets the index of a DataFrame from column name and drop column data", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const df = new dfd.DataFrame(data); + const df_new = df.setIndex({ column: "alpha", drop: true }); + assert.deepEqual(df_new.index, [ "A", "B", "C" ]); + assert.deepEqual(df_new.columns, [ "count" ]); + assert.deepEqual(df_new.values, [ [ 1 ], [ 2 ], [ 3 ] ]); + assert.deepEqual(df_new["alpha"], undefined); + }); + it("Sets the index of a DataFrame created from an Array inplace", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ], [ 0, 2, 4 ], [ 360, 180, 360 ], [ 0, 2, 4 ] ]; + const df = new dfd.DataFrame(data); + df.setIndex({ index: [ "one", "two", "three", "four", "five" ], "inplace": true }); + assert.deepEqual(df.index, [ "one", "two", "three", "four", "five" ]); + }); + it("Throws error on wrong row length", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.throws(() => df.setIndex({ index: [ "one", "two", "three", "four", "five" ], "inplace": true }), Error, + "ParamError: index must be the same length as the number of rows" + ); + }); + it("Throws error on column not found", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ] ]; + const df = new dfd.DataFrame(data); + assert.throws(() => df.setIndex({ column: "alpha", inplace: true }), Error, + "ParamError: column not found in column names" + ); + }); + + }); + + describe("resetIndex", function () { + it("Resets the index of a DataFrame created from an Object", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const df = new dfd.DataFrame(data, { index: [ "one", "two", "three" ] }); + const df_reset = df.resetIndex(); + assert.deepEqual(df_reset.index, [ 0, 1, 2 ]); + }); + it("Resets the index of a DataFrame created from an Array inplace", function () { + const data = [ [ 0, 2, 4 ], [ 360, 180, 360 ], [ 0, 2, 4 ], [ 360, 180, 360 ], [ 0, 2, 4 ] ]; + const df = new dfd.DataFrame(data, { index: [ "one", "two", "three", "four", "five" ] }); + df.resetIndex({ inplace: true }); + assert.deepEqual(df.index, [ 0, 1, 2, 3, 4 ]); + }); + }); + + + describe("apply", function () { + + it("Apply an aggregation function to a DataFrame axis = 1", function () { + const data = [ [ 0, 2, 4 ], + [ 3, 2, 2 ], + [ 0, 2, 1 ] ]; + const df = new dfd.DataFrame(data); + + const sum = (x) => { + return x.reduce((a, b) => a + b, 0); + }; + const expected = [ 6, 7, 3 ]; + const dfApply = df.apply(sum, { axis: 1 }); + assert.deepEqual(dfApply.values, expected); + assert.deepEqual(dfApply.index, [ 0, 1, 2 ]); + + }); + it("Apply an aggregation function to a DataFrame axis = 0", function () { + const data = [ [ 0, 2, 4 ], + [ 3, 2, 2 ], + [ 0, 2, 1 ] ]; + const df = new dfd.DataFrame(data, { columns: [ "col1", "col2", "col3" ] }); + + const sum = (x) => { + return x.reduce((a, b) => a + b, 0); + }; + const expected = [ 3, 6, 7 ]; + const dfApply = df.apply(sum, { axis: 0 }); + assert.deepEqual(dfApply.values, expected); + assert.deepEqual(dfApply.index, [ "col1", "col2", "col3" ]); + }); + + }); + + describe("applyMap", function () { + it("Apply an element-wise function to a DataFrame", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ], + [ 0, 2, 4 ] ]; + const df = new dfd.DataFrame(data); + + const add = (x) => { + return x + 1000; + }; + const expected = [ [ 1000, 1002, 1004 ], [ 1360, 1180, 1360 ], [ 1000, 1002, 1004 ] ]; + const dfApply = df.applyMap(add); + assert.deepEqual(dfApply.values, expected); + }); + + it("Apply an element-wise function to a DataFrame", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ], + [ 0, 2, 4 ], + [ 0, 2, 4 ] ]; + const df = new dfd.DataFrame(data); + const add = (x) => { + return x + 1000; + }; + const expected = [ [ 1000, 1002, 1004 ], [ 1360, 1180, 1360 ], [ 1000, 1002, 1004 ], [ 1000, 1002, 1004 ] ]; + const dfApply = df.applyMap(add); + assert.deepEqual(dfApply.values, expected); + }); + + it("Apply an element-wise function to a DataFrame inplace", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ], + [ 0, 2, 4 ] ]; + const df = new dfd.DataFrame(data); + + const add = (x) => { + return x + 1000; + }; + const expected = [ [ 1000, 1002, 1004 ], [ 1360, 1180, 1360 ], [ 1000, 1002, 1004 ] ]; + df.applyMap(add, { inplace: true }); + assert.deepEqual(df.values, expected); + }); + + it("Apply an element-wise function to a DataFrame inplace", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ], + [ 0, 2, 4 ], + [ 0, 2, 4 ] ]; + const df = new dfd.DataFrame(data); + + const add = (x) => { + return x + 1000; + }; + const expected = [ [ 1000, 1002, 1004 ], [ 1360, 1180, 1360 ], [ 1000, 1002, 1004 ], [ 1000, 1002, 1004 ] ]; + df.applyMap(add, { inplace: true }); + assert.deepEqual(df.values, expected); + }); + }); + + describe("column", function () { + it("Obtain a column from a dataframe created from object", function () { + const data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + const options = { columns: [ "Gender", "count" ] }; + const df = new dfd.DataFrame(data, options); + const expected = df.column("count"); + const rslt_data = [ 1, 2, 3 ]; + assert.deepEqual(expected.values, rslt_data); + }); + it("Obtain a column from a dataframe", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const expected = df.column("C"); + const rslt_data = [ 3, 6, 40, 78 ]; + assert.deepEqual(expected.values, rslt_data); + }); + it("Throw Error for wrong column", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + assert.throws(() => { df.column("D"); }, Error, "ParamError: Column not found!. Column name must be one of A,B,C"); + + }); + }); + + + describe("dropNa", function () { + it("drop NaNs along axis 0", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ], + [ NaN, 180, 360 ] ]; + const column = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_val = [ [ 2, 4 ], + [ 180, 360 ], + [ 180, 360 ] ]; + assert.deepEqual(df.dropNa({ axis: 0 }).values, df_val); + + }); + it("drop NaNs along axis 1", function () { + const data = [ [ 0, 2, 4 ], + [ 360, 180, 360 ], + [ NaN, 180, 360 ] ]; + const column = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_val = [ [ 0, 2, 4 ], + [ 360, 180, 360 ] ]; + assert.deepEqual(df.dropNa({ axis: 1 }).values, df_val); + + }); + it("drop NaNs along axis 1", function () { + const data = [ [ NaN, 1, 2, 3 ], [ 3, 4, NaN, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_val = [ [ 5, 6, 7, 8 ] ]; + assert.deepEqual(df.dropNa({ axis: 1 }).values, df_val); + + }); + it("drop inplace at axis 0, inplace false ", function () { + const data = [ [ NaN, 1, 2, 3 ], [ 3, 4, NaN, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + + const df_val = [ [ 1, 3 ], [ 4, 9 ], [ 6, 8 ] ]; + + assert.deepEqual(df.dropNa({ axis: 0 }).values, df_val); + + }); + it("drop inplace at axis 0, inplace true ", function () { + const data = [ [ NaN, 1, 2, 3 ], [ 3, 4, NaN, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + + const df_val = [ [ 1, 3 ], [ 4, 9 ], [ 6, 8 ] ]; + df.dropNa({ axis: 0, inplace: true }); + assert.deepEqual(df.values, df_val); + + }); + it("drop inplace at axis 1 at inplace true", function () { + const data = [ [ NaN, 1, 2, 3 ], [ 3, 4, NaN, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + + const df_val = [ [ 5, 6, 7, 8 ] ]; + + df.dropNa({ axis: 1, inplace: true }); + assert.deepEqual(df.values, df_val); + + }); + + it("drop works for undefined values", function () { + let data = [ [ null, 1, 2, 3 ], [ 3, 4, undefined, 9 ], [ 5, 6, 7, 8 ] ]; + let column = [ "A", "B", "C", "D" ]; + let df = new dfd.DataFrame(data, { columns: column }); + + let df_val = [ [ 5, 6, 7, 8 ] ]; + + df.dropNa({ axis: 1, inplace: true }); + assert.deepEqual(df.values, df_val); + + }); + }); + + describe("isNa", function () { + + it("check if values are empty (element-wise", function () { + const data = [ [ NaN, 1, 2, 3 ], [ 3, 4, undefined, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + + const df_val = [ + [ true, false, false, false ], + [ false, false, true, false ], + [ false, false, false, false ] + ]; + const dfNew = df.isNa(); + assert.deepEqual(dfNew.values, df_val); + assert.deepEqual(dfNew.dtypes, [ "boolean", "boolean", "boolean", "boolean" ]); + assert.deepEqual(dfNew.columns, column); + }); + }); + + describe("fillNa", function () { + + it("replace all NaN value inplace", function () { + const data = [ [ NaN, 1, 2, 3 ], [ 3, 4, NaN, 9 ], [ 5, 6, 7, 8 ] ]; + const columns = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const expected = [ [ -999, 1, 2, 3 ], [ 3, 4, -999, 9 ], [ 5, 6, 7, 8 ] ]; + df.fillNa(-999, { inplace: true }); + assert.deepEqual(df.values, expected); + }); + it("replace all undefined value", function () { + const data = [ [ undefined, 1, 2, 3 ], [ 3, 4, undefined, 9 ], [ 5, 6, 7, 8 ] ]; + const columns = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const expected = [ [ -999, 1, 2, 3 ], [ 3, 4, -999, 9 ], [ 5, 6, 7, 8 ] ]; + + const df_filled = df.fillNa(-999); + assert.deepEqual(df_filled.values, expected); + }); + it("replace all undefined value with 0 works", function () { + const data = [ [ undefined, 1, 2, 3 ], [ 3, 4, null, 9 ], [ 5, NaN, 7, 8 ] ]; + const columns = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const expected = [ [ 0, 1, 2, 3 ], [ 3, 4, 0, 9 ], [ 5, 0, 7, 8 ] ]; + + const df_filled = df.fillNa(0); + assert.deepEqual(df_filled.values, expected); + }); + it("Fills only a specified column", function () { + const data = [ [ 1, 2, 3 ], + [ 4, 5, 6 ], + [ 20, NaN, 40 ], + [ 39, NaN, NaN ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const expected = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 2, 40 ], [ 39, 2, NaN ] ]; + const df_filled = df.fillNa([ 2 ], { columns: [ "B" ] }); + + assert.deepEqual(df_filled.values, expected); + }); + it("Fills column with specified values not in place", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ NaN, 20, 40 ], [ NaN, -1, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const new_vals = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ -2, 20, 40 ], [ -2, -1, 78 ] ]; + const df_filled = df.fillNa([ -2 ], { columns: [ "A" ] }); + + assert.deepEqual(df_filled.values, new_vals); + }); + + it("Fills a list of columns with specified values", function () { + const data = [ [ 1, undefined, 3 ], [ 4, undefined, 6 ], [ NaN, "boy", 40 ], [ NaN, "girl", NaN ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const new_vals = [ [ 1, "girl", 3 ], [ 4, "girl", 6 ], [ 200, "boy", 40 ], [ 200, "girl", NaN ] ]; + const df_filled = df.fillNa([ 200, "girl" ], { columns: [ "A", "B" ] }); + assert.deepEqual(df_filled.values, new_vals); + }); + it("Fills a list of columns with specified values inplace", function () { + const data = [ [ 1, undefined, 3 ], [ 4, undefined, 6 ], [ NaN, "boy", 40 ], [ NaN, "girl", 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const new_vals = [ [ 1, "girl", 3 ], [ 4, "girl", 6 ], [ 200, "boy", 40 ], [ 200, "girl", 78 ] ]; + df.fillNa([ 200, "girl" ], { columns: [ "A", "B" ], inplace: true }); + assert.deepEqual(df.values, new_vals); + }); + }); + + describe("selectDtypes", function () { + + it("Returns float columns in a DataFrame", function () { + const data = [ [ 30, 1, 2, "boy" ], [ 3.2, 4, 30, "girl" ], [ 5.09, 6, 7, "cat" ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes([ 'float32' ]); + assert.deepEqual(df_sub.values, [ [ 30 ], [ 3.2 ], [ 5.09 ] ]); + }); + + it("Returns int columns in a DataFrame", function () { + const data = [ [ 30, 1, 2, "boy" ], + [ 3.2, 4, 30, "girl" ], + [ 5.09, 6, 7, "cat" ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes([ 'int32' ]); + assert.deepEqual(df_sub.values, [ [ 1, 2 ], [ 4, 30 ], [ 6, 7 ] ]); + }); + + it("Returns string columns in a DataFrame", function () { + const data = [ [ 30, 1, 2, "boy" ], + [ 3.2, 4, 30, "girl" ], + [ 5.09, 6, 7, "cat" ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes([ 'string' ]); + assert.deepEqual(df_sub.values, [ [ "boy" ], [ "girl" ], [ "cat" ] ]); + }); + + it("Returns string and float columns in a DataFrame", function () { + const data = [ [ 30, 1, 2, "boy" ], + [ 3.2, 4, 30, "girl" ], + [ 5.09, 6, 7, "cat" ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes([ 'string', 'float32' ]); + assert.deepEqual(df_sub.values, [ [ 30, "boy" ], [ 3.2, "girl" ], [ 5.09, "cat" ] ]); + }); + + it("Returns int and float columns in a DataFrame", function () { + const data = [ [ 30, 1, 2, "boy" ], + [ 3.2, 4, 30, "girl" ], + [ 5.09, 6, 7, "cat" ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes([ 'int32', 'float32' ]); + assert.deepEqual(df_sub.values, [ [ 30, 1, 2 ], [ 3.2, 4, 30 ], [ 5.09, 6, 7 ] ]); + }); + }); + + + describe("lt", function () { + it("Returns Less than of DataFrame and other DataFrame (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const data2 = [ [ 100, 450, 590, 5 ], [ 25, 2, 0, 10 ] ]; + + const df = new dfd.DataFrame(data1); + const df2 = new dfd.DataFrame(data2); + const expected = [ [ true, true, true, false ], + [ false, false, false, false ] ]; + assert.deepEqual(df.lt(df2).values, expected); + }); + + it("Return Less than of series and scalar (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const sf = new dfd.DataFrame(data1); + const expected = [ [ true, false, false, true ], + [ true, true, true, true ] ]; + assert.deepEqual(sf.lt(30).values, expected); + }); + it("Return Less than of series and DataFrame along axis 1", function () { + const data1 = [ [ 10, 45, 56, 10 ], + [ 23, 20, 10, 10 ] ]; + const sf = new dfd.Series([ 10, 23, 56, 100 ]); + const df = new dfd.DataFrame(data1); + const expected = [ [ false, false, false, true ], [ false, true, true, true ] ]; + assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); + }); + + it("Return Less than of Array and DataFrame along axis 1", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 23, 20, 10, 10 ] ]; + const sf = [ 10, 23, 56, 100 ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ false, false, false, true ], [ false, true, true, true ] ]; + assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); + }); + it("Return Less than of series and DataFrame along axis 0", function () { + const data1 = [ [ 10, 45, 56, 10 ], + [ 23, 20, 10, 10 ] ]; + const sf = new dfd.Series([ 10, 23 ]); + const df = new dfd.DataFrame(data1); + const expected = [ [ false, false, false, false ], [ false, true, true, true ] ]; + const result = df.lt(sf, { axis: 0 }); + assert.deepEqual(result.values, expected); + }); + + it("Return Less than of Array and DataFrame along axis 0", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 23, 20, 10, 10 ] ]; + const sf = [ 10, 23 ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ false, false, false, false ], [ false, true, true, true ] ]; + const result = df.lt(sf, { axis: 0 }); + assert.deepEqual(result.values, expected); + }); + + }); + + describe("gt", function () { + it("Return Greater than of series and other series (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const data2 = [ [ 100, 450, 590, 5 ], [ 25, 2, 0, 10 ] ]; + + const df = new dfd.DataFrame(data1); + const df2 = new dfd.DataFrame(data2); + const expected = [ [ false, false, false, true ], [ false, true, true, false ] ]; + assert.deepEqual(df.gt(df2).values, expected); + }); + + it("Return Greater than of series scalar (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const sf = new dfd.DataFrame(data1); + const expected = [ [ false, true, true, false ], [ false, false, false, false ] ]; + assert.deepEqual(sf.gt(30).values, expected); + }); + + it("Return Less than of Array and DataFrame scalar along axis 1", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 23, 20, 10, 10 ] ]; + const sf = [ 10, 23, 56, 100 ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ false, true, false, false ], [ true, false, false, false ] ]; + assert.deepEqual(df.gt(sf, { axis: 1 }).values, expected); + }); + it("Return Less than of Array and DataFrame scalar along axis 0", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 23, 20, 10, 10 ] ]; + const sf = [ 10, 23 ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ false, true, true, false ], [ false, false, false, false ] ]; + assert.deepEqual(df.gt(sf, { axis: 0 }).values, expected); + }); + + }); + + describe("le", function () { + it("Return Less than or Equal to of series and other series (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const data2 = [ [ 100, 450, 590, 5 ], [ 25, 2, 0, 10 ] ]; + + const df = new dfd.DataFrame(data1); + const df2 = new dfd.DataFrame(data2); + const expected = [ [ true, true, true, false ], [ true, false, false, true ] ]; + assert.deepEqual(df.le(df2).values, expected); + }); + + it("Return Less than or Equal to of series scalar (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 30, 10 ] ]; + const sf = new dfd.DataFrame(data1); + const expected = [ [ true, false, false, true ], [ true, true, true, true ] ]; + assert.deepEqual(sf.le(30).values, expected); + }); + + }); + + describe("ge", function () { + it("Return Greater than or Equal to of series and other series (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const data2 = [ [ 100, 450, 590, 5 ], [ 25, 2, 0, 10 ] ]; + + const df = new dfd.DataFrame(data1); + const df2 = new dfd.DataFrame(data2); + const expected = [ [ false, false, false, true ], [ true, true, true, true ] ]; + assert.deepEqual(df.ge(df2).values, expected); + }); + + it("Return Greater than or Equal to of series scalar (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 30, 10 ] ]; + const sf = new dfd.DataFrame(data1); + const expected = [ [ false, true, true, false ], [ false, false, true, false ] ]; + assert.deepEqual(sf.ge(30).values, expected); + }); + + }); + + describe("ne", function () { + it("Return Not Equal to of series and other series (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const data2 = [ [ 100, 450, 590, 5 ], [ 25, 2, 0, 10 ] ]; + + const df = new dfd.DataFrame(data1); + const df2 = new dfd.DataFrame(data2); + const expected = [ [ true, true, true, true ], [ false, true, true, false ] ]; + assert.deepEqual(df.ne(df2).values, expected); + }); + + it("Return Not Equal to of series scalar (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 30, 10 ] ]; + const sf = new dfd.DataFrame(data1); + const expected = [ [ true, true, true, true ], [ true, true, false, true ] ]; + assert.deepEqual(sf.ne(30).values, expected); + }); + it("Return Less than of Array and DataFrame along axis 1 (column)", function () { + const data = { + 'cost': [ 250, 150, 100 ], + 'revenue': [ 100, 250, 300 ] + }; + const sf = [ 100, 300 ]; + const df = new dfd.DataFrame(data, { index: [ 'A', 'B', 'C' ] }); + const expected = [ [ true, true ], [ true, true ], [ false, false ] ]; + const result = df.ne(sf, { axis: 1 }); + assert.deepEqual(result.values, expected); + }); + + }); + + describe("eq", function () { + it("Return Equal to of DataFrame and other DataFrame (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + const data2 = [ [ 100, 450, 590, 5 ], [ 25, 2, 0, 10 ] ]; + + const df = new dfd.DataFrame(data1); + const df2 = new dfd.DataFrame(data2); + const expected = [ [ false, false, false, false ], [ true, false, false, true ] ]; + assert.deepEqual(df.eq(df2).values, expected); + }); + + it("Return Equal to of DataFrame with scalar (element-wise)", function () { + const data1 = [ [ 10, 45, 56, 10 ], [ 25, 23, 30, 10 ] ]; + const sf = new dfd.DataFrame(data1); + const expected = [ [ false, false, false, false ], [ false, false, true, false ] ]; + assert.deepEqual(sf.eq(30).values, expected); + }); + it("Return Equal to of series and DataFrame scalar along axis 1", function () { + const data1 = { "Col1": [ 10, 45, 56, 10 ], "Col2": [ 23, 20, 10, 10 ] }; + const sf = new dfd.Series([ 10, 23 ]); + const df = new dfd.DataFrame(data1); + const expected = [ [ true, true ], [ false, false ], [ false, false ], [ true, false ] ]; + assert.deepEqual(df.eq(sf, { axis: 1 }).values, expected); + }); + it("Return Less than of Array and DataFrame along axis 0", function () { + const data = { + 'cost': [ 250, 150, 100 ], + 'revenue': [ 100, 250, 300 ] + }; + const sf = [ 250, 250, 100 ]; + const df = new dfd.DataFrame(data, { index: [ 'A', 'B', 'C' ] }); + const expected = [ [ true, false ], [ false, true ], [ true, false ] ]; + const result = df.eq(sf, { axis: 0 }); + assert.deepEqual(result.values, expected); + }); + + }); + + describe("replace", function () { + it("Replace across all columns", function () { + const data1 = [ [ 10, 45, 56, 25 ], [ 23, 20, 10, 24 ] ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ -999, 45, 56, 25 ], [ 23, 20, -999, 24 ] ]; + const df_rep = df.replace(10, -999); + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace accross all columns inplace", function () { + const data1 = [ [ "A", "A", "A", "B" ], [ "B", "C", "C", "D" ] ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ "boy", "boy", "boy", "B" ], [ "B", "C", "C", "D" ] ]; + df.replace("A", "boy", { inplace: true }); + assert.deepEqual(df.values, expected); + }); + it("Replace values in specified two column(s)", function () { + const data1 = [ [ "A", "A", 1, "girl" ], + [ "B", "A", 2, "woman" ], + [ "A", "B", 3, "man" ] ]; + const df = new dfd.DataFrame(data1, { columns: [ "col1", "col2", "col3", "col4" ] }); + const expected = [ [ "boy", "boy", 1, "girl" ], + [ "B", "boy", 2, "woman" ], + [ "boy", "B", 3, "man" ] ]; + const df_rep = df.replace("A", "boy", { columns: [ "col1", "col2" ] }); + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace values in specified single column(s)", function () { + const data1 = [ [ 2, "A", 1, "girl" ], + [ 3, "A", 2, "woman" ], + [ 4, "B", 3, "man" ] ]; + const df = new dfd.DataFrame(data1, { columns: [ "col1", "col2", "col3", "col4" ] }); + const expected = [ [ 2, "A", 1, "girl" ], + [ 100, "A", 2, "woman" ], + [ 4, "B", 3, "man" ] ]; + const df_rep = df.replace(3, 100, { columns: [ "col1" ] }); + assert.deepEqual(df_rep.values, expected); + assert.notDeepEqual(df_rep, df); + assert.notDeepEqual(df_rep.values, df.values); + }); + + it("Replace values in specified two column(s) inplace", function () { + const data1 = [ [ "A", "A", 1, "girl" ], + [ "B", "A", 2, "woman" ], + [ "A", "B", 3, "man" ] ]; + const df = new dfd.DataFrame(data1, { columns: [ "col1", "col2", "col3", "col4" ] }); + const expected = [ [ "boy", "boy", 1, "girl" ], + [ "B", "boy", 2, "woman" ], + [ "boy", "B", 3, "man" ] ]; + df.replace("A", "boy", { columns: [ "col1", "col2" ], inplace: true }); + assert.deepEqual(df.values, expected); + }); + + it("Replace values in specified single column(s) inplace", function () { + const data1 = [ [ 2, "A", 1, "girl" ], + [ 3, "A", 2, "woman" ], + [ 4, "B", 3, "man" ] ]; + const df = new dfd.DataFrame(data1, { columns: [ "col1", "col2", "col3", "col4" ] }); + const expected = [ [ 2, "A", 1, "girl" ], + [ 100, "A", 2, "woman" ], + [ 4, "B", 3, "man" ] ]; + df.replace(3, 100, { columns: [ "col1" ], inplace: true }); + assert.deepEqual(df.values, expected); + }); + + }); + + describe("sum", function () { + it("Sum values of a DataFrame by Default axis column (axis=1)", function () { + const data1 = [ [ 30, 40, 3.1 ], + [ 5, 5, 5.1 ], + [ 5, 5, 3.2 ] ]; + const sf = new dfd.DataFrame(data1); + const res = [ 73.1, 15.1, 13.2 ]; + assert.deepEqual(sf.sum().values, res); + }); + it("Sum values of a DataFrame along row axis (axis=0)", function () { + const data1 = [ [ 30, 40, 3.1 ], + [ 5, 5, 5.1 ], + [ 5, 5, 3.2 ] ]; + const df = new dfd.DataFrame(data1); + const res = [ 40, 50, 11.399999999999999 ]; + assert.deepEqual(df.sum({ axis: 0 }).values, res); + }); + it("Sum values of a mixed DataFrame along row axis (axis=0)", function () { + const data1 = [ [ 30, 40, 3.1, true ], + [ 5, 5, 5.1, true ], + [ 5, 5, 3.2, true ] ]; + const df = new dfd.DataFrame(data1); + const res = [ 40, 50, 11.399999999999999, 3 ]; + assert.deepEqual(df.sum({ axis: 0 }).values, res); + }); + it("Sum values of a boolean DataFrame along row axis (axis=0)", function () { + const data1 = [ [ true, true, false, true ], + [ false, false, false, false ], + [ false, true, true, false ] ]; + const df = new dfd.DataFrame(data1); + const res = [ 1, 2, 1, 1 ]; + assert.deepEqual(df.sum({ axis: 0 }).values, res); + }); + it("Sum values of a boolean DataFrame along default column axis (axis=1)", function () { + const data1 = [ [ true, true, false, true ], + [ false, false, false, false ], + [ false, true, true, false ] ]; + const df = new dfd.DataFrame(data1); + const res = [ 3, 0, 2 ]; + assert.deepEqual(df.sum().values, res); + }); + it("Sum values of a df with missing values", function () { + const data1 = [ [ 11, 20, 3 ], [ null, 15, 6 ], [ 2, 30, 40 ], [ 2, 89, 78 ] ]; + const df = new dfd.DataFrame(data1); + const res = [ 34, 21, 72, 169 ]; + assert.deepEqual(df.sum({ axis: 1 }).values, res); + }); + + }); + + describe("abs", function () { + it("Returns the absolute values in DataFrame of ints", function () { + const data1 = [ [ -10, 45, 56, 10 ], [ -25, 23, 20, -10 ] ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ 10, 45, 56, 10 ], [ 25, 23, 20, 10 ] ]; + assert.deepEqual(df.abs().values, expected); + }); + + it("Returns the absolute values in mixed DataFrame", function () { + const data1 = [ [ -10, -45.1, 56, 10 ], [ -25, -23.2, 20, -10 ] ]; + const df = new dfd.DataFrame(data1); + const expected = [ [ 10, 45.1, 56, 10 ], [ 25, 23.2, 20, 10 ] ]; + assert.deepEqual(df.abs().values, expected); + }); + }); + + describe("T", function () { + it("Return the Transpose of a DataFrame", function () { + const data1 = [ [ 10, 45, 56, 10 ], + [ 25, 23, 20, 10 ] ]; + + const cols = [ "a", "b", "c", "d" ]; + const df = new dfd.DataFrame(data1, { columns: cols }); + const df_trans = df.T; + const expected_vals = [ [ 10, 25 ], [ 45, 23 ], [ 56, 20 ], [ 10, 10 ] ]; + const expected_index = cols; + const expected_col_names = [ "0", "1" ]; + assert.deepEqual(df_trans.index, expected_index); + assert.deepEqual(df_trans.values, expected_vals); + assert.deepEqual(df_trans.columns, expected_col_names); + + }); + }); + + describe("transpose", function () { + it("Return the Transpose of a DataFrame", function () { + const data1 = [ [ 10, 45, 56, 10 ], + [ 25, 23, 20, 10 ] ]; + + const cols = [ "a", "b", "c", "d" ]; + const df = new dfd.DataFrame(data1, { columns: cols }); + const df_trans = df.T; + const expected_vals = [ [ 10, 25 ], [ 45, 23 ], [ 56, 20 ], [ 10, 10 ] ]; + const expected_index = cols; + const expected_col_names = [ "0", "1" ]; + assert.deepEqual(df_trans.index, expected_index); + assert.deepEqual(df_trans.values, expected_vals); + assert.deepEqual(df_trans.columns, expected_col_names); + + }); + it("Transpose a DataFrame inplace", function () { + const data1 = [ [ 10, 45, 56, 10 ], + [ 25, 23, 20, 10 ] ]; + + const cols = [ "a", "b", "c", "d" ]; + const df = new dfd.DataFrame(data1, { columns: cols }); + df.transpose({ inplace: true }); + const expected_vals = [ [ 10, 25 ], [ 45, 23 ], [ 56, 20 ], [ 10, 10 ] ]; + const expected_index = cols; + const expected_col_names = [ "0", "1" ]; + assert.deepEqual(df.index, expected_index); + assert.deepEqual(df.values, expected_vals); + assert.deepEqual(df.columns, expected_col_names); + + }); + }); + + + describe("asType", function () { + it("set type of float column to int", function () { + const data = { + "A": [ -20.1, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20.1, -20.23, 30.3, 40.11 ], + "D": [ "a", "b", "c", "c" ] + }; + const df = new dfd.DataFrame(data); + const dfNew = df.asType("A", "int32"); + dfNew["D"] = [ "a", "b", "c", "F" ]; + assert.deepEqual(dfNew.dtypes, [ 'int32', 'int32', 'float32', 'string' ]); + assert.deepEqual(dfNew['A'].values, [ -20, 30, 47, -20 ]); + assert.notDeepEqual(dfNew["D"].values, df["D"].values); + + }); + it("set type of int column to float", function () { + const data = { + "A": [ -20.1, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20.1, -20.23, 30.3, 40.11 ], + "D": [ "a", "b", "c", "c" ] + }; + const df = new dfd.DataFrame(data); + const dfNew = df.asType("B", "float32"); + + assert.deepEqual(dfNew.dtypes, [ 'float32', 'float32', 'float32', 'string' ]); + assert.deepEqual(dfNew['B'].values, [ 34, -4, 5, 6 ]); + + }); + it("set type of string column to int", function () { + const data = { + "A": [ -20.1, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20.1, -20.23, 30.3, 40.11 ], + "D": [ "20.1", "21", "23.4", "50.78" ] + }; + const df = new dfd.DataFrame(data); + const dfNew = df.asType("D", "int32"); + + assert.deepEqual(dfNew.dtypes, [ 'float32', 'int32', 'float32', 'int32' ]); + assert.deepEqual(dfNew['D'].values, [ 20, 21, 23, 50 ]); + + }); + it("set type of string column to float", function () { + const data = { + "A": [ -20.1, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20.1, -20.23, 30.3, 40.11 ], + "D": [ "20.1", "21", "23.4", "50.78" ] + }; + const df = new dfd.DataFrame(data); + const dfNew = df.asType("D", "float32"); + + assert.deepEqual(dfNew.dtypes, [ 'float32', 'int32', 'float32', 'float32' ]); + assert.deepEqual(dfNew['D'].values, [ 20.1, 21, 23.4, 50.78 ]); + + }); + }); + + describe("nUnique", function () { + it("Returns the number of unique elements along axis 1", function () { + const data = { + "A": [ -20, 30, 47.3, -20, 2 ], + "B": [ 34, -4, 5, 6, 2 ], + "C": [ 20, 20, 30, 30, 2 ], + "D": [ "a", "b", "c", "c", "d" ] + }; + + const df = new dfd.DataFrame(data); + const res = [ 4, 4, 4, 4, 2 ]; + assert.deepEqual(df.nUnique(1).values, res); + + }); + it("Returns the number of unique elements along axis 0", function () { + const data = { + "A": [ 20, 30, 47.3, 30 ], + "B": [ 34, -4, 5, 30 ], + "C": [ 20, 20, 30, 30 ], + "D": [ "a", "b", "c", "c" ] + }; + + const df = new dfd.DataFrame(data); + const res = [ 3, 4, 2, 3 ]; + assert.deepEqual(df.nUnique(0).values, res); + + }); + + }); + + + describe("rename", function () { + it("Rename columns along axis 1", function () { + const data = { + "A": [ -20, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20, 20, 30, 30 ] + }; + + const df = new dfd.DataFrame(data); + const dfNew = df.rename({ "A": "a1", "B": "b1" }); + const res = [ "a1", "b1", "C" ]; + assert.deepEqual(dfNew.columns, res); + + }); + it("confirms original column name is not modified along axis 1", function () { + const data = { + "A": [ -20, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "D": [ "a", "b", "c", "c" ] + }; + + const df = new dfd.DataFrame(data); + const dfNew = df.rename({ "A": "a1", "B": "b1" }, { axis: 1 }); + const res = [ "A", "B", "D" ]; + assert.deepEqual(df.columns, res); + + }); + it("Rename columns along axis 1 inplace", function () { + const data = { + "A": [ -20, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20, 20, 30, 30 ] + }; + + const df = new dfd.DataFrame(data); + df.rename({ "A": "a1", "B": "b1" }, { inplace: true }); + const res = [ "a1", "b1", "C" ]; + assert.deepEqual(df.columns, res); + + }); + it("Rename string index along axis 0", function () { + const data = { + "A": [ -20, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20, 20, 30, 30 ] + }; + + const df = new dfd.DataFrame(data, { index: [ "a", "b", "c", "d" ] }); + const dfNew = df.rename({ "a": 0, "b": 1 }, { axis: 0 }); + const res = [ 0, 1, "c", "d" ]; + assert.deepEqual(dfNew.index, res); + + }); + it("Rename string index along axis 0 inplace", function () { + const data = { + "A": [ -20, 30, 47.3, -20 ], + "B": [ 34, -4, 5, 6 ], + "C": [ 20, 20, 30, 30 ] + }; + + const df = new dfd.DataFrame(data, { index: [ "a", "b", "c", "d" ] }); + df.rename({ "a": 0, "b": 1 }, { axis: 0, inplace: true }); + const res = [ 0, 1, "c", "d" ]; + assert.deepEqual(df.index, res); + + }); + + it("Get new column via subseting works after rename (inplace)", function () { + let data = { + "A": [ -20, 30, 47.3 ], + "B": [ 34, -4, 5 ], + "C": [ 20, 2, 30 ] + }; + let df = new dfd.DataFrame(data); + df.rename({ "A": "new_name" }, { inplace: true }); + df["new_name"].print(); + assert.deepEqual(df["new_name"].values, data["A"]); + }); + + it("Get new column via subseting works after rename (not-inplace)", function () { + let data = { + "A": [ -20, 30, 47.3 ], + "B": [ 34, -4, 5 ], + "C": [ 20, 2, 30 ] + }; + let df = new dfd.DataFrame(data); + let new_df = df.rename({ "A": "new_name" }); + assert.deepEqual(new_df["new_name"].values, data["A"]); + }); + }); + + describe("sortIndex", function () { + + it("sort index in ascending order", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ], index: [ "b", "a", "c" ] }); + const df2 = df.sortIndex(); + const rslt = [ [ 360, 180, 360, 'a' ], [ 0, 2, 4, 'b' ], [ 2, 4, 6, 'c' ] ]; + + assert.deepEqual(df2.values, rslt); + }); + it("sort index in ascending order - inplace", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ], index: [ "b", "a", "c" ] }); + df.sortIndex({ inplace: true }); + const rslt = [ [ 360, 180, 360, 'a' ], [ 0, 2, 4, 'b' ], [ 2, 4, 6, 'c' ] ]; + assert.deepEqual(df.values, rslt); + }); + it("sort index in descending order", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ], index: [ "b", "a", "c" ] }); + const df2 = df.sortIndex({ ascending: false }); + const rslt = [ [ 2, 4, 6, 'c' ], [ 0, 2, 4, 'b' ], [ 360, 180, 360, 'a' ] ]; + + assert.deepEqual(df2.values, rslt); + }); + it("sort index in descending order with inplace set to true", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ], index: [ 4, 2, 5 ] }); + df.sortIndex({ ascending: false, inplace: true }); + const rslt = [ [ 2, 4, 6, 'c' ], [ 0, 2, 4, 'b' ], [ 360, 180, 360, 'a' ] ]; + assert.deepEqual(df.values, rslt); + }); + + it("sort index in descending order and retains index", function () { + let data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + let df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ], index: [ "b", "a", "c" ] }); + let df2 = df.sortIndex({ ascending: false }); + let rslt = [ "c", "b", "a" ]; + + assert.deepEqual(df2.index, rslt); + }); + }); + + describe("append", function () { + + it("Append works for an array", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data); + const expected_val = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ], + [ 20, 40, 60, "d" ] ]; + + const newDf = df.append([ 20, 40, 60, "d" ], [ "n1" ]); + assert.deepEqual(newDf.values, expected_val); + assert.deepEqual(newDf.index, [ 0, 1, 2, "n1" ]); + }); + it("Append works for an array of arrays", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data); + const expected_val = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ], + [ 20, 40, 60, "d" ], + [ 21, 42, 61, "y" ] ]; + + const newDf = df.append([ [ 20, 40, 60, "d" ], [ 21, 42, 61, "y" ] ], [ "n1", "n2" ]); + assert.deepEqual(newDf.values, expected_val); + assert.deepEqual(newDf.index, [ 0, 1, 2, "n1", "n2" ]); + }); + + it("Append works for DataFrame", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ] }); + const df2 = new dfd.DataFrame([ [ 20, 40, 60, "d" ] ], { "columns": [ "col1", "col2", "col3", "col4" ] }); + + const expected_val = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ], + [ 20, 40, 60, "d" ] ]; + + const newDf = df.append(df2, [ "n1" ]); + assert.deepEqual(newDf.values, expected_val); + + }); + it("Append works for Series", function () { + const data = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ] ]; + + const df = new dfd.DataFrame(data, { "columns": [ "col1", "col2", "col3", "col4" ] }); + const sf = new dfd.Series([ 20, 40, 60, "d" ]); + + const expected_val = [ [ 0, 2, 4, "b" ], + [ 360, 180, 360, "a" ], + [ 2, 4, 6, "c" ], + [ 20, 40, 60, "d" ] ]; + + const newDf = df.append(sf, [ "n1" ]); + assert.deepEqual(newDf.values, expected_val); + + }); + }); + + describe("cumProd", function () { + + it("cumProd works for axis 1", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 2, 4, 12 ], + [ 3, 12, 132, 1188 ], + [ 5, 30, 210, 1680 ] ]; + + const newDf = df.cumProd(); + assert.deepEqual(newDf.values, rslt); + }); + it("cumProd axis 0 works", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 6, 4, 22, 27 ], + [ 30, 24, 154, 216 ] ]; + + assert.deepEqual(df.cumProd({ axis: 0 }).values, rslt); + }); + + it("cumProd works for axis 1 inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 2, 4, 12 ], + [ 3, 12, 132, 1188 ], + [ 5, 30, 210, 1680 ] ]; + + df.cumProd({ inplace: true }); + assert.deepEqual(df.values, rslt); + }); + it("cumProd axis 0 works inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 6, 4, 22, 27 ], + [ 30, 24, 154, 216 ] ]; + df.cumProd({ axis: 0, inplace: true }); + assert.deepEqual(df.values, rslt); + }); + }); + + describe("cumSum", function () { + + it("cumSum works for axis 1", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 3, 5, 8 ], + [ 3, 7, 18, 27 ], + [ 5, 11, 18, 26 ] ]; + + const newDf = df.cumSum(); + assert.deepEqual(newDf.values, rslt); + }); + it("cumSum axis 0 works", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 5, 5, 13, 12 ], + [ 10, 11, 20, 20 ] ]; + + assert.deepEqual(df.cumSum({ axis: 0 }).values, rslt); + }); + + it("cumSum works for axis 1 inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 3, 5, 8 ], + [ 3, 7, 18, 27 ], + [ 5, 11, 18, 26 ] ]; + + df.cumSum({ inplace: true }); + assert.deepEqual(df.values, rslt); + }); + it("cumSum axis 0 works inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 5, 5, 13, 12 ], + [ 10, 11, 20, 20 ] ]; + df.cumSum({ axis: 0, inplace: true }); + assert.deepEqual(df.values, rslt); + }); + }); + + describe("cumMin", function () { + + it("cumMin works for axis 1", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 1, 1 ], + [ 3, 3, 3, 3 ], + [ 5, 5, 5, 5 ] ]; + + const newDf = df.cumMin(); + assert.deepEqual(newDf.values, rslt); + }); + it("cumMin axis 0 works", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 2, 1, 2, 3 ], + [ 2, 1, 2, 3 ] ]; + + assert.deepEqual(df.cumMin({ axis: 0 }).values, rslt); + }); + + it("cumMin works for axis 1 inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 1, 1 ], + [ 3, 3, 3, 3 ], + [ 5, 5, 5, 5 ] ]; + + df.cumMin({ inplace: true }); + assert.deepEqual(df.values, rslt); + }); + it("cumMin axis 0 works inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 2, 1, 2, 3 ], + [ 2, 1, 2, 3 ] ]; + df.cumMin({ axis: 0, inplace: true }); + assert.deepEqual(df.values, rslt); + }); + }); + + describe("cumMax", function () { + + it("cumMax works for axis 1", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 2, 2, 3 ], + [ 3, 4, 11, 11 ], + [ 5, 6, 7, 8 ] ]; + + const newDf = df.cumMax(); + assert.deepEqual(newDf.values, rslt); + }); + it("cumMax axis 0 works", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 3, 4, 11, 9 ], + [ 5, 6, 11, 9 ] ]; + + assert.deepEqual(df.cumMax({ axis: 0 }).values, rslt); + }); + + it("cumMax works for axis 1 inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 2, 2, 3 ], + [ 3, 4, 11, 11 ], + [ 5, 6, 7, 8 ] ]; + + df.cumMax({ inplace: true }); + assert.deepEqual(df.values, rslt); + }); + it("cumMax axis 0 works inplace", function () { + const data = [ [ 2, 1, 2, 3 ], [ 3, 4, 11, 9 ], [ 5, 6, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ [ 2, 1, 2, 3 ], + [ 3, 4, 11, 9 ], + [ 5, 6, 11, 9 ] ]; + df.cumMax({ axis: 0, inplace: true }); + assert.deepEqual(df.values, rslt); + }); + }); + + + describe("query", function () { + + it("Get the DataFrame containing rows with the filtered column", function () { + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const query_df = df.query(df["B"].ge(5)); + const query_data = [ [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + assert.deepEqual(query_df.values, query_data); + }); + it("Get the Dataframe containing rows with the filtered column in String values", function () { + const data = { "Abs": [ 20, 30, 47 ], "Count": [ 34, 4, 5 ], "country code": [ "NG", "FR", "GH" ] }; + const cols = [ "Abs", "Count", "country code" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const query_df = df.query(df["country code"].str.includes("NG")); + + const query_data = [ [ 20, 34, "NG" ] ]; + assert.deepEqual(query_df.values, query_data); + }); + it("Get the Dataframe containing rows with the filtered column in String values inplace", function () { + const data = { "Abs": [ 20, 30, 47 ], "Count": [ 34, 4, 5 ], "country code": [ "NG", "FR", "GH" ] }; + const cols = [ "Abs", "Count", "country code" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + df.query(df["country code"].eq("NG"), { inplace: true }); + const query_data = [ [ 20, 34, "NG" ] ]; + assert.deepEqual(df.values, query_data); + }); + it("Confirms that query index are updated", function () { + + const data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + const query_df = df.query(df["B"].ge(5)); + assert.deepEqual(query_df.index, [ 1, 2, 3 ]); + }); + + it("Confirms chaining boolean queries work", function () { + + const data = [ [ 1, 2, 3 ], + [ 4, 5, 60 ], + [ 20, 30, 4 ], + [ 39, 89, 7 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const query_df = df.query( + df["B"].ge(5).and(df["C"].lt(10)) + ); + const query_data = [ [ 20, 30, 4 ], [ 39, 89, 7 ] ]; + assert.deepEqual(query_df.values, query_data); + assert.deepEqual(query_df.index, [ 2, 3 ]); + }); + + it("Confirms chaining boolean queries work and returns empty DF", function () { + + const data = [ [ 1, 2, 3 ], + [ 4, 5, 60 ], + [ 20, 30, 40 ], + [ 39, 89, 70 ] ]; + const cols = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns: cols }); + + const query_df = df.query( + df["B"].ge(5).and(df["C"].lt(10)) + ); + assert.deepEqual(query_df.values, []); + assert.deepEqual(query_df.index, []); + }); + + it("Confirms that column names are not changed", function () { + + let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; + let cols = [ "A", "B", "C" ]; + let df = new dfd.DataFrame(data, { columns: cols }); + let df_query = df.query( df["B"].ge(5)); + assert.deepEqual(df_query.index, [ 1, 2, 3 ]); + assert.deepEqual(df_query.columns, [ "A", "B", "C" ]); + }); + + }); + + describe("cTypes", function () { + + it("Returns the correct dtype in a DataFrame", function () { + const data = [ [ "boy", 1.2, 2, 3 ], [ "girl", 4.32, 11, 9 ], [ '4', 6.1, 7, 8 ] ]; + const column = [ "A", "B", "C", "D" ]; + const df = new dfd.DataFrame(data, { columns: column }); + const rslt = [ "string", "float32", "int32", "int32" ]; + assert.deepEqual(df.ctypes.values, rslt); + }); + }); + + + describe("getDummies", function () { + it("getDummies works on DataFrame", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const df1 = df.getDummies({ prefixSeparator: [ "_", "#" ], columns: [ "A", "d" ], prefix: "test" }); + const expectedColumns = [ 'B', 'C', 'test_1', 'test_3', 'test_4', 'test#fat', 'test#good', 'test#best' ]; + const expected = [ [ 'dog', 1.0, 1, 0, 0, 1, 0, 0 ], + [ 'fog', 2.0, 0, 1, 0, 0, 1, 0 ], + [ 'gof', 3.0, 0, 0, 1, 0, 0, 1 ] ]; + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + it("Throw error if the prefix specified is not equal to the column specified", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + assert.throws(function () { df.getDummies({ prefix: [ "fg" ], prefixSeparator: "_", columns: [ "A", "d" ] }); }, Error, + `ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "fg"}`); + + }); + it("replace column sepecified with prefix", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const df1 = df.getDummies({ prefix: [ "F", "G" ], prefixSeparator: "_", columns: [ "A", "d" ] }); + const expectedColumns = [ + 'B', 'C', + 'F_1', 'F_3', + 'F_4', 'G_fat', + 'G_good', 'G_best' + ]; + + const expected = [ [ 'dog', 1.0, 1, 0, 0, 1, 0, 0 ], + [ 'fog', 2.0, 0, 1, 0, 0, 1, 0 ], + [ 'gof', 3.0, 0, 0, 1, 0, 0, 1 ] ]; + + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("getDummies auto infers and encode columns with string dtype", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const df1 = df.getDummies({ prefixSeparator: "_" }); + const expectedColumns = [ + 'A', 'C', + 'B_dog', 'B_fog', + 'B_gof', 'd_fat', + 'd_good', 'd_best' + ]; + const expected = [ + [ + 1, 1, 1, 0, + 0, 1, 0, 0 + ], + [ + 3, 2, 0, 1, + 0, 0, 1, 0 + ], + [ + 4, 3, 0, 0, + 1, 0, 0, 1 + ] + ]; + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("should one hot encode all other columns", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + const rslt = [ + [ 1, 'dog', 1, 1, 0, 0 ], + [ 3, 'fog', 2, 0, 1, 0 ], + [ 4, 'gof', 3, 0, 0, 1 ] + ]; + + assert.deepEqual(df.getDummies({ columns: [ "d" ] }).values, rslt); + + }); + }); + + describe("iat", function () { + it("iat works on DataFrame", function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + const columns = [ "a", "b", "c", "d" ]; + const df = new dfd.DataFrame(data, { columns }); + assert.equal(df.iat(0, 0), 1); + assert.equal(df.iat(1, 1), 6); + assert.equal(df.iat(2, 3), 12); + }); + it("throws error on string indices", function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + const columns = [ "a", "b", "c", "d" ]; + const index = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns, index }); + /* @ts-ignore */ + assert.throws(function () { df.iat("A", 0); }, Error, "ParamError: row and column index must be an integer. Use .at to get a row or column by label."); + /* @ts-ignore */ + assert.throws(function () { df.iat(0, "A"); }, Error, "ParamError: row and column index must be an integer. Use .at to get a row or column by label."); + }); + }); + + describe("at", function () { + it("at works on DataFrame", function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + const columns = [ "a", "b", "c", "d" ]; + const index = [ "A", "B", "C" ]; + const df = new dfd.DataFrame(data, { columns, index }); + assert.equal(df.at("A", "a"), 1); + assert.equal(df.at("B", "b"), 6); + assert.equal(df.at("C", "c"), 11); + + }); + it("throws error on numeric column index", function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + const columns = [ "a", "b", "c", "d" ]; + const index = [ 0, "B", "C" ]; + const df = new dfd.DataFrame(data, { columns, index }); + + assert.equal(df.at(0, "b"), 2); + /* @ts-ignore */ + assert.throws(function () { df.at(0, 1); }, Error, "ParamError: column index must be a string. Use .iat to get a row or column by index."); + /* @ts-ignore */ + assert.throws(function () { df.at("B", 0); }, Error, "ParamError: column index must be a string. Use .iat to get a row or column by index."); + + }); + + }); + + describe("DateTime datetime is supported", function () { + it("DateTime datetime is supported", function () { + let data = [ [ "Alice", 2, new Date(2029, 1, 1) ], + [ "Bob", 5, new Date(2019, 1, 2) ], + [ "Charlie", 30, new Date(2019, 1, 3) ], + [ "Dennis", 89, new Date(2019, 1, 4) ] ]; + + let columns = [ "Name", "Count", "Date" ]; + + let df = new dfd.DataFrame(data, { columns: columns }); + assert.deepEqual(df.dtypes, [ "string", "int32", "datetime" ]); + + const dateValues = [ new Date(2029, 1, 1), new Date(2019, 1, 2), new Date(2019, 1, 3), new Date(2019, 1, 4) ]; + assert.deepEqual(df["Date"].values, dateValues); + }); + + it("datetime column properties can be accessed", function () { + let data = [ [ "Alice", 2, new Date("2029-01-01 01:00:00") ], + [ "Bob", 5, new Date("2019-01-02") ], + [ "Charlie", 30, new Date("2020-01-03 01:00:20") ], + [ "Dennis", 89, new Date("2022-02-04 02:16:00") ] ]; + + let columns = [ "Name", "Count", "Date" ]; + + let df = new dfd.DataFrame(data, { columns: columns }); + + assert.deepEqual(df["Date"].dt.year().values, [ 2029, 2019, 2020, 2022 ]); + assert.deepEqual(df["Date"].dt.month().values, [ 0, 0, 0, 1 ]); + assert.deepEqual(df["Date"].dt.dayOfMonth().values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["Date"].dt.hours().values, [ 1, 0, 1, 2 ]); + assert.deepEqual(df["Date"].dt.minutes().values, [ 0, 0, 0, 16 ]); + assert.deepEqual(df["Date"].dt.seconds().values, [ 0, 0, 20, 0 ]); + + }); + + it("datetime column created from dtype passed", function () { + let data = [ [ "Alice", 2, "2029-01-01 01:00:00" ], + [ "Bob", 5, "2019-01-02" ], + [ "Charlie", 30, "2020-01-03 01:00:20" ], + [ "Dennis", 89, "2022-02-04 02:16:00" ] ]; + + let columns = [ "Name", "Count", "Date" ]; + let dtypes = [ "string", "int32", "datetime" ]; + + let df = new dfd.DataFrame(data, { columns, dtypes }); + + assert.deepEqual(df["Date"].dt.year().values, [ 2029, 2019, 2020, 2022 ]); + assert.deepEqual(df["Date"].dt.month().values, [ 0, 0, 0, 1 ]); + assert.deepEqual(df["Date"].dt.dayOfMonth().values, [ 1, 2, 3, 4 ]); + assert.deepEqual(df["Date"].dt.hours().values, [ 1, 0, 1, 2 ]); + assert.deepEqual(df["Date"].dt.minutes().values, [ 0, 0, 0, 16 ]); + assert.deepEqual(df["Date"].dt.seconds().values, [ 0, 0, 20, 0 ]); + + }); + }); +}); diff --git a/src/danfojs-browser/tests/core/generic.test.js b/src/danfojs-browser/tests/core/generic.test.js new file mode 100644 index 00000000..eadcc936 --- /dev/null +++ b/src/danfojs-browser/tests/core/generic.test.js @@ -0,0 +1,509 @@ +/* eslint-disable no-undef */ +const tensor = require('@tensorflow/tfjs').tensor; + +describe("Generic (NDFrame)", function () { + describe("NDframe Created from Array", function () { + it("prints the shape of a 1D array", function () { + let data = [ 1, 2, 3, "Boy", "Girl" ]; + let ndframe = new dfd.NDframe({ data, isSeries: true }); + assert.deepEqual(ndframe.shape, [ 5, 1 ]); + }); + it("prints the default assigned column name in a series", function () { + let data = [ "Boy", 20, 25 ]; + let ndframe = new dfd.NDframe({ data, isSeries: true }); + assert.deepEqual(ndframe.columns, [ "0" ]); + }); + it("prints the assigned column name in a series", function () { + let data = [ "Boy", 20, 25 ]; + let ndframe = new dfd.NDframe({ data, columns: [ "Records" ], isSeries: true }); + assert.deepEqual(ndframe.columns, [ "Records" ]); + }); + it("prints the shape of a 2D array", function () { + let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.shape, [ 2, 2 ]); + }); + it("prints the default assigned column names in 2D frame", function () { + let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.columns, [ "0", "1" ]); + }); + it("prints the assigned column names", function () { + let data = [ [ "Boy", 20 ], [ "Girl", 25 ] ]; + let options = { "columns": [ "Gender", "Age" ], "isSeries": false }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.columns, [ "Gender", "Age" ]); + }); + it("prints the size of a frame", function () { + let data = [ [ "Boy", 20, 1 ], [ "Girl", 25, 3 ] ]; + let options = { "columns": [ "Gender", "Age", "count" ], "isSeries": false }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.size, 6); + }); + it("prints the dimension of a frame", function () { + let data = [ [ "Boy", 20, 1 ], [ "Girl", 25, 3 ] ]; + let options = { "columns": [ "Gender", "Age", "count" ], "isSeries": false }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.ndim, 2); + }); + it("prints the values of a frame", function () { + let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ] ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, data); + }); + it("prints the values of a frame", function () { + let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ] ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, data); + }); + + it("Throws error on duplicate column name", function () { + let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ] ]; + assert.throws( + () => new dfd.NDframe({ data, isSeries: false, columns: [ "A", "A", "C" ] }), + Error, + "ColumnIndexError: Column index must contain unique values" + ); + }); + + it("Throws error on duplicate index", function () { + let data = [ [ 21, 20, 1 ], [ 20, 25, 3 ], [ 19, 30, 5 ] ]; + assert.throws( + () => new dfd.NDframe({ data, isSeries: false, index: [ 1, 1, 2 ] }), + Error, + "IndexError: Row index must contain unique values" + ); + }); + + it("Successfully create a 2D Frame when first value is empty", function () { + let data = [ [ null, 20, 1 ], [ 20, 25, 3 ] ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + //@ts-ignore + assert.deepEqual(ndframe.values, data); + }); + it("Successfully create a 1D Frame when first value is empty", function () { + let data = [ null, 'bval2', 'bval3', 'bval4' ]; + let ndframe = new dfd.NDframe({ data, isSeries: true }); + //@ts-ignore + assert.deepEqual(ndframe.values, data); + }); + }); + + describe("NDframe Created from JavaScript Object", function () { + + it("prints the shape of a 2D frame created from an Object", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.shape, [ 3, 2 ]); + }); + it("prints the column names of frame created from an Object", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.columns, [ "alpha", "count" ]); + }); + it("prints the shape of a 1D frame created from an Object", function () { + let data = [ { alpha: "A", count: 1 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.shape, [ 1, 2 ]); + }); + + it("prints the size of a frame created from an Object", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.size, 6); + }); + it("prints the dimension of a frame created from an Object", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.ndim, 2); + }); + it("prints the values of a frame created from an Object", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, [ [ "A", 1 ], [ "B", 2 ] ]); + }); + it("prints the values of a frame created from an Object with undefined values", function () { + let data = [ { alpha: "A", count: undefined }, { alpha: undefined, count: 2 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, [ [ "A", undefined ], [ undefined, 2 ] ]); + }); + + it("prints the values of a frame created from an Object with NaN values", function () { + let data = [ { alpha: "A", count: NaN }, { alpha: NaN, count: 2 } ]; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, [ [ "A", NaN ], [ NaN, 2 ] ]); + }); + + // it("NDframe created from json takes key position into consideration", function () { + // let json_data = [ { A: "A", B: "B", C: "C" }, + // { A: "A", B: "B", C: "C" }, + // { C: "C", B: "B", A: "A" }, + // { A: "A", C: "C", B: "B" } ]; + + // let output = [ + // [ + // 'A', + // 'B', + // 'C' + // ], + // [ + // 'A', + // 'B', + // 'C' + // ], + // [ + // 'A', + // 'B', + // 'C' + // ], + // [ + // 'A', + // 'B', + // 'C' + // ] + // ]; + // let ndframe = new dfd.NDframe({ json_data, isSeries: false }); + // assert.deepEqual(ndframe.values, output); + // }); + + // it("NDframe created from json sets value to NaN if not present", function () { + // let json_data = [ { A: "A", B: "B", C: "C" }, + // { A: "A", B: "B", C: "C" }, + // { C: "C", B: "B", A: "A" }, + // { A: "A", C: "C" } ]; + + // let output = [ + // [ + // 'A', + // 'B', + // 'C' + // ], + // [ + // 'A', + // 'B', + // 'C' + // ], + // [ + // 'A', + // 'B', + // 'C' + // ], + // [ + // 'A', + // 'B', + // NaN + // ] + // ]; + // let ndframe = new dfd.NDframe({ json_data, isSeries: false }); + // assert.deepEqual(ndframe.values, output); + // }); + + }); + + describe("Replacing row data", function () { + it("retrieves the col data after row data is replaced in a DataFrame", function () { + let data = { alpha: [ "A", "B" ], count: [ 1, 2 ] }; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + ndframe.$setValues([ [ "A", 20 ], [ "D", 211 ] ]); + assert.deepEqual(ndframe.values, [ [ "A", 20 ], [ "D", 211 ] ]); + + }); + it("Correct dtypes is inferred after row data is replaced in a DataFrame", function () { + let data = { alpha: [ "A", "B" ], count: [ 1, 2 ] }; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + ndframe.$setValues([ [ 20, 20 ], [ 11.4, 211 ] ]); + assert.deepEqual(ndframe.dtypes, [ "float32", "int32" ]); + + }); + it("Throws row length error on invalid data length in DataFrame", function () { + let data = { alpha: [ "A", "B" ], count: [ 1, 2 ] }; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.throws( + () => { + ndframe.$setValues([ [ 20, 20 ], [ 11.4, 211 ], [ 11.4, 211 ] ]); + }, + Error, + "Row data length mismatch. You provided data with length 3 but Ndframe has row of length 2" + ); + }); + it("Throws column length error on invalid data length in DataFrame", function () { + let data = { alpha: [ "A", "B" ], count: [ 1, 2 ] }; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.throws( + () => { + ndframe.$setValues([ [ 20, 211 ], [ 20, 20, 11.4, 211 ] ]); + }, + Error, + "Column data length mismatch. You provided data with length 2 but Ndframe has column of length 2" + ); + }); + it("retrieves the col data after row data is replaced in a Series", function () { + let data = [ "A", "B", 1, 2 ]; + let ndframe = new dfd.NDframe({ data, isSeries: true }); + ndframe.$setValues([ "A", "D", "E", "O" ]); + assert.deepEqual(ndframe.values, [ "A", "D", "E", "O" ]); + assert.deepEqual(ndframe.$dataIncolumnFormat, [ "A", "D", "E", "O" ]); + + }); + it("Correct dtypes is inferred after updating values", function () { + let data = [ "A", "D", "E", "O" ]; + let ndframe = new dfd.NDframe({ data, isSeries: true }); + ndframe.$setValues([ 1, 2, 3, 4 ]); + assert.deepEqual(ndframe.values, [ 1, 2, 3, 4 ]); + assert.deepEqual(ndframe.dtypes[0], "int32"); + }); + it("Correct dtypes is inferred after updating values in low memory mode", function () { + let data = [ "A", "D", "E", "O" ]; + let ndframe = new dfd.NDframe({ data, isSeries: true, config: { lowMemoryMode: true } }); + ndframe.$setValues([ 1, 2, 3, 4 ]); + assert.deepEqual(ndframe.values, [ 1, 2, 3, 4 ]); + assert.deepEqual(ndframe.dtypes[0], "int32"); + }); + it("Throws row length error on invalid data length", function () { + let data = [ "A", "D", "E", "O" ]; + let ndframe = new dfd.NDframe({ data, isSeries: true, config: { lowMemoryMode: true } }); + assert.throws( + () => { + ndframe.$setValues([ 1, 2, 3, 4, 1, 3 ]); + }, + Error, + "Row data length mismatch. You provided data with length 6 but Ndframe has row of length 4" + ); + }); + + }); + + describe("NDframe Created from a Tensor", function () { + + it("prints the shape of a 2D frame created from a 2D tensor", function () { + let data = tensor([ 1, 2, 3, 4 ]); + let ndframe = new dfd.NDframe({ data, isSeries: true }); + assert.deepEqual(ndframe.ndim, 1); + assert.deepEqual(ndframe.values, [ 1, 2, 3, 4 ]); + + }); + it("prints the shape of a 2D frame created from a 1D tensor", function () { + let data = tensor([ [ 2, 3, 4 ], [ 4, 5, 6 ] ]); + let ndframe = new dfd.NDframe({ data, columns: [ "alpha", "count", "sum" ], isSeries: false }); + assert.deepEqual(ndframe.columns, [ "alpha", "count", "sum" ]); + }); + + }); + + describe("index", function () { + it("Returns the index of an NDframe", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + let df = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(df.index, [ 0, 1, 2 ]); + }); + it("Returns the index of an NDframe created from an Array", function () { + let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; + let df = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(df.index, [ 0, 1, 2, 3 ]); + }); + }); + + describe("NDframe Created from JavaScript Object of Arrays", function () { + + it("retrieves the col data created from OA ", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ] }; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, [ [ 'A', 1 ], [ 'B', 2 ], [ 'C', 3 ], [ 'D', 4 ] ]); + }); + it("retrieves the data 2", function () { + let data = { alpha: [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + let res = [ + [ 'A', 1, 20.3 ], + [ 'B', 2, 30.456 ], + [ 'C', 3, 40.9 ], + [ 'D', 4, 90.1 ] + ]; + assert.deepEqual(ndframe.values, res); + }); + it("retrieves the row data created from OA ", function () { + let data = { alpha: [ "A", "B" ], count: [ 1, 2 ] }; + let ndframe = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, [ [ "A", 1 ], [ "B", 2 ] ]); + }); + }); + + describe("setIndex", function () { + it("sets the index of an NDframe", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 } ]; + let df = new dfd.NDframe({ data, isSeries: false }); + df.$setIndex([ "A", "B", "C" ]); + assert.deepEqual(df.index, [ "A", "B", "C" ]); + }); + it("Returns the index of an NDframe created from an Array", function () { + let data = [ [ 12, 2, 20 ], [ 90, 5, 23 ], [ 45, 56, 70 ], [ 9, 10, 19 ] ]; + let df = new dfd.NDframe({ data, isSeries: false }); + df.$setIndex([ 10, 20, 30, 40 ]); + assert.deepEqual(df.index, [ 10, 20, 30, 40 ]); + }); + }); + + + describe("dtype", function () { + it("Returns int dtype set during creation of 1DFrame (Series) from an Object", function () { + let data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; + let options = { dtypes: [ 'int32' ], isSeries: true }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ 'int32' ]); + }); + + it("Returns string dtype set during creation of 1DFrame (Series) from an Array", function () { + let data = [ "Alice", "Yemi", "Rising", "Mark" ]; + let options = { dtypes: [ 'string' ], isSeries: true }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ "string" ]); + }); + + it("Returns string dtype automatically inferred from 1DFrame (Series)", function () { + let data = [ "Alice", "Yemi", "Rising", "Mark" ]; + let options = { columns: 'Names', isSeries: true }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ "string" ]); + }); + + it("Returns int dtype automatically inferred from 1DFrame (Series)", function () { + let data = [ 20, 30, 20, 20 ]; + let options = { columns: 'Size', isSeries: true }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ "int32" ]); + }); + it("Returns float dtype automatically inferred from 1DFrame (Series)", function () { + let data = [ 20.1, 30.4, 20.2, 4.23, 20.1 ]; + let options = { columns: 'Size', isSeries: true }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ "float32" ]); + }); + + + it("Returns dtype set during creation of 2DFrame from an Object", function () { + let data = [ { alpha: "A", count: 1 }, { alpha: "B", count: 2 } ]; + let options = { dtypes: [ 'string', 'int32' ] }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ 'string', 'int32' ]); + }); + it("Returns dtype set during creation of 2DFrame from an Array", function () { + let data = [ [ "Alice", 2, 3.0 ], [ "Boy", 5, 6.1 ], [ "Girl", 30, 40 ], [ 39, 89, 78.2 ] ]; + let cols = [ "Name", "Count", "Score" ]; + let options = { columns: cols, dtypes: [ 'string', 'int32', 'float32' ] }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ "string", "int32", "float32" ]); + }); + + it("Returns dtype automatically inferred from 2DFrame", function () { + let data = [ [ "Alice", 2, 3.1 ], [ "Boy", 5, 6.1 ], [ "Girl", 30, 40.2 ], [ 39, 89, 78.2 ] ]; + let cols = [ "Name", "Count", "Score" ]; + let options = { columns: cols }; + let ndframe = new dfd.NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, [ "string", "int32", "float32" ]); + }); + + }); + + describe("Empty NDFrame", function () { + it("Can successfully create an empty NDframe from empty array", function () { + let data = []; + let df = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(df.shape, [ 0, 0 ]); + assert.deepEqual(df.columns, []); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new dfd.NDframe({ data, isSeries: true }); + assert.deepEqual(sf.shape, [ 0, 0 ]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + it("Can successfully create an empty NDframe from undefined data", function () { + let data = undefined; + let df = new dfd.NDframe({ data, isSeries: false }); + assert.deepEqual(df.shape, [ 0, 0 ]); + assert.deepEqual(df.columns, []); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new dfd.NDframe({ data, isSeries: true }); + assert.deepEqual(sf.shape, [ 0, 0 ]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty NDframe", function () { + let df = new dfd.NDframe({ isSeries: false }); + assert.deepEqual(df.shape, [ 0, 0 ]); + assert.deepEqual(df.columns, []); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new dfd.NDframe({ isSeries: true }); + assert.deepEqual(sf.shape, [ 0, 0 ]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty NDframe with columns names", function () { + let data = []; + let df = new dfd.NDframe({ data, columns: [ "A", "B", "C" ], isSeries: false }); + assert.deepEqual(df.shape, [ 0, 3 ]); + assert.deepEqual(df.columns, [ "A", "B", "C" ]); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new dfd.NDframe({ data, columns: [ "A" ], isSeries: true }); + assert.deepEqual(sf.shape, [ 0, 1 ]); + assert.deepEqual(sf.columns, [ "A" ]); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty NDframe with columns names and dtypes", function () { + let data = []; + let df = new dfd.NDframe({ data, columns: [ "A", "B", "C" ], dtypes: [ "string", "string", "int32" ], isSeries: false }); + assert.deepEqual(df.shape, [ 0, 3 ]); + assert.deepEqual(df.columns, [ "A", "B", "C" ]); + assert.deepEqual(df.dtypes, [ "string", "string", "int32" ]); + assert.deepEqual(df.values, []); + let sf = new dfd.NDframe({ data, columns: [ "A" ], dtypes: [ "string" ], isSeries: true }); + assert.deepEqual(sf.shape, [ 0, 1 ]); + assert.deepEqual(sf.columns, [ "A" ]); + assert.deepEqual(sf.dtypes, [ "string" ]); + assert.deepEqual(sf.values, []); + }); + + it("Cannot successfully create an empty NDframe with only columns dtypes", function () { + let data = []; + assert.throws( + () => new dfd.NDframe({ data, dtypes: [ "string", "string", "int32" ], isSeries: false }), + Error, + "DtypeError: columns parameter must be provided when dtypes parameter is provided" + ); + assert.throws( + () => new dfd.NDframe({ data, dtypes: [ "string" ], isSeries: true }), + Error, + "DtypeError: columns parameter must be provided when dtypes parameter is provided" + ); + }); + + }); + + describe("DataFrame supports date object", function () { + it("Can successfully create a DataFrame from an Array with date object", function () { + let data = [ [ "Alice", 2, new Date(2019, 1, 1) ], + [ "Bob", 5, new Date(2019, 1, 2) ], + [ "Charlie", 30, new Date(2019, 1, 3) ], + [ "Dennis", 89, new Date(2019, 1, 4) ] ]; + let columns = [ "Name", "Count", "Date" ]; + + let df = new dfd.NDframe({ data, columns, isSeries: false }); + let dfDtypes = [ 'string', 'int32', 'datetime' ]; + assert.deepEqual(df.dtypes, dfDtypes); + // @ts-ignore + assert.deepEqual(df.values, data); + assert.deepEqual(df.columns, columns); + }); + }); + +}); diff --git a/src/danfojs-browser/tests/core/indexing.test.js b/src/danfojs-browser/tests/core/indexing.test.js new file mode 100644 index 00000000..535759ab --- /dev/null +++ b/src/danfojs-browser/tests/core/indexing.test.js @@ -0,0 +1,429 @@ +/* eslint-disable no-undef */ + +describe("Iloc and Loc based Indexing", function () { + describe("Iloc Index", function () { + it("throw error for wrong row index value", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc(0); }, Error, `rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); + }); + + it("throw error for wrong string split parameter", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ "0;1" ]); }, Error, `Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + }); + + it("throw error for wrong string split value", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ "0:a" ]); }, Error, `Invalid row split parameter. Split parameter must be a number`); + }); + + it("throw error for string split values greater than 2", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ "0:4:2" ]); }, Error, `Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + }); + + it("throw error for row index larger than series length", function () { + let data = [ 1, 2, 34, 5, 6 ]; + + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ 0, 8 ]); }, Error, "Invalid row parameter: Specified index 8 cannot be bigger than index length 5"); + }); + + it("throw error for non-numeric row index", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ 0, "4" ]); }, Error, "Invalid row parameter: row index 4 must be a number"); + }); + + + it("df.iloc works for rows:[0,1]", function () { + let data = [ 1, 2, 34, 5, 6 ]; + + let df = new dfd.Series(data); + + let sf = df.iloc([ 0, 1 ]); + let expected = [ 1, 2 ]; + + assert.deepEqual(sf.values, expected); + }); + + it("df.iloc works for rows:[1]", function () { + let data = [ 1, 2, 34, 5, 6 ]; + + let df = new dfd.Series(data); + + let sf = df.iloc([ 1 ]); + let expected = [ 2 ]; + + assert.deepEqual(sf.values, expected); + }); + + it("correct index is returned for df.iloc rows:[1, 2]", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data, { index: [ "a", "b", "c", "d", "e" ] }); + + let sf = df.iloc([ 1, 4 ]); + let expected = [ "b", "e" ]; + + assert.deepEqual(sf.index, expected); + }); + + + it("row slice with string param works [0:2]", function () { + let data = [ 1, 2, 4, 5, 6, 20, 30, 40, 39, 89, 78 ]; + let df = new dfd.Series(data); + + let sf = df.iloc([ "0:2" ]); + let expected = [ 1, 2 ]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [1:]", function () { + let data = [ 1, 2, 34, 5, 620, 30, 409, 89, 78 ]; + let df = new dfd.Series(data); + + let sf = df.iloc([ "1:" ]); + let expected = [ 2, 34, 5, 620, 30, 409, 89, 78 ]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:2]", function () { + let data = [ 1, 2, 34, 5, 6, 20, 30, 40, 39, 89, 78 ]; + let df = new dfd.Series(data); + let sf = df.iloc([ ":2" ]); + let expected = [ 1, 2 ]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:]", function () { + let data = [ 1, 2, 3, 5, 20, 30, 4039, 89, 78 ]; + let df = new dfd.Series(data); + let expected = [ 1, 2, 3, 5, 20, 30, 4039, 89, 78 ]; + + let sf = df.iloc([ ":" ]); + assert.deepEqual(sf.values, expected); + + }); + + it(`throw error for wrong start index size ["0:20"]`, function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ "0:20" ]); }, Error, `row slice [end] index cannot be bigger than 5`); + }); + + it(`throw error for wrong start index size ["-1:2"]`, function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ "-1:2" ]); }, Error, `row slice [start] index cannot be less than 0`); + }); + + it("check data after column slice", function () { + let data = [ 1, 2, 34, 5, 620, 30, 4039, 89, 78 ]; + let df = new dfd.Series(data); + + let sf = df.iloc([ 0, 1, 6 ]); + let expected = [ 1, 2, 4039 ]; + assert.deepEqual(sf.values, expected); + + }); + + it("iloc works for boolean array", function () { + let data = [ 1, 2, 34, 5, 620 ]; + let df = new dfd.Series(data); + + let sf = df.iloc([ true, true, false, true, false ]); + let expected = [ 1, 2, 5 ]; + assert.deepEqual(sf.values, expected); + + }); + + it("iloc works for boolean array (all true)", function () { + let data = [ 1, 2, 34, 5, 620 ]; + let df = new dfd.Series(data); + + let sf = df.iloc([ true, true, true, true, true ]); + let expected = [ 1, 2, 34, 5, 620 ]; + assert.deepEqual(sf.values, expected); + + }); + it("iloc works for boolean array (all false)", function () { + let data = [ 1, 2, 34, 5, 620 ]; + let df = new dfd.Series(data); + + let sf = df.iloc([ false, false, false, false, false ]); + let expected = []; + assert.deepEqual(sf.values, expected); + + }); + + it("boolean iloc works for DataFrame", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: [ false, false, false, true ] }); + const result = [ [ 'Pear', 10, 250 ] ]; + assert.deepEqual(subDf.values, result); + + }); + + + it("boolean iloc works for DataFrame with specified columns", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: [ false, false, false, true ], columns: [ 0, 2 ] }); + const result = [ [ 'Pear', 250 ] ]; + assert.deepEqual(subDf.values, result); + + }); + + it("boolean iloc works for DataFrame with Series bool selector", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.iloc({ rows: df["Count"].gt(10), columns: [ 0, 2 ] }); + const result = [ [ 'Apples', 200 ], [ 'Banana', 40 ] ]; + assert.deepEqual(subDf.values, result); + + }); + }); + + describe("Loc Index", function () { + it("throw error for wrong row index value", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.loc(0); }, Error, `rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); + }); + + it("throw error for wrong string split parameter", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.loc([ "a;1" ]); }, Error, `IndexError: Specified index (a;1) not found`); + }); + it(`throw error for wrong string split parameter ("0;1")`, function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.loc([ "0;1" ]); }, Error, `IndexError: Specified index (0;1) not found`); + }); + + it("throw error for wrong string split end value", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.loc([ "0:a" ]); }, Error, `IndexError: Specified end index not found`); + }); + + it("throw error for string split values greater than 2", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.loc([ "0:4:2" ]); }, Error, `Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + }); + + it("throw error for row index larger than series length", function () { + let data = [ 1, 2, 34, 5, 6 ]; + + let df = new dfd.Series(data); + assert.throws(function () { df.loc([ 0, 8 ]); }, Error, "IndexError: Specified index (8) not found"); + }); + + it("throw error for non-numeric row index not found", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.loc([ 0, "4" ]); }, Error, "IndexError: Specified index (4) not found"); + }); + + + it("df.iloc works for rows:[0,1]", function () { + let data = [ 1, 2, 34, 5, 6 ]; + + let df = new dfd.Series(data); + + let sf = df.loc([ 0, 1 ]); + let expected = [ 1, 2 ]; + + assert.deepEqual(sf.values, expected); + }); + + it("df.iloc works for rows:[1]", function () { + let data = [ 1, 2, 34, 5, 6 ]; + + let df = new dfd.Series(data); + + let sf = df.loc([ 1 ]); + let expected = [ 2 ]; + + assert.deepEqual(sf.values, expected); + }); + + it("correct index is returned for df.loc([1, 4])", function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data, { index: [ "a", "b", "c", "d", "e" ] }); + + let sf = df.loc([ "b", "e" ]); + let expected = [ "b", "e" ]; + assert.deepEqual(sf.index, expected); + }); + + it("row slice with string param works [0:2]", function () { + let data = [ 1, 2, 4, 5, 6, 20, 30, 40, 39, 89, 78 ]; + let df = new dfd.Series(data); + + let sf = df.loc([ "0:2" ]); + let expected = [ 1, 2 ]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [1:]", function () { + let data = [ 1, 2, 34, 5, 620, 30, 409, 89, 78 ]; + let df = new dfd.Series(data); + + let sf = df.loc([ "1:" ]); + let expected = [ 2, 34, 5, 620, 30, 409, 89, 78 ]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:2]", function () { + let data = [ 1, 2, 34, 5, 6, 20, 30, 40, 39, 89, 78 ]; + let df = new dfd.Series(data); + let sf = df.loc([ ":2" ]); + let expected = [ 1, 2 ]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:]", function () { + let data = [ 1, 2, 3, 5, 20, 30, 4039, 89, 78 ]; + let df = new dfd.Series(data); + let expected = [ 1, 2, 3, 5, 20, 30, 4039, 89, 78 ]; + + let sf = df.loc([ ":" ]); + assert.deepEqual(sf.values, expected); + + }); + + it(`throw error for wrong start index size ["0:20"]`, function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ "0:20" ]); }, Error, `row slice [end] index cannot be bigger than 5`); + }); + + it(`throw error for wrong start index size ["-1:2"]`, function () { + let data = [ 1, 2, 34, 5, 6 ]; + let df = new dfd.Series(data); + assert.throws(function () { df.iloc([ "-1:2" ]); }, Error, `row slice [start] index cannot be less than 0`); + }); + + it("check data after column slice", function () { + let data = [ 1, 2, 34, 5, 620, 30, 4039, 89, 78 ]; + let df = new dfd.Series(data); + + let sf = df.loc([ 0, 1, 6 ]); + let expected = [ 1, 2, 4039 ]; + assert.deepEqual(sf.values, expected); + + }); + + it("loc works for boolean array", function () { + let data = [ 1, 2, 34, 5, 620 ]; + let df = new dfd.Series(data); + + let sf = df.loc([ true, true, false, true, false ]); + let expected = [ 1, 2, 5 ]; + assert.deepEqual(sf.values, expected); + + }); + + it("loc works for boolean array (all true)", function () { + let data = [ 1, 2, 34, 5, 620 ]; + let df = new dfd.Series(data); + + let sf = df.loc([ true, true, true, true, true ]); + let expected = [ 1, 2, 34, 5, 620 ]; + assert.deepEqual(sf.values, expected); + + }); + it("loc works for boolean array (all false)", function () { + let data = [ 1, 2, 34, 5, 620 ]; + let df = new dfd.Series(data); + + let sf = df.loc([ false, false, false, false, false ]); + let expected = []; + assert.deepEqual(sf.values, expected); + + }); + + it("boolean loc works for DataFrame", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.loc({ rows: [ false, false, false, true ] }); + const result = [ [ 'Pear', 10, 250 ] ]; + assert.deepEqual(subDf.values, result); + + }); + + + it("boolean loc works for DataFrame with specified columns", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.loc({ rows: [ false, false, false, true ], columns: [ "Name", "Price" ] }); + const result = [ [ 'Pear', 250 ] ]; + assert.deepEqual(subDf.values, result); + + }); + + it("boolean loc works for DataFrame with Series bool selector", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.loc({ rows: df["Count"].gt(10), columns: [ "Name", "Price" ] }); + const result = [ [ 'Apples', 200 ], [ 'Banana', 40 ] ]; + assert.deepEqual(subDf.values, result); + + }); + + it("loc with no matches create a Empty DataFrame conserving columns information", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new dfd.DataFrame(data); + const subDf = df.loc({ rows: df["Count"].gt(50) }); + + assert.deepEqual(subDf.values, []); + assert.deepEqual(subDf.shape, [ 0, 3 ]); + assert.deepEqual(subDf.columns, [ "Name", "Count", "Price" ]); + assert.deepEqual(subDf.dtypes, [ "string", "int32", "int32" ]); + + }); + }); + +}); diff --git a/src/danfojs-browser/tests/core/series.test.js b/src/danfojs-browser/tests/core/series.test.js new file mode 100644 index 00000000..cd47d6ba --- /dev/null +++ b/src/danfojs-browser/tests/core/series.test.js @@ -0,0 +1,1684 @@ +/* eslint-disable no-undef */ + +describe("Series Functions", () => { + + describe("head", function () { + it("Gets the first 2 rows in a Series", function () { + const data = [ 1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78 ]; + const cols = [ "A" ]; + const sf = new dfd.Series(data, { columns: cols }); + assert.deepEqual(sf.head(2).values, [ 1, 2 ]); + assert.deepEqual(sf.head(5).values, [ 1, 2, 3, 4, 5 ]); + }); + it("Returns all rows when DataFrame length is less than rows", function () { + const data = [ 1, 2, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.head().values, data); + + }); + it("throw error when row specified is less than 0", function () { + const data = [ 1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78 ]; + const sf = new dfd.Series(data); + assert.throws(function () { assert.deepEqual(sf.head(-1).values, data); }, Error, `ParamError: Number of rows cannot be less than 1`); + }); + }); + + + describe("tail", function () { + it("Prints the last n rows of a Series", function () { + const data = [ 1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.tail(2).values, [ 89, 78 ]); + assert.deepEqual(sf.tail(4).values, [ 40, 39, 89, 78 ]); + + }); + it("Returns all rows when DataFrame length is less than rows", function () { + const data = [ 1, 2, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.tail().values, data); + + }); + it("throw error when row specified is less than 0", function () { + const data = [ "Boy", "Girl", "Man", "Woman", "Tall" ]; + const cols = [ "Items" ]; + const sf = new dfd.Series(data, { columns: cols }); + assert.throws(function () { assert.deepEqual(sf.tail(-1).values, data); }, Error, `ParamError: Number of rows cannot be less than 1`); + }); + }); + + describe("sample", function () { + it("Samples n number of random elements from a DataFrame", async function () { + const data = [ 1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78 ]; + const sf = new dfd.Series(data); + assert.deepEqual((await sf.sample(7)).values.length, 7); + }); + it("Return all values if n of sample -1", async function () { + const data = [ 1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78 ]; + const sf = new dfd.Series(data); + assert.deepEqual((await sf.sample(-1)).values.length, data.length); + }); + + it("Throw error if n is greater than length of Series", async function () { + const data = [ 1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78 ]; + const sf = new dfd.Series(data); + try { + await sf.sample(100); + } catch (e) { + expect(e.message).to.eql('Sample size n cannot be bigger than size of dataset'); + } + }); + }); + + describe("add", function () { + it("Return Addition of series with another series", function () { + const data = [ 1, 2, 3, 4, 5, 6 ]; + const data2 = [ 30, 40, 39, 1, 2, 1 ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf.add(sf2).values, [ 31, 42, 42, 5, 7, 7 ]); + }); + it("Return Addition of series with a single value (Broadcasting)", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.add(1).values, [ 2, 3, 4, 5, 6 ]); + }); + it("Return Addition of series with another series inplace", function () { + const data = [ 1, 2, 3, 4, 5, 6 ]; + const data2 = [ 30, 40, 39, 1, 2, 1 ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + sf.add(sf2, { inplace: true }); + assert.deepEqual(sf.values, [ 31, 42, 42, 5, 7, 7 ]); + }); + it("Return Addition of series with a single value (Broadcasting) inplace", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + sf.add(1, { inplace: true }); + assert.deepEqual(sf.values, [ 2, 3, 4, 5, 6 ]); + }); + it("Dtype is properly updated on addition of series with a single float value inplace", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + sf.add(1.23, { inplace: true }); + assert.deepEqual(sf.dtypes[0], "float32"); + assert.deepEqual(sf.values, [ 2.23, 3.23, 4.23, 5.23, 6.23 ]); + }); + it("Add works properly when using tfjs add function", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + sf.add(1.23, { inplace: true }); + assert.deepEqual(sf.dtypes[0], "float32"); + assert.deepEqual(sf.values, [ 2.23, 3.23, 4.23, 5.23, 6.23 ]); + }); + it("Add works properly when using tfjs add function on Series", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series([ 1.23, 1.23, 1.23, 1.23, 1.23 ]); + sf.add(sf2, { inplace: true }); + assert.deepEqual(sf.values, [ 2.23, 3.23, 4.23, 5.23, 6.23 ]); + }); + it("Throws type error on addition of string type", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ "A", "B", "C", "d" ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws( + () => { + sf.add(sf2); + }, + Error, + "DtypeError: String data type does not support add operation" + ); + }); + it("Throws length error if series length mixmatch", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ 1, 2, 3, 4, 5, 6 ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws(() => { sf.add(sf2); }, Error, "Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); + }); + }); + + describe("sub", function () { + it("Return Subtraction of series with another series", function () { + const data1 = [ 30, 40, 39, 1, 2, 1 ]; + const data2 = [ 1, 2, 3, 4, 5, 6 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.sub(sf2).values, [ 29, 38, 36, -3, -3, -5 ]); + }); + it("Return Subtraction of series with a single value (Broadcasting)", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.sub(1).values, [ 0, 1, 2, 3, 4 ]); + }); + it("Throws type error on Subtraction of string type", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ "A", "B", "C", "d" ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws( + () => { + sf.sub(sf2); + }, + Error, + "DtypeError: String data type does not support sub operation" + ); + }); + it("Throws length error if series length mixmatch", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ 1, 2, 3, 4, 5, 6 ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws(() => { sf.sub(sf2); }, Error, "Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); + }); + }); + + describe("mul", function () { + it("Return multiplication of series with another series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 1, 2, 3, 4 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.mul(sf2).values, [ 30, 80, 9, 20 ]); + }); + it("Return multiplication of series with a single value (Broadcasting)", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.mul(1).values, [ 1, 2, 3, 4, 5 ]); + }); + it("Throws type error on multiplication of string type", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ "A", "B", "C", "d" ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws(() => { sf.mul(sf2); }, Error, "DtypeError: String data type does not support mul operation"); + }); + it("Throws length error if series length mixmatch", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ 1, 2, 3, 4, 5, 6 ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws(() => { sf.mul(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); + }); + }); + + + describe("div", function () { + it("Return float division of series with another series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 1, 2, 3, 4 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.div(sf2).values, [ 30, 20, 1, 1.25 ]); + }); + it("Return integer division of series with another series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 1, 2, 3, 4 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.div(sf2, false).values, [ 30, 20, 1, 1.25 ]); + }); + it("Return division of series with a single value (Broadcasting)", function () { + const data = [ 10, 2, 3, 90 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.div(2).values, [ 5, 1, 1.5, 45 ]); + }); + it("Throws type error on division of string type", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ "A", "B", "C", "d" ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws(() => { sf.div(sf2); }, Error, `DtypeError: String data type does not support div operation`); + }); + it("Throws length error if series length mixmatch", function () { + const data = [ 1, 2, 3, 4 ]; + const data2 = [ 1, 2, 3, 4, 5, 6 ]; + const sf = new dfd.Series(data); + const sf2 = new dfd.Series(data2); + assert.throws(() => { sf.div(sf2); }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)"); + }); + }); + + describe("pow", function () { + it("Return Exponetial power of series with another series", function () { + const data1 = [ 2, 3, 4, 5 ]; + const data2 = [ 1, 2, 3, 0 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.pow(sf2).values, [ 2, 9, 64, 1 ]); + }); + it("Return Exponetial power of series with a single value (Broadcasting)", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.pow(2).values, [ 1, 4, 9, 16, 25 ]); + }); + }); + + describe("mod", function () { + it("Return modulo of series with another float series", function () { + const data1 = [ 2, 30, 4, 5 ]; + const data2 = [ 1.1, 2.2, 3.3, 2.4 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + const expected = [ + 0.8999999999999999, + 1.3999999999999977, + 0.7000000000000002, + 0.20000000000000018 + ]; + assert.deepEqual(sf1.mod(sf2).values, expected); + }); + it("Return modulo of series with another int series", function () { + const data1 = [ 2, 30, 4, 5 ]; + const data2 = [ 1, 2, 3, 1 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.mod(sf2).values, [ 0, 0, 1, 0 ]); + }); + it("Return modulo power of series with a single value (Broadcasting)", function () { + const data = [ 1, 2, 3, 4, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.mod(2).values, [ 1, 0, 1, 0, 1 ]); + }); + }); + + describe("toString", function () { + it("Prints a series to the console", async function () { + const data = [ 1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78 ]; + const sf = new dfd.Series(data); + sf.print(); + }); + it("Prints a series to the console", async function () { + const data = [ "This is a long text group and I want it to print in full", + "This is a long text group and I want it to print in full" ]; + const sf = new dfd.Series(data); + sf.print(); + }); + }); + + describe("Empty Series", function () { + it("Can successfully create an empty Series from empty array", function () { + const data = []; + const sf = new dfd.Series(data); + assert.deepEqual(sf.shape, [ 0, 0 ]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty Series", function () { + const sf = new dfd.Series(); + assert.deepEqual(sf.shape, [ 0, 0 ]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + }); + + describe("mean", function () { + it("Computes the mean of elements in a int series", function () { + const data1 = [ 30, 40, 3, 5, NaN ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.mean(), 19.5); + }); + it("Computes the mean of elements in a int series using TFJS", function () { + const data1 = [ 30, 40, 3, 5, NaN ]; + const sf = new dfd.Series(data1, { config: { useTfjsMathFunctions: true } }); + assert.deepEqual(sf.mean(), 19.5); + }); + it("Computes the mean of elements in a float series", function () { + const data1 = [ 30.1, 40.2, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.mean(), 19.625); + }); + it("Computes the mean of elements in a float series with NaN", function () { + const data1 = [ 30.1, 40.2, 3.1, 5.1, NaN ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.mean(), 19.625); + }); + it("Computes the mean of a boolean series", function () { + const data1 = [ true, false, false, false, true, true, false, true ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.mean(), 0.5); + }); + it("Throws error if dtype is string", function () { + const data1 = [ "boy", "girl", "Man" ]; + const sf = new dfd.Series(data1); + assert.throws( + () => { + sf.mean(); + }, + Error, + "DtypeError: String data type does not support mean operation" + ); + }); + }); + + describe("median", function () { + it("Computes the median value of elements across int Series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.median(), 17.5); + }); + it("Computes the median value of elements across float Series", function () { + const data1 = [ 30.1, 40.2, 3.1, 5.1, NaN ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.median(), 17.6); + }); + }); + + describe("sum", function () { + it("Sum values of a Int Series", function () { + const data1 = [ 30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.sum(), 131); + }); + it("Sum values of a Float Series", function () { + const data1 = [ 30.1, 3.1, 40.2, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.sum(), 81.6); + }); + it("Sum values of a bool Series", function () { + const data1 = [ true, true, false, false, false ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.sum(), 2); + }); + it("Sum values a Series with missing values", function () { + const data1 = [ 11, NaN, 2, 2 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.sum(), 15); + }); + }); + + describe("mode", function () { + it("Computes the multi-modal values of a Series", function () { + const data1 = [ 30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.mode(), [ 5, 3 ]); + }); + it("Computes the modal value of a Series", function () { + const data1 = [ 30.1, 3.1, 40.2, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.mode(), [ 3.1 ]); + }); + }); + + describe("min", function () { + it("Returns the single smallest elementin a Series", function () { + const data = [ 30, 40, 3, 5 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.min(), 3); + }); + it("Computes the minimum of elements across an float Series", function () { + const data1 = [ 30.1, 40.2, 3.12, 5.1 ]; + const sf = new dfd.Series(data1, { dtypes: [ "float32" ] }); + assert.deepEqual(Number(sf.min().toFixed(2)), 3.12); + }); + }); + + describe("max", function () { + it("Computes the maximum of elements across dimensions of a Series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.max(), 40); + }); + it("Return sum of float values in a series", function () { + const data1 = [ 30.1, 40.21, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(Number(sf.max().toFixed(2)), 40.21); + }); + it("Throws error on addition of string Series", function () { + const data1 = [ "boy", "gitl", "woman", "man" ]; + const sf = new dfd.Series(data1); + assert.throws( + () => { + sf.max(); + }, + Error, + "DtypeError: String data type does not support max operation" + ); + }); + }); + + describe("count", function () { + it("Returns the count of non NaN values in a string Series", function () { + const data = [ "boy", "gitl", "woman", NaN ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.count(), 3); + }); + it("Returns the count of values in a string Series without NaN", function () { + const data = [ "boy", "gitl", "woman", "Man" ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.count(), 4); + }); + it("Returns the count of non NaN values in a int Series", function () { + const data = [ 20, 30, NaN, 2, NaN, 30, 21 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.count(), 5); + }); + it("Returns the count of non NaN values in a float Series", function () { + const data = [ 20.1, 30.4, NaN, 2.1, NaN, 30.0, 21.3 ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.count(), 5); + }); + }); + + describe("std", function () { + it("Computes the standard of elements in a int series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.std(), 18.375708603116962); + }); + it("Computes the standard deviation of elements in a float series", function () { + const data1 = [ 30.1, 40.2, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.std(), 18.412925713566906); + }); + it("Computes the standard deviation of elements in a float series with missing values", function () { + const data1 = [ 30, 40, 3, 5, undefined ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.std(), 18.375708603116962); + }); + }); + + describe("var", function () { + it("Computes the variance of elements in a int series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.var(), 337.6666666666667); + }); + it("Computes the variance of elements in a float series", function () { + const data1 = [ 30.1, 40.2, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.var(), 339.03583333333336); + }); + it("Computes the variance of elements in a int series with missing values", function () { + const data1 = [ 30, undefined, 40, 3, 5 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.var(), 337.6666666666667); + }); + }); + + describe("round", function () { + it("Rounds elements in a Series to nearest whole number", function () { + const data1 = [ 30.21091, 40.190901, 3.564, 5.0212 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.round().values, [ 30.2, 40.2, 3.6, 5 ]); + }); + it("Rounds elements in a Series to 1dp", function () { + const data1 = [ 30.21091, 40.190901, 3.564, 5.0212 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.round(1).values, [ 30.2, 40.2, 3.6, 5.0 ]); + }); + it("Rounds elements in a Series to 2dp", function () { + const data1 = [ 30.2191, 40.190901, 3.564, 5.0212 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.round(2).values, [ 30.22, 40.19, 3.56, 5.02 ]); + }); + + it("Rounds elements in a Series to 2dp inplace", function () { + const data1 = [ 30.2191, 40.190901, 3.564, 5.0212 ]; + const sf = new dfd.Series(data1); + sf.round(2, { inplace: true }); + assert.deepEqual(sf.values, [ 30.22, 40.19, 3.56, 5.02 ]); + }); + + it("Rounds elements in a Series with missing values to 2dp", function () { + const data1 = [ 30.2191, undefined, 3.564, NaN ]; + const sf = new dfd.Series(data1); + sf.round(2, { inplace: true }); + assert.deepEqual(sf.values, [ 30.22, undefined, 3.56, NaN ]); + }); + + }); + + describe("maximum", function () { + it("Returns the maximum of two series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 10, 41, 2, 0 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.maximum(sf2).values, [ 30, 41, 3, 5 ]); + }); + it("Returns the maximum of series and Array", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 10, 41, 2, 0 ]; + const sf1 = new dfd.Series(data1); + assert.deepEqual(sf1.maximum([ 10, 41, 2, 0 ]).values, [ 30, 41, 3, 5 ]); + }); + it("Returns the maximum of series and scalar", function () { + const data1 = [ 30, 40, 3, 5 ]; + const sf1 = new dfd.Series(data1); + assert.deepEqual(sf1.maximum(10).values, [ 30, 40, 10, 10 ]); + }); + it("Throws error on checking maximum of incompatible Series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 10, 41, 2 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.throws( + () => { + sf1.maximum(sf2); + }, + Error, + "ParamError: Row length mismatch. Length of other (3), must be the same as Ndframe (4)" + ); + }); + }); + + describe("minimum", function () { + it("Returns the minimum of two series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 10, 41, 2, 0 ]; + const sf1 = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + assert.deepEqual(sf1.minimum(sf2).values, [ 10, 40, 2, 0 ]); + }); + it("Returns the minimum of series and array", function () { + const data1 = [ 30, 40, 3, 5 ]; + const data2 = [ 10, 41, 2, 0 ]; + const sf1 = new dfd.Series(data1); + assert.deepEqual(sf1.minimum(data2).values, [ 10, 40, 2, 0 ]); + }); + it("Returns the minimum of two series", function () { + const data1 = [ 30, 40, 3, 5 ]; + const sf1 = new dfd.Series(data1); + assert.deepEqual(sf1.minimum(10).values, [ 10, 10, 3, 5 ]); + }); + }); + + describe("isNa", function () { + it("Return a boolean same-sized object indicating if string Series contain NaN", function () { + const data1 = [ NaN, undefined, "girl", "Man" ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.isNa().values, [ true, true, false, false ]); + }); + it("Return a boolean same-sized object indicating if float Series values are NaN", function () { + const data1 = [ 30.21091, NaN, 3.564, undefined ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.isNa().values, [ false, true, false, true ]); + }); + it("Return a boolean same-sized object indicating if int Series values are NaN", function () { + const data1 = [ 30, 40, 3, 5, undefined, null ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.isNa().values, [ + false, + false, + false, + false, + true, + true + ]); + }); + }); + + describe("fillNa", function () { + it("replace all NaN value with specified value", function () { + const data = [ NaN, 1, 2, 33, 4, null, 5, 6, 7, 8 ]; + const sf = new dfd.Series(data); + const sfVal = [ -999, 1, 2, 33, 4, -999, 5, 6, 7, 8 ]; + sf.fillNa(-999, { inplace: true }); + assert.deepEqual(sf.values, sfVal); + }); + it("replace all NaN value in string Series with specified value", function () { + const data = [ NaN, "boy", NaN, "hey", "Man", undefined ]; + const sf = new dfd.Series(data); + const sfVal = [ "filled", "boy", "filled", "hey", "Man", "filled" ]; + const sfFill = sf.fillNa("filled"); + assert.deepEqual(sfFill.values, sfVal); + }); + it("Data is in right format after filling", function () { + const data = [ NaN, "boy", NaN, "hey", "Man", undefined ]; + const sf = new dfd.Series(data); + const sfVal = [ "filled", "boy", "filled", "hey", "Man", "filled" ]; + const sfFill = sf.fillNa("filled"); + assert.deepEqual(sfFill.values, sfVal); + assert.deepEqual(sfFill.$dataIncolumnFormat, sfVal); + + }); + }); + + describe("sortValues", function () { + it("Sort values in a Series in ascending order (not inplace)", function () { + const sf = new dfd.Series([ 20, 30, 1, 2, 4, 57, 89, 0, 4 ]); + const result = [ 0, 1, 2, 4, 4, 20, 30, 57, 89 ]; + const sortedSf = sf.sortValues(); + assert.deepEqual(sortedSf.values, result); + assert.deepEqual(sortedSf.$dataIncolumnFormat, result); + + }); + it("confirms that sortValues in ascending order does not happen inplace", function () { + const sf = new dfd.Series([ 20, 30, 1, 2, 4, 57, 89, 0, 4 ]); + const result = [ 0, 1, 2, 4, 4, 20, 30, 57, 89 ]; + const expectedIndex = [ 7, 2, 3, 8, 4, 0, 1, 5, 6 ]; + sf.sortValues({ ascending:true, inplace: true }); + assert.deepEqual(sf.values, result); + assert.deepEqual(sf.index, expectedIndex); + }); + it("Sort values in a Series in Descending order", function () { + const sf = new dfd.Series([ 20, 30, 1, 2, 4, 57, 89, 0, 4 ]); + const result = [ 89, 57, 30, 20, 4, 4, 2, 1, 0 ]; + const sortedSf = sf.sortValues({ ascending: false }); + assert.deepEqual(sortedSf.values, result); + }); + it("confirms that sortValues in descending order happens inplace", function () { + const sf = new dfd.Series([ 20, 30, 1, 2, 4, 57, 89, 0, 4 ]); + const result = [ 89, 57, 30, 20, 4, 4, 2, 1, 0 ]; + sf.sortValues({ ascending: false, inplace: true }); + assert.deepEqual(sf.values, result); + }); + it("Confirms that series index is sorted in ascending order (not in inplace)", function () { + const sf = new dfd.Series([ 20, 30, 1, 2, 4, 57, 89, 0, 4 ]); + const result = [ 7, 2, 3, 8, 4, 0, 1, 5, 6 ]; + const sortedSf = sf.sortValues(); + assert.deepEqual(sortedSf.index, result); + }); + it("Confirms that series index is sorted in descending order (not in inplace)", function () { + const sf = new dfd.Series([ 20, 30, 1, 2, 4, 57, 89, 0, 4 ]); + const result = [ 6, 5, 1, 0, 4, 8, 3, 2, 7 ]; + const sortedSf = sf.sortValues({ ascending: false }); + assert.deepEqual(sortedSf.index, result); + }); + it("Sort string values in a Series", function () { + const sf = new dfd.Series([ "boy", "zebra", "girl", "man" ]); + const result = [ "boy", "girl", "man", "zebra" ]; + const sortedSf = sf.sortValues({ ascending: false }); + assert.deepEqual(sortedSf.values, result); + }); + + it("Index is retained after sort (ascending=true)", function () { + let index = [ "apple", "banana", "orange", "grape" ]; + let value = [ 3, 6, 2, 9 ]; + + let sf = new dfd.Series(value, { index }); + sf.sortValues().print(); + const expectedValues = [ 2, 3, 6, 9 ]; + const expectedIndex = [ "orange", "apple", "banana", "grape" ]; + const sortedSf = sf.sortValues(); + assert.deepEqual(sortedSf.values, expectedValues); + assert.deepEqual(sortedSf.index, expectedIndex); + }); + it("Index is retained after sort (ascending=false)", function () { + let index = [ "apple", "banana", "orange", "grape" ]; + let value = [ 3, 6, 2, 9 ]; + + let sf = new dfd.Series(value, { index }); + sf.sortValues().print(); + const expectedValues = [ 9, 6, 3, 2 ]; + const expectedIndex = [ "grape", "banana", "apple", "orange" ]; + const sortedSf = sf.sortValues({ ascending: false }); + assert.deepEqual(sortedSf.values, expectedValues); + assert.deepEqual(sortedSf.index, expectedIndex); + }); + + it("Index is retained after inplace sort (ascending=false)", function () { + let index = [ "apple", "banana", "orange", "grape" ]; + let value = [ 3, 6, 2, 9 ]; + + let sf = new dfd.Series(value, { index }); + sf.sortValues().print(); + const expectedValues = [ 9, 6, 3, 2 ]; + const expectedIndex = [ "grape", "banana", "apple", "orange" ]; + sf.sortValues({ ascending: false, inplace: true }); + assert.deepEqual(sf.values, expectedValues); + assert.deepEqual(sf.index, expectedIndex); + }); + + }); + + describe("describe", function () { + it("Computes the descriptive statistics on an int Series", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.describe().round().values, [ + 7, + 27, + 17.4, + 10, + 23, + 56, + 302 + ]); + }); + it("Computes the descriptive statistics on a float Series", function () { + const data1 = [ 30.1, 40.2, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.describe().round().values, [ + 4, + 19.6, + 18.4, + 3.1, + 17.6, + 40.2, + 339 + ]); + }); + it("Computes the descriptive statistics on a float Series", function () { + const data1 = [ 30.1, 40.2, 3.1, 5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.describe().index, [ + "count", + "mean", + "std", + "min", + "median", + "max", + "variance" + ]); + }); + }); + + describe("resetIndex", function () { + it("resets the index of a Series", function () { + const data = [ + { alpha: "A", count: 1 }, + { alpha: "B", count: 2 }, + { alpha: "C", count: 3 } + ]; + const df = new dfd.Series(data, { index: [ "one", "two", "three" ] }); + const dfReset = df.resetIndex(); + assert.deepEqual(dfReset.index, [ 0, 1, 2 ]); + }); + it("Reset the index of a Series created from an Array", function () { + const data = [ 1, 2, 3, 4, 5, 6 ]; + const df = new dfd.Series(data, { index: [ "one", "two", "three", "four", "five", "six" ] }); + const dfNew = df.resetIndex(); + assert.deepEqual(dfNew.index, [ 0, 1, 2, 3, 4, 5 ]); + }); + it("checks that the original series changed after reseting new index inplace", function () { + const data = [ + { index: "A", count: 1 }, + { index: "B", count: 2 }, + { index: "C", count: 3 } + ]; + const df = new dfd.Series(data, { index: [ "one", "two", "three" ] }); + df.resetIndex({ inplace: true }); + assert.deepEqual(df.index, [ 0, 1, 2 ]); + }); + }); + + describe("setIndex", function () { + it("sets the index of an Series", function () { + const data = [ + { alpha: "A", count: 1 }, + { alpha: "B", count: 2 }, + { alpha: "C", count: 3 } + ]; + const df = new dfd.Series(data); + const dfNew = df.setIndex([ "one", "two", "three" ]); + assert.deepEqual(dfNew.index, [ "one", "two", "three" ]); + assert.notDeepEqual(df.index, dfNew.index); + }); + it("checks that the original series is not modified after setting new index not-inplace", function () { + const data = [ + { alpha: "A", count: 1 }, + { alpha: "B", count: 2 }, + { alpha: "C", count: 3 } + ]; + const df = new dfd.Series(data); + const dfNew = df.setIndex([ "one", "two", "three" ]); + assert.notDeepEqual(df.index, dfNew.index); + }); + it("sets the index of an Series inplace", function () { + const data = [ 12, 2, 20, 50 ]; + const df = new dfd.Series(data); + df.setIndex([ "one", "two", "three", "four" ], { inplace: true }); + assert.deepEqual(df.index, [ "one", "two", "three", "four" ]); + }); + it("Throws index not found error", function () { + const data = [ 12, 2, 20, 50 ]; + const df = new dfd.Series(data); + assert.throws(() => { + df.setIndex(); + }, Error, + "Param Error: Must specify index array" + ); + }); + }); + + describe("Map", function () { + it("map series element to object keys", function () { + const sf = new dfd.Series([ 1, 2, 3, 4 ]); + const map = { 1: "ok", 2: "okie", 3: "frit", 4: "gop" }; + const rslt = [ "ok", "okie", "frit", "gop" ]; + assert.deepEqual(sf.map(map).values, rslt); + }); + it("map series element to object keys inplace", function () { + const sf = new dfd.Series([ 1, 2, 3, 4 ]); + const map = { 1: "ok", 2: "okie", 3: "frit", 4: "gop" }; + const rslt = [ "ok", "okie", "frit", "gop" ]; + sf.map(map, { inplace: true }); + assert.deepEqual(sf.values, rslt); + }); + it("map series element to incomplete object keys", function () { + const sf = new dfd.Series([ 1, 2, 3, 4 ]); + const map = { 1: "ok", 2: "okie", 4: "gop" }; + const rslt = [ "ok", "okie", 3, "gop" ]; + sf.map(map, { inplace: true }); + assert.deepEqual(sf.values, rslt); + }); + it("map series element to a function statement", function () { + const sf = new dfd.Series([ 1, 2, 3, 4 ]); + const func_map = (x) => { + return x + 1; + }; + const rslt = [ 2, 3, 4, 5 ]; + assert.deepEqual(sf.map(func_map).values, rslt); + }); + + it("map series element to a function statement inplace", function () { + const sf = new dfd.Series([ 1, 2, 3, 4 ]); + const func_map = (x) => { + return x + 1; + }; + const rslt = [ 2, 3, 4, 5 ]; + sf.map(func_map, { inplace: true }); + assert.deepEqual(sf.values, rslt); + }); + + it("map passes along the index", function () { + const sf = new dfd.Series([ 1, 2, 3, 4 ]); + const func_map = (x, i) => { + return x + i; + }; + const rslt = [ 1, 3, 5, 7 ]; + sf.map(func_map, { inplace: true }); + assert.deepEqual(sf.values, rslt); + }); + }); + + describe("Apply", function () { + it("apply a function to a series element", function () { + const sf = new dfd.Series([ 1, 2, 3, 4, 5, 6, 7, 8 ]); + const applyFunc = (x) => { + return x + x; + }; + + const rslt = [ 2, 4, 6, 8, 10, 12, 14, 16 ]; + assert.deepEqual(sf.apply(applyFunc).values, rslt); + }); + + it("apply a function to a series element inplace", function () { + const sf = new dfd.Series([ 1, 2, 3, 4, 5, 6, 7, 8 ]); + const applyFunc = (x) => { + return x + x; + }; + + const rslt = [ 2, 4, 6, 8, 10, 12, 14, 16 ]; + sf.apply(applyFunc, { inplace: true }); + assert.deepEqual(sf.values, rslt); + }); + }); + + describe("unique", function () { + it("returns the unique values in a Series of type int", function () { + const sf = new dfd.Series([ 1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5 ]); + const expected = [ 1, 2, 3, 4, 5, 6, 7, 8, 22 ]; + assert.deepEqual(sf.unique().values, expected); + }); + it("returns the unique values in a Series of type string", function () { + const sf = new dfd.Series([ "a", "a", "b", "c", "c", "d", "e", "d", "d", "e" ]); + const expected = [ "a", "b", "c", "d", "e" ]; + assert.deepEqual(sf.unique().values, expected); + }); + it("returns the unique values in a Series of type string", function () { + const sf = new dfd.Series([ "a", "a", "b", "c", "c", "d", "e", "d", "d", "e" ]); + const expected = [ "a", "b", "c", "d", "e" ]; + assert.deepEqual(sf.unique().values, expected); + }); + }); + + describe("nUnique", function () { + it("returns the number of unique values in a Series of type string", function () { + const sf = new dfd.Series([ "a", "a", "b", "c", "c", "d", "e", "d", "d", "e" ]); + assert.deepEqual(sf.nUnique(), 5); + }); + it("returns the number of unique values in a Series of type int32", function () { + const sf = new dfd.Series([ 1, 2, 3, 4, 3, 4, 3, 50, 4, 4, 4, 1 ]); + assert.deepEqual(sf.nUnique(), 5); + }); + }); + + describe("valueCounts", function () { + it("returns the unique values and their counts in a Series of type int", function () { + const sf = new dfd.Series([ 1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5 ]); + const expectedIndex = [ 1, 2, 3, 4, 5, 6, 7, 8, 22 ]; + const expectedVals = [ 3, 1, 1, 1, 4, 1, 1, 2, 1 ]; + assert.deepEqual(sf.valueCounts().values, expectedVals); + assert.deepEqual(sf.valueCounts().index, expectedIndex); + }); + it("returns the unique values and their counts in a Series of type string", function () { + const sf = new dfd.Series([ "a", "a", "b", "c", "c", "d", "e", "d", "d", "e" ]); + const expectedVals = [ 2, 1, 2, 3, 2 ]; + const expectedIndex = [ "a", "b", "c", "d", "e" ]; + assert.deepEqual(sf.valueCounts().values, expectedVals); + assert.deepEqual(sf.valueCounts().index, expectedIndex); + }); + it("returns the unique values and their counts in a Series of type boolean", function () { + const sf = new dfd.Series([ true, false, false, true, true ]); + const expectedVals = [ 3, 2 ]; + const expectedIndex = [ "true", "false" ]; + assert.deepEqual(sf.valueCounts().values, expectedVals); + assert.deepEqual(sf.valueCounts().index, expectedIndex); + }); + }); + + describe("abs", function () { + it("Returns the absolute values in Series", function () { + const data1 = [ -10, 45, 56, -25, 23, -20, 10 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.abs().values, [ 10, 45, 56, 25, 23, 20, 10 ]); + }); + it("Computes the descriptive statistics on a float Series", function () { + const data1 = [ -30.1, -40.2, -3.1, -5.1 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.abs().values, [ 30.1, 40.2, 3.1, 5.1 ]); + }); + }); + + describe("cumSum", function () { + it("Return cumulative sum over a Series", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.cumSum().values, [ 10, 55, 111, 136, 159, 179, 189 ]); + }); + it("Return cumulative sum over a Series inplace", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + sf.cumSum({ inplace: true }); + assert.deepEqual(sf.values, [ 10, 55, 111, 136, 159, 179, 189 ]); + }); + }); + + describe("cumMax", function () { + it("Return cumulative maximum over a Series", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.cumMax().values, [ 10, 45, 56, 56, 56, 56, 56 ]); + }); + it("Return cumulative maximum over a Series inplace", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + sf.cumMax({ inplace: true }); + assert.deepEqual(sf.values, [ 10, 45, 56, 56, 56, 56, 56 ]); + }); + }); + + describe("cumMin", function () { + it("Return cumulative minimum over a Series", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + assert.deepEqual(sf.cumMin().values, [ 10, 10, 10, 10, 10, 10, 10 ]); + }); + }); + + describe("cumProd", function () { + it("Return cumulative product over a Series", function () { + const data1 = [ 1, 2, 10, 3, 12, 14, 1 ]; + const sf = new dfd.Series(data1); + const rslt = [ 1, 2, 20, 60, 720, 10080, 10080 ]; + assert.deepEqual(sf.cumProd().values, rslt); + }); + }); + + describe("lt", function () { + it("Return Less than of series and other series (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const data2 = [ 100, 450, 590, 5, 25, 2, 0 ]; + + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + const expected = [ true, true, true, false, true, false, false ]; + assert.deepEqual(sf.lt(sf2).values, expected); + }); + + it("Return Less than of series scalar (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ true, false, false, true, true, true, true ]; + assert.deepEqual(sf.lt(30).values, expected); + }); + + it("Correct index is returned after operation", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const sf = new dfd.Series(data1, { index: [ "one", "two", "three", "four", "five" ] }); + + const expected = [ "one", "two", "three", "four", "five" ]; + assert.deepEqual(sf.lt(data2).index, expected); + }); + }); + + describe("gt", function () { + it("Return Greater than of series and other series (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const data2 = [ 100, 450, 590, 5, 25, 2, 0 ]; + + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + const expected = [ false, false, false, true, false, true, true ]; + assert.deepEqual(sf.gt(sf2).values, expected); + }); + + it("Return Greater than of series scalar (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ false, true, true, false, false, false, false ]; + assert.deepEqual(sf.gt(30).values, expected); + }); + + it("Correct index is returned after operation", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const sf = new dfd.Series(data1, { index: [ "one", "two", "three", "four", "five" ] }); + + const expected = [ "one", "two", "three", "four", "five" ]; + assert.deepEqual(sf.and(data2).index, expected); + }); + }); + + describe("le", function () { + it("Return Less than or Equal to of series and other series (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const data2 = [ 100, 450, 590, 5, 25, 2, 0 ]; + + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + const expected = [ true, true, true, false, true, false, false ]; + assert.deepEqual(sf.le(sf2).values, expected); + }); + + it("Return Less than or Equal to of series scalar (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ true, false, false, true, true, true, true ]; + assert.deepEqual(sf.le(30).values, expected); + }); + }); + + describe("ge", function () { + it("Return Greater than or Equal to of series and other series (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const data2 = [ 100, 450, 56, 5, 25, 20, 0 ]; + + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + const expected = [ false, false, true, true, false, true, true ]; + assert.deepEqual(sf.ge(sf2).values, expected); + }); + + it("Return Greater than or Equal to of series scalar (element-wise)", function () { + const data1 = [ 30, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ true, true, true, false, false, false, false ]; + assert.deepEqual(sf.ge(30).values, expected); + }); + }); + + describe("ne", function () { + it("Return Not Equal to of series and other series (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const data2 = [ 10, 450, 56, 5, 25, 2, 0 ]; + + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + const expected = [ false, true, false, true, true, true, true ]; + assert.deepEqual(sf.ne(sf2).values, expected); + }); + + it("Return Not Equal to of series scalar (element-wise)", function () { + const data1 = [ 10, 30, 56, 30, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ true, false, true, false, true, true, true ]; + assert.deepEqual(sf.ne(30).values, expected); + }); + }); + + describe("eq", function () { + it("Return Equal to of series and other series (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const data2 = [ 100, 450, 590, 25, 25, 2, 0 ]; + + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + const expected = [ false, false, false, true, false, false, false ]; + assert.deepEqual(sf.eq(sf2).values, expected); + }); + + it("Return Equal to of series scalar (element-wise)", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 30 ]; + const sf = new dfd.Series(data1); + const expected = [ false, false, false, false, false, false, true ]; + assert.deepEqual(sf.eq(30).values, expected); + }); + }); + + describe("replace", function () { + it("Replace values with new value", function () { + const data1 = [ 10, 45, 56, 25, 23, 20, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ -50, 45, 56, 25, 23, 20, -50 ]; + const dfRep = sf.replace(10, -50); + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace values given in replace param with value (String type)", function () { + const data1 = [ "A", "A", "A", "B", "B", "C", "C", "D" ]; + const sf = new dfd.Series(data1); + const expected = [ "boy", "boy", "boy", "B", "B", "C", "C", "D" ]; + sf.replace("A", "boy", { inplace: true }); + assert.deepEqual(sf.values, expected); + }); + it("Replace values given in replace param with value (boolean type)", function () { + const data1 = [ true, true, false, false ]; + const sf = new dfd.Series(data1); + const expected = [ false, false, false, false ]; + sf.replace(true, false, { inplace: true }); + assert.deepEqual(sf.values, expected); + }); + it("Throw error on wrong param passed", function () { + const data1 = [ "A", "A", "A", "B", "B", "C", "C", "D" ]; + const sf = new dfd.Series(data1); + assert.throws( + () => { + sf.replace(null, "boy", { inplace: true }); + }, + Error, + "Params Error: Must specify param 'oldValue' to replace" + ); + }); + }); + + describe("dropDuplicates", function () { + it("Return Series with duplicate values removed (Default, first values kept)", function () { + const data1 = [ 10, 45, 56, 10, 23, 20, 10, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ 10, 45, 56, 23, 20 ]; + const expectedIndex = [ 0, 1, 2, 4, 5 ]; + const df_drop = sf.dropDuplicates(); + assert.deepEqual(df_drop.values, expected); + assert.deepEqual(df_drop.index, expectedIndex); + }); + + it("Return Series with duplicate values removed (last values kept)", function () { + const data1 = [ 10, 45, 56, 10, 23, 20, 10, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ 45, 56, 23, 20, 10 ]; + const expectedIndex = [ 1, 2, 4, 5, 7 ]; + const df_drop = sf.dropDuplicates({ keep: "last" }); + assert.deepEqual(df_drop.values, expected); + assert.deepEqual(df_drop.index, expectedIndex); + }); + + it("Return Series with duplicate values removed (String)", function () { + const data1 = [ "A", "A", "A", "B", "B", "C", "C", "D" ]; + const sf = new dfd.Series(data1); + const expected = [ "A", "B", "C", "D" ]; + const expectedIndex = [ 0, 3, 5, 7 ]; + sf.dropDuplicates({ keep: "first", inplace: true }); + assert.deepEqual(sf.values, expected); + assert.deepEqual(sf.index, expectedIndex); + }); + }); + + describe("dropNa", function () { + it("Return a new dfd.Series with missing values removed (Int)", function () { + const data1 = [ 10, 45, undefined, 10, 23, 20, undefined, 10 ]; + const sf = new dfd.Series(data1); + const expected = [ 10, 45, 10, 23, 20, 10 ]; + const expectedIndex = [ 0, 1, 3, 4, 5, 7 ]; + const sfDrop = sf.dropNa(); + assert.deepEqual(sfDrop.values, expected); + assert.deepEqual(sfDrop.index, expectedIndex); + assert.deepEqual(sfDrop.shape, [ 6, 1 ]); + }); + + it("Return a new dfd.Series with missing values removed (String)", function () { + const data1 = [ "A", NaN, "A", "B", "B", NaN, "C", undefined ]; + const sf = new dfd.Series(data1); + const expected = [ "A", "A", "B", "B", "C" ]; + const expectedIndex = [ 0, 2, 3, 4, 6 ]; + + sf.dropNa({ inplace: true }); + assert.deepEqual(sf.values, expected); + assert.deepEqual(sf.index, expectedIndex); + assert.deepEqual(sf.shape, [ 5, 1 ]); + }); + }); + + describe("argSort", function () { + it("Return the integer indices that would sort the Series values", function () { + const data1 = [ 10, 45, 20, 10, 23, 20, 30, 11 ]; + const sf = new dfd.Series(data1); + const expected = [ 3, 0, 7, 5, 2, 4, 6, 1 ]; + const sf_sort = sf.argSort(); + assert.deepEqual(sf_sort.values, expected); + }); + + it("Return the integer indices that would sort the Series values", function () { + const data1 = [ 10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11 ]; + const sf = new dfd.Series(data1); + const expected = [ 6, 4, 5, 7, 0, 3, 1, 2 ]; + const sf_sort = sf.argSort({ ascending: false }); + assert.deepEqual(sf_sort.values, expected); + }); + }); + + describe("argMax", function () { + it("Return int position of the largest value in the Series.", function () { + const data1 = [ 10, 45, 20, 10, 23, 20, 30, 11 ]; + const sf = new dfd.Series(data1); + const expected = 1; + const argMax = sf.argMax(); + assert.deepEqual(argMax, expected); + }); + + it("Return int position of the largest value in the Float Series.", function () { + const data1 = [ 10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11 ]; + const sf = new dfd.Series(data1); + const expected = 6; + const argMax = sf.argMax(); + assert.deepEqual(argMax, expected); + }); + }); + + describe("argMin", function () { + it("Return int position of the smallest value in the Series", function () { + const data1 = [ 10, 45, 20, 122, 23, 20, 30, 11 ]; + const sf = new dfd.Series(data1); + const expected = 0; + const argMin = sf.argMin(); + assert.deepEqual(argMin, expected); + }); + + it("Return int position of the smallest value in a Float Series", function () { + const data1 = [ 10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11 ]; + const sf = new dfd.Series(data1); + const expected = 2; + const argMin = sf.argMin(); + assert.deepEqual(argMin, expected); + }); + }); + + describe("Str", function () { + it("Converts all characters to lowercase inplace", function () { + const data = [ "lower", "CAPITALS", "this is a sentence", "SwApCaSe" ]; + const res = [ "lower", "capitals", "this is a sentence", "swapcase" ]; + const sf = new dfd.Series(data); + sf.str.toLowerCase({ inplace: true }); + assert.deepEqual(sf.values, res); + }); + it("Converts all characters to lowercase", function () { + const data = [ "lower", "CAPITALS", "this is a sentence", "SwApCaSe" ]; + const res = [ "lower", "capitals", "this is a sentence", "swapcase" ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.str.toLowerCase().values, res); + }); + it("Converts all characters to capital case.", function () { + const data = [ "lower", "CAPITALS", "this is a sentence", "SwApCaSe" ]; + const res = [ "Lower", "Capitals", "This is a sentence", "Swapcase" ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.str.capitalize().values, res); + }); + + it("Returns the character at the specified index (position)", function () { + const data = [ "lower", "CAPITALS", "this is a sentence", "SwApCaSe" ]; + const res = [ "w", "P", "i", "A" ]; + const sf = new dfd.Series(data); + assert.deepEqual(sf.str.charAt(2).values, res); + }); + + it("Throws error on concat of numeric series", function () { + const data = [ 1, 2, 3, 4, 5, 6 ]; + const sf = new dfd.Series(data); + assert.throws( + () => { + sf.str.concat("20", 1); + }, + Error, + "Cannot call accessor str on non-string type" + ); + + }); + }); + + describe("dt", function () { + it("check month generated", function () { + const data = [ "02Sep2019", "03Dec2019", "04Jan2019" ]; + const sf = new dfd.Series(data); + const expected = [ 8, 11, 0 ]; + assert.deepEqual(sf.dt.month().values, expected); + }); + + it("check month Name generated", function () { + const data = [ "06-30-2019", "07-29-2019", "08-28-2019" ]; + const sf = new dfd.Series(data); + const expected = [ "June", "July", "August" ]; + assert.deepEqual(sf.dt.monthName().values, expected); + }); + + it("check days of the weeks generated", function () { + const data = [ "06-30-2019", "07-29-2019", "08-28-2019" ]; + const sf = new dfd.Series(data); + const expected = [ "Sunday", "Monday", "Wednesday" ]; + assert.deepEqual(sf.dt.dayOfWeekName().values, expected); + }); + + it("check day of the month generated", function () { + const data = [ "06-30-2019", "07-29-2019", "08-28-2019" ]; + const sf = new dfd.Series(data); + const expected = [ 30, 29, 28 ]; + assert.deepEqual(sf.dt.dayOfMonth().values, expected); + }); + }); + + describe("astype", function () { + it("set type of float column to int", function () { + const data = [ -20.1, 30, 47.3, -20 ]; + const ndframe = new dfd.Series(data); + const df = ndframe.asType("int32"); + + assert.deepEqual(df.dtypes[0], "int32"); + assert.deepEqual(df.values, [ -20, 30, 47, -20 ]); + }); + it("set type of int column to float", function () { + const data = [ 34, -4, 5, 6 ]; + const ndframe = new dfd.Series(data); + const df = ndframe.asType("float32"); + assert.deepEqual(df.dtypes[0], "float32"); + assert.deepEqual(df.values, [ 34, -4, 5, 6 ]); + }); + it("set type of string column to int", function () { + const data = [ "20.1", "21", "23.4", "50.78" ]; + const ndframe = new dfd.Series(data); + const df = ndframe.asType("int32"); + + assert.deepEqual(df.dtypes[0], "int32"); + assert.deepEqual(df.values, [ 20, 21, 23, 50 ]); + }); + it("set type of string column to float", function () { + const data = [ "20.1", "21", "23.4", "50.78" ]; + const ndframe = new dfd.Series(data); + const df = ndframe.asType("float32"); + + assert.deepEqual(df.dtypes[0], "float32"); + assert.deepEqual(df.values, [ 20.1, 21, 23.4, 50.78 ]); + }); + it("set type of float column to string", function () { + const data = [ -20.1, 30, 47.3, -20 ]; + const ndframe = new dfd.Series(data); + const df = ndframe.asType("string"); + assert.deepEqual(df.dtypes[0], "string"); + assert.deepEqual(df.values, [ "-20.1", "30", "47.3", "-20" ]); + }); + it("set type of int column to string", function () { + const data = [ 34, -4, 5, 6 ]; + const ndframe = new dfd.Series(data); + const df = ndframe.asType("string"); + assert.deepEqual(df.dtypes[0], "string"); + assert.deepEqual(df.values, [ "34", "-4", "5", "6" ]); + }); + it("set type of int column to string inplace", function () { + const data = [ 34, -4, 5, 6 ]; + const ndframe = new dfd.Series(data); + ndframe.asType("string", { inplace: true }); + assert.deepEqual(ndframe.dtypes[0], "string"); + assert.deepEqual(ndframe.values, [ "34", "-4", "5", "6" ]); + }); + }); + + describe("append", function () { + it("Add a new single value to the end of a Series inplace", function () { + const data = [ 1, 2, 3, 4, "a", "b", "c" ]; + const sf = new dfd.Series(data); + const expected_val = [ 1, 2, 3, 4, "a", "b", "c", "d" ]; + sf.append("d", 7, { inplace: true }); + assert.deepEqual(sf.values, expected_val); + }); + it("Add a new array of values to the end of a Series inplace", function () { + const data = [ 1, 2, 3, 4 ]; + const to_add = [ "a", "b", "c" ]; + const index = [ 4, 5, 6 ]; + const sf = new dfd.Series(data); + const expected_val = [ 1, 2, 3, 4, "a", "b", "c" ]; + sf.append(to_add, index, { inplace: true }); + assert.deepEqual(sf.values, expected_val); + }); + it("Add a Series to the end of another Series inplace", function () { + const sf1 = new dfd.Series([ 1, 2, 3, 4 ]); + const sf2 = new dfd.Series([ "a", "b", "c" ]); + const index = [ 4, 5, 6 ]; + const expected_val = [ 1, 2, 3, 4, "a", "b", "c" ]; + sf1.append(sf2, index, { inplace: true }); + assert.deepEqual(sf1.values, expected_val); + }); + it("Add a new single value to the end of a Series", function () { + const data = [ 1, 2, 3, 4, "a", "b", "c" ]; + const sf = new dfd.Series(data); + const expected_val = [ 1, 2, 3, 4, "a", "b", "c", "d" ]; + const sf2 = sf.append("d", 7); + assert.deepEqual(sf2.values, expected_val); + }); + it("Add a new array of values to the end of a Series", function () { + const data = [ 1, 2, 3, 4 ]; + const to_add = [ "a", "b", "c" ]; + const index = [ 4, 5, 6 ]; + const sf = new dfd.Series(data); + const expected_val = [ 1, 2, 3, 4, "a", "b", "c" ]; + const sf2 = sf.append(to_add, index); + assert.deepEqual(sf2.values, expected_val); + }); + it("Add a Series to the end of another Series", function () { + const sf1 = new dfd.Series([ 1, 2, 3, 4 ]); + const sf2 = new dfd.Series([ "a", "b", "c" ]); + const index = [ 4, 5, 6 ]; + const expected_val = [ 1, 2, 3, 4, "a", "b", "c" ]; + const sf3 = sf1.append(sf2, index); + assert.deepEqual(sf3.values, expected_val); + }); + it("Confirm index Change after append", function () { + const sf1 = new dfd.Series([ 1, 2, 3, 4 ]); + const sf2 = new dfd.Series([ "a", "b", "c" ]); + const index = [ 4, 5, 6 ]; + const sf3 = sf1.append(sf2, index); + assert.deepEqual(sf3.index, [ 0, 1, 2, 3, 4, 5, 6 ]); + }); + it("Confirm index Change after append inplace", function () { + const sf1 = new dfd.Series([ 1, 2, 3, 4 ]); + const sf2 = new dfd.Series([ "a", "b", "c" ]); + const index = [ 4, 5, 6 ]; + sf1.append(sf2, index, { inplace: true }); + assert.deepEqual(sf1.index, [ 0, 1, 2, 3, 4, 5, 6 ]); + }); + it("Can append a value of zero", function() { + const data = [ 1, 2, 3, 4, "a", "b", "c" ]; + const sf = new dfd.Series(data); + const expected_val = [ 1, 2, 3, 4, "a", "b", "c", 0 ]; + sf.append(0, 7, { inplace: true }); + assert.deepEqual(sf.values, expected_val); + }); + }); + + describe("and", function () { + it("Return logical AND of series and other series (element-wise)", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + + const expected = [ true, false, true, false, false ]; + assert.deepEqual(sf.and(sf2).values, expected); + }); + + it("Return logical AND of series and other scalar", function () { + const data1 = [ true, true, true, false, false ]; + const sf = new dfd.Series(data1); + + const expected = [ true, true, true, false, false ]; + assert.deepEqual(sf.and(true).values, expected); + }); + + it("Return logical AND of series and other array (element-wise)", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const sf = new dfd.Series(data1); + + const expected = [ true, false, true, false, false ]; + assert.deepEqual(sf.and(data2).values, expected); + }); + + it("Chaining works for logical AND of series and other array (element-wise)", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const data3 = [ true, false, false, true, false ]; + + const sf = new dfd.Series(data1); + const expected = [ true, false, false, false, false ]; + assert.deepEqual(sf.and(data2).and(data3).values, expected); + }); + + it("Chaining works for logical AND and OR combined", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const data3 = [ true, false, false, true, false ]; + + const sf = new dfd.Series(data1); + const expected = [ true, false, true, true, false ]; + assert.deepEqual(sf.and(data2).or(data3).values, expected); + }); + it("Correct index is returned after operation", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const sf = new dfd.Series(data1, { index: [ "one", "two", "three", "four", "five" ] }); + + const expected = [ "one", "two", "three", "four", "five" ]; + assert.deepEqual(sf.and(data2).index, expected); + }); + }); + + describe("or", function () { + it("Return logical OR of series and other series (element-wise)", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const sf = new dfd.Series(data1); + const sf2 = new dfd.Series(data2); + + const expected = [ true, true, true, true, false ]; + assert.deepEqual(sf.or(sf2).values, expected); + }); + + it("Return logical OR of series and other scalar", function () { + const data1 = [ true, true, true, false, false ]; + const sf = new dfd.Series(data1); + + const expected = [ true, true, true, true, true ]; + assert.deepEqual(sf.or(true).values, expected); + }); + + it("Return logical OR of series and other array (element-wise)", function () { + const data1 = [ true, true, true, false, false ]; + const data2 = [ true, false, true, true, false ]; + const sf = new dfd.Series(data1); + + const expected = [ true, true, true, true, false ]; + assert.deepEqual(sf.or(data2).values, expected); + }); + }); + + describe("getDummies", function () { + it("getDummies works on Series", function () { + + const data = [ "dog", "male", "female", "male", "female", "male", "dog" ]; + const sf = new dfd.Series(data); + const df = sf.getDummies({ prefix: "test", prefixSeparator: "/" }); + + const dfValues = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 1, 0, 0 ] + ]; + const dfColumns = [ 'test/dog', 'test/male', 'test/female' ]; + assert.deepEqual(df.values, dfValues); + assert.deepEqual(df.columns, dfColumns); + }); + it("getDummies works on Series with default prefix and prefixSeperator", function () { + + const data = [ "dog", "male", "female", "male", "female", "male", "dog" ]; + const sf = new dfd.Series(data); + const df = sf.getDummies(); + + const dfValues = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 1, 0, 0 ] + ]; + const dfColumns = [ '0_dog', '1_male', '2_female' ]; + assert.deepEqual(df.values, dfValues); + assert.deepEqual(df.columns, dfColumns); + }); + + }); + + describe("iat", function () { + it("iat works on Series", function () { + const data = [ 1, 2, 3, 4 ]; + const index = [ "a", "b", "c", "d" ]; + const df = new dfd.Series(data, { index }); + assert.equal(df.iat(0), 1); + assert.equal(df.iat(1), 2); + assert.equal(df.iat(2), 3); + }); + it("iat can return undefined", function () { + const data = [ 1, undefined, null, NaN ]; + const df = new dfd.Series(data); + assert.equal(df.iat(1), undefined); + assert.equal(df.iat(2), null); + /* @ts-ignore */ + assert.equal(isNaN(df.iat(3)), true); + }); + it("throws error on string indices", function () { + const data = [ 1, 2, 3, 4 ]; + const index = [ "a", "b", "c", "d" ]; + const df = new dfd.Series(data, { index }); + /* @ts-ignore */ + assert.throws(function () { df.iat("A"); }, Error, "ParamError: row index must be an integer. Use .at to get a row by label."); + }); + }); + + describe("at", function () { + it("at works on Series", function () { + const data = [ 1, 2, 3, 4 ]; + const index = [ "a", "b", "c", "d" ]; + const df = new dfd.Series(data, { index }); + assert.equal(df.at("a"), 1); + assert.equal(df.at("b"), 2); + assert.equal(df.at("c"), 3); + }); + it("at can return undefined", function () { + const data = [ 1, undefined, null, NaN ]; + const index = [ "a", "b", "c", "d" ]; + const df = new dfd.Series(data, { index }); + assert.equal(df.at("b"), undefined); + assert.equal(df.at("c"), null); + /* @ts-ignore */ + assert.equal(isNaN(df.at("d")), true); + }); + it("throws error on string indices", function () { + const data = [ 1, 2, 3, 4 ]; + const index = [ "a", "b", "c", "d" ]; + const df = new dfd.Series(data, { index }); + /* @ts-ignore */ + assert.throws(function () { df.at(0); }, Error, "ParamError: row index must be a string. Use .iat to get a row by index."); + }); + + }); +}); diff --git a/danfojs-browser/tests/core/strings.js b/src/danfojs-browser/tests/core/strings.test.js similarity index 85% rename from danfojs-browser/tests/core/strings.js rename to src/danfojs-browser/tests/core/strings.test.js index 74c2598d..74c16108 100644 --- a/danfojs-browser/tests/core/strings.js +++ b/src/danfojs-browser/tests/core/strings.test.js @@ -1,30 +1,29 @@ /* eslint-disable no-undef */ - describe("Str", function () { it("Converts all characters to lowercase.", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 'lower', 'capitals', 'this is a sentence', 'swapcase' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.toLowerCase().values, res); }); it("Converts all characters to uppercase.", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 'LOWER', 'CAPITALS', 'THIS IS A SENTENCE', 'SWAPCASE' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.toUpperCase().values, res); }); it("Converts all characters to capital case.", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 'Lower', 'Capitals', 'This is a sentence', 'Swapcase' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.capitalize().values, res); }); it("Returns the character at the specified index (position)", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ "w", "P", "i", "A" ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.charAt(2).values, res); }); it("Joins two or more strings. 0 joins from the start", function () { @@ -32,7 +31,7 @@ describe("Str", function () { let data2 = [ 'XX', 'YY', 'BB', '01' ]; let res = [ 'XXlower', 'YYCAPITALS', 'BBsentence', '01SwApCaSe' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.concat(data2, 0).values, res); }); @@ -41,125 +40,125 @@ describe("Str", function () { let data2 = [ 'XX', 'YY', 'BB', '01' ]; let res = [ 'lowerXX', 'CAPITALSYY', 'sentenceBB', 'SwApCaSe01' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.concat(data2, 1).values, res); }); it("Joins two arrays of strings. 0 joins from the start", function () { let data = [ 'lower', 'CAPITALS', 'sentence', 'SwApCaSe' ]; let res = [ 'prelower', 'preCAPITALS', 'presentence', 'preSwApCaSe' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.concat("pre", 0).values, res); }); it("Joins two or more strings. 1 joins from the end", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 'lowerpost', 'CAPITALSpost', 'this is a sentencepost', 'SwApCaSepost' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.concat("post", 1).values, res); }); it("Checks whether a string begins with specified characters", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ true, false, false, false ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.startsWith("l").values, res); }); it("Checks whether a string ends with specified characters", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ false, false, true, true ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.endsWith("e").values, res); }); it("Checks whether a string contains the specified string/characters", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ false, false, true, false ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.includes("sentence").values, res); }); it("Returns the position of the first found occurrence of a specified value in a string", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ -1, 0, -1, 4 ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.indexOf("C").values, res); }); it("Returns the position of the last found occurrence of a specified value in a string", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 4, -1, -1, -1 ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.lastIndexOf("r").values, res); }); it("Returns a new string with a specified number of copies of an existing string", function () { let data = [ 'a', 'b', 'c', 'd' ]; let res = [ 'aaa', 'bbb', 'ccc', 'ddd' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.repeat(3).values, res); }); it("Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 'lower', 'CXXXPITALS', 'this is a sentence', 'SwXXXpCaSe' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.replace("A", "XXX").values, res); }); it("Searches a string for a specified value, or regular expression, and returns the position of the match", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ -1, 1, -1, 2 ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.search("A").values, res); }); it("Extracts a part of a string and returns a new string", function () { let data = [ 'lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 'ow', 'AP', 'hi', 'wA' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.slice(1, 3).values, res); }); it("Splits a string into an array of substrings", function () { let data = [ 'lower part', 'CAPITALS city', 'is a sentence', 'SwAp CaSe' ]; let res = [ "lower,part", "CAPITALS,city", "is,a,sentence", "SwAp,CaSe" ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.split(" ").values, res); }); it("Extracts the characters from a string, beginning at a specified start position, and through the specified number of character", function () { let data = [ 'lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe' ]; let res = [ " p", "AL", "is", "Ca" ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.substr(5, 2).values, res); }); it("Extracts the characters from a string, between two specified indices", function () { let data = [ 'lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe' ]; let res = [ "w", "P", "i", "A" ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.substring(2, 3).values, res); }); it("Removes whitespace from both ends of a string", function () { let data = [ 'lower part ', ' CAPITALS city', ' this is a sentence', ' SwAp CaSe' ]; let res = [ 'lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.trim().values, res); }); it("Joins strings to specified value", function () { let data = [ 'lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe' ]; let res = [ 'lower part,new', 'CAPITALS city,new', 'this is a sentence,new', 'SwAp CaSe,new' ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.join("new", ",").values, res); }); it("Counts the number of characters in string", function () { let data = [ 'lower part', 'CAPITALS', 'this is a sentence', 'SwApCaSe' ]; let res = [ 10, 8, 18, 8 ]; - let str = new dfd.Str(new dfd.Series(data)); + let str = new dfd.Series(data).str; assert.deepEqual(str.len().values, res); }); diff --git a/src/danfojs-browser/tests/io/csv.reader.test.js b/src/danfojs-browser/tests/io/csv.reader.test.js new file mode 100644 index 00000000..9fcc2a2f --- /dev/null +++ b/src/danfojs-browser/tests/io/csv.reader.test.js @@ -0,0 +1,181 @@ +/* eslint-disable no-undef */ + +describe("readCSV", function () { + this.timeout(10000); + it("Read remote csv file works", async function () { + const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/titanic.csv"; + let df = await dfd.readCSV(remoteFile, { header: true, preview: 5 }); + assert.deepEqual(df.shape, [ 5, 8 ]); + assert.deepEqual(df.columns, [ + 'Survived', + 'Pclass', + 'Name', + 'Sex', + 'Age', + 'Siblings/Spouses Aboard', + 'Parents/Children Aboard', + 'Fare' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'int32', + 'string', 'string', + 'int32', 'int32', + 'int32', 'float32' + ]); + }); + + it("Read remote csv file with config works", async function () { + const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/titanic.csv"; + const frameConfig = { + columns: [ + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H' + ] + }; + let df = await dfd.readCSV(remoteFile, { header: true, preview: 5, frameConfig }); + assert.deepEqual(df.shape, [ 5, 8 ]); + assert.deepEqual(df.columns, [ + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'int32', + 'string', 'string', + 'int32', 'int32', + 'int32', 'float32' + ]); + }); + + it("Read remote csv file works and returns correct data type", async function () { + const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/titanic.csv"; + let df = await dfd.readCSV(remoteFile, { header: true, preview: 2 }); + const values = [ + [ 0, 3, 'Mr. Owen Harris Braund', 'male', 22, 1, 0, 7.25 ], + [ 1, 1, 'Mrs. John Bradley (Florence Briggs Thayer) Cumings', 'female', 38, 1, 0, 71.2833 ] + ]; + assert.deepEqual(df.values, values); + }); + + it("Should throw error when reading non-existent remote file", async function () { + const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/nonexistent.csv"; + try { + await dfd.readCSV(remoteFile); + assert.fail("Should have thrown an error"); + } catch (error) { + assert.ok(error instanceof Error); + } + }); + + it("Should throw error when reading malformed CSV", async function () { + const malformedCSV = new File([ "a,b,c\n1,2\n3,4,5,6" ], "malformed.csv", { type: "text/csv" }); + try { + await dfd.readCSV(malformedCSV); + assert.fail("Should have thrown an error"); + } catch (error) { + assert.ok(error instanceof Error); + } + }); + + it("Should throw error when reading invalid file type", async function () { + const invalidFile = new File([ "not a csv" ], "test.txt", { type: "text/plain" }); + try { + await dfd.readCSV(invalidFile); + assert.fail("Should have thrown an error"); + } catch (error) { + assert.ok(error instanceof Error); + } + }); + + it("Preserves leading zeros when dtype is string", async function () { + // Create a CSV file with leading zeros + const csvContent = "codes\n012345\n001234"; + const file = new File([ csvContent ], "leading_zeros.csv", { type: "text/csv" }); + + const df = await dfd.readCSV(file, { + frameConfig: { + dtypes: [ "string" ] + } + }); + + assert.deepEqual(df.values, [ [ "012345" ], [ "001234" ] ]); + assert.deepEqual(df.dtypes, [ "string" ]); + + // Verify the values are actually strings + const jsonData = dfd.toJSON(df); + assert.deepEqual(jsonData, [ { codes: "012345" }, { codes: "001234" } ]); + }); + + it("Converts to numbers when dtype is not string", async function () { + // Create a CSV file with leading zeros + const csvContent = "codes\n012345\n001234"; + const file = new File([ csvContent ], "leading_zeros.csv", { type: "text/csv" }); + + const df = await dfd.readCSV(file); // default behavior without string dtype + + // Values should be converted to numbers + assert.deepEqual(df.values, [ [ 12345 ], [ 1234 ] ]); + assert.deepEqual(df.dtypes, [ "int32" ]); + + // Verify JSON output + const jsonData = dfd.toJSON(df); + assert.deepEqual(jsonData, [ { codes: 12345 }, { codes: 1234 } ]); + }); +}); + +// describe("streamCSV", function () { +// this.timeout(100000); + +// it("Streaming remote csv file with callback works", async function () { +// const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/titanic.csv"; +// await dfd.streamCSV(remoteFile, (df) => { +// if (df) { +// assert.deepEqual(df.shape, [ 1, 8 ]); +// assert.deepEqual(df.columns, [ +// 'Survived', +// 'Pclass', +// 'Name', +// 'Sex', +// 'Age', +// 'Siblings/Spouses Aboard', +// 'Parents/Children Aboard', +// 'Fare' +// ]); +// } else { +// assert.deepEqual(df, null); +// } +// }, { header: true, preview: 3 }); + +// }); + +// }); + + +describe("toCSV", function () { + it("toCSV works", async function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + let df = new dfd.DataFrame(data, { columns: [ "a", "b", "c", "d" ] }); + assert.deepEqual(dfd.toCSV(df, { download: false }), `a,b,c,d\n1,2,3,4\n5,6,7,8\n9,10,11,12\n`); + }); + it("toCSV works for specified seperator", async function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + let df = new dfd.DataFrame(data, { columns: [ "a", "b", "c", "d" ] }); + assert.deepEqual(dfd.toCSV(df, { sep: "+", download: false }), `a+b+c+d\n1+2+3+4\n5+6+7+8\n9+10+11+12\n`); + }); + it("toCSV works for series", async function () { + const data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]; + let df = new dfd.Series(data); + assert.deepEqual(dfd.toCSV(df, { sep: "+", download: false }), `1+2+3+4+5+6+7+8+9+10+11+12`); + }); +}); diff --git a/src/danfojs-browser/tests/io/excel.reader.test.js b/src/danfojs-browser/tests/io/excel.reader.test.js new file mode 100644 index 00000000..0d0160b1 --- /dev/null +++ b/src/danfojs-browser/tests/io/excel.reader.test.js @@ -0,0 +1,45 @@ +/* eslint-disable no-undef */ + +describe("readExcel", function () { + this.timeout(100000); + it("Read remote excel file works", async function () { + const remoteFile = "https://raw.githubusercontent.com/opensource9ja/danfojs/dev//src/danfojs-node/test/samples/sample.xlsx"; + let df = await dfd.readExcel(remoteFile); + assert.deepEqual(df.columns, [ + 'Year', + 'Stocks', + 'T.Bills', + 'T.Bonds' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'float32', + 'float32', 'float32' + ]); + assert.deepEqual(df.shape, [ 82, 4 ]); + }); + + it("Read remote excel file with config works", async function () { + const remoteFile = "https://raw.githubusercontent.com/opensource9ja/danfojs/dev//src/danfojs-node/test/samples/sample.xlsx"; + const frameConfig = { + columns: [ + 'A', + 'B', + 'C', + 'D' + ] + }; + let df = await dfd.readExcel(remoteFile, { frameConfig }); + assert.deepEqual(df.columns, [ + 'A', + 'B', + 'C', + 'D' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'float32', + 'float32', 'float32' + ]); + assert.deepEqual(df.shape, [ 82, 4 ]); + }); +}); + diff --git a/src/danfojs-browser/tests/io/json.reader.test.js b/src/danfojs-browser/tests/io/json.reader.test.js new file mode 100644 index 00000000..87a223db --- /dev/null +++ b/src/danfojs-browser/tests/io/json.reader.test.js @@ -0,0 +1,76 @@ +/* eslint-disable no-undef */ + +describe("readJSON", function () { + this.timeout(100000); + + it("Read remote csv file works", async function () { + const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/book.json"; + const df = await dfd.readJSON(remoteFile); + assert.deepEqual(df.columns, [ + 'book_id', + 'title', + 'image_url', + 'authors' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'string', + 'string', 'string' + ]); + }); + + it("Read remote csv file with config works", async function () { + const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/book.json"; + const frameConfig = { + columns: [ + 'A', + 'B', + 'C', + 'D' + ] + }; + const df = await dfd.readJSON(remoteFile, { frameConfig }); + assert.deepEqual(df.columns, [ + 'A', + 'B', + 'C', + 'D' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'string', + 'string', 'string' + ]); + }); +}); + +describe("toJSON", function () { + it("toJSON works", async function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + const df = new dfd.DataFrame(data, { columns: [ "a", "b", "c", "d" ] }); + const expected = [ + { "a": 1, "b": 2, "c": 3, "d": 4 }, + { "a": 5, "b": 6, "c": 7, "d": 8 }, + { "a": 9, "b": 10, "c": 11, "d": 12 } + ]; + const json = dfd.toJSON(df, { download: false }); + assert.deepEqual(json, expected); + }); + it("toJSON works for row format", async function () { + const data = [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]; + const df = new dfd.DataFrame(data, { columns: [ "a", "b", "c", "d" ] }); + const expected = { + "a": [ 1, 5, 9 ], + "b": [ 2, 6, 10 ], + "c": [ 3, 7, 11 ], + "d": [ 4, 8, 12 ] + }; + const json = dfd.toJSON(df, { format: "row", download: false }); + assert.deepEqual(json, expected); + }); + + it("toJSON works for series", async function () { + const data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]; + const df = new dfd.Series(data); + assert.deepEqual(dfd.toJSON(df, { download: false }), { "0": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] }); + }); + +}); diff --git a/danfojs-browser/tests/core/concat.js b/src/danfojs-browser/tests/transformers/concat.test.js similarity index 65% rename from danfojs-browser/tests/core/concat.js rename to src/danfojs-browser/tests/transformers/concat.test.js index 6ee9e089..1d3aca5a 100644 --- a/danfojs-browser/tests/core/concat.js +++ b/src/danfojs-browser/tests/transformers/concat.test.js @@ -1,7 +1,6 @@ /* eslint-disable no-undef */ -describe("Concatenate", function () { - +describe("Concat", () => { it("Check the axis 0 concatenation", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; let cols = [ "A", "B", "C" ]; @@ -15,7 +14,7 @@ describe("Concatenate", function () { let cols2 = [ "A", "B", "C", "D" ]; let df2 = new dfd.DataFrame(data2, { columns: cols2 }); - let new_df = dfd.concat({ "df_list": [ df, df1, df2 ], "axis": 0 }); + let new_df = dfd.concat({ dfList: [ df, df1, df2 ], axis: 0 }); let data_values = [ [ 1, 2, 3, NaN ], [ 4, 5, 6, NaN ], [ 20, 30, 40, NaN ], [ 39, 89, 78, NaN ], [ 1, 2, 3, NaN ], [ 4, 5, 6, NaN ], [ 20, 30, 40, NaN ], [ 39, 89, 78, NaN ], @@ -37,7 +36,7 @@ describe("Concatenate", function () { let cols2 = [ "A", "B", "C", "D" ]; let df2 = new dfd.DataFrame(data2, { columns: cols2 }); - let new_df = dfd.concat({ "df_list": [ df, df1, df2 ], "axis": 1 }); + let new_df = dfd.concat({ dfList: [ df, df1, df2 ], axis: 1 }); let data_values = [ [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 5 ], [ 4, 5, 6, 4, 5, 6, 4, 5, 6, 8 ], [ 20, 30, 40, 20, 30, 40, 20, 30, 40, 10 ], [ 39, 89, 78, 39, 89, 78, NaN, @@ -55,20 +54,18 @@ describe("Concatenate", function () { let df = new dfd.DataFrame(data, { columns: cols }); let s1 = new dfd.Series(data1); - let s2 = new dfd.Series(data2); let rslt = [ - [ 1, 2, 3, NaN ], - [ 4, 5, 6, NaN ], - [ 20, 30, 40, NaN ], - [ 39, 89, 78, NaN ], - [ NaN, NaN, NaN, 1 ], - [ NaN, NaN, NaN, 2 ], - [ NaN, NaN, NaN, 3 ], - [ NaN, NaN, NaN, 4 ] + [ NaN, 1, 2, 3 ], + [ NaN, 4, 5, 6 ], + [ NaN, 20, 30, 40 ], + [ NaN, 39, 89, 78 ], + [ 1, NaN, NaN, NaN ], + [ 2, NaN, NaN, NaN ], + [ 3, NaN, NaN, NaN ], + [ 4, NaN, NaN, NaN ] ]; - - let con = dfd.concat({ "df_list": [ df, s1 ], "axis": 0 }); + let con = dfd.concat({ dfList: [ df, s1 ], axis: 0 }); assert.deepEqual(con.values, rslt); @@ -83,14 +80,14 @@ describe("Concatenate", function () { let data1 = [ 1, 2, 3, 4 ]; let s1 = new dfd.Series(data1); let rslt = [ - [ 1, 2, 3, 1 ], - [ 4, 5, 6, 2 ], - [ 20, 30, 40, 3 ], - [ 39, 89, 78, 4 ] + [ 1, 1, 2, 3 ], + [ 2, 4, 5, 6 ], + [ 3, 20, 30, 40 ], + [ 4, 39, 89, 78 ] ]; - let con = dfd.concat({ "df_list": [ df, s1 ], "axis": 1 }); + let con = dfd.concat({ dfList: [ df, s1 ], axis: 1 }); assert.deepEqual(con.values, rslt); @@ -105,7 +102,7 @@ describe("Concatenate", function () { let rslt = [ [ 1, 3 ], [ 2, 4 ], [ 3, 5 ], [ 4, 6 ] ]; - let con = dfd.concat({ "df_list": [ s1, s2 ], "axis": 1 }); + let con = dfd.concat({ dfList: [ s1, s2 ], axis: 1 }); assert.deepEqual(con.values, rslt); @@ -122,38 +119,10 @@ describe("Concatenate", function () { 3, 4, 5, 6 ]; - let con = dfd.concat({ "df_list": [ s1, s2 ], "axis": 0 }); + let con = dfd.concat({ dfList: [ s1, s2 ], axis: 0 }); assert.deepEqual(con.values, rslt); }); - it("test if df_list is an array", function(){ - - assert.throws(function () { dfd.concat({ "df_list":23, "axis":0 }); }, Error, 'df_list must be an Array of dataFrames/Series'); - - }); - it("assign default axis for concating", function(){ - let data1 = [ 1, 2, 3, 4 ]; - let data2 = [ 3, 4, 5, 6 ]; - - let s1 = new dfd.Series(data1); - let s2 = new dfd.Series(data2); - let rslt = [ [ 1, 3 ], [ 2, 4 ], [ 3, 5 ], [ 4, 6 ] ]; - - - let con = dfd.concat({ "df_list": [ s1, s2 ], "axis": 12 }); - - assert.deepEqual(con.values, rslt); - }); - it("ensure axis is a number", function(){ - let data1 = [ 1, 2, 3, 4 ]; - let data2 = [ 3, 4, 5, 6 ]; - - let s1 = new dfd.Series(data1); - let s2 = new dfd.Series(data2); - - assert.throws(function () { dfd.concat({ "df_list":[ s1, s2 ], "axis":"r" }); }, Error, 'axis must be a number'); - }); - }); diff --git a/src/danfojs-browser/tests/transformers/dummy.encoder.test.js b/src/danfojs-browser/tests/transformers/dummy.encoder.test.js new file mode 100644 index 00000000..a15d79d6 --- /dev/null +++ b/src/danfojs-browser/tests/transformers/dummy.encoder.test.js @@ -0,0 +1,173 @@ +/* eslint-disable no-undef */ + +describe("DummyEncoder", function () { + it("getDummies works on Series", function () { + + const data = [ "dog", "male", "female", "male", "female", "male", "dog" ]; + const series = new dfd.Series(data); + const df = dfd.getDummies(series, { prefix: "test", prefixSeparator: "/" }); + + const dfValues = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 1, 0, 0 ] + ]; + const dfColumns = [ 'test/dog', 'test/male', 'test/female' ]; + assert.deepEqual(df.values, dfValues); + assert.deepEqual(df.columns, dfColumns); + }); + it("getDummies works on Series with default prefix and prefixSeperator", function () { + + const data = [ "dog", "male", "female", "male", "female", "male", "dog" ]; + const series = new dfd.Series(data); + const df = dfd.getDummies(series); + + const dfValues = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ], + [ 1, 0, 0 ] + ]; + const dfColumns = [ '0_dog', '1_male', '2_female' ]; + assert.deepEqual(df.values, dfValues); + assert.deepEqual(df.columns, dfColumns); + }); + + it("getDummies works on DataFrame", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const df1 = dfd.getDummies(df, { prefixSeparator: [ "_", "#" ], columns: [ "A", "d" ], prefix: "test" }); + const expectedColumns = [ 'B', 'C', 'test_1', 'test_3', 'test_4', 'test#fat', 'test#good', 'test#best' ]; + const expected = [ [ 'dog', 1.0, 1, 0, 0, 1, 0, 0 ], + [ 'fog', 2.0, 0, 1, 0, 0, 1, 0 ], + [ 'gof', 3.0, 0, 0, 1, 0, 0, 1 ] ]; + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + it("Throw error if the prefix specified is not equal to the column specified", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + assert.throws(function () { dfd.getDummies(df, { prefix: [ "fg" ], prefixSeparator: "_", columns: [ "A", "d" ] }); }, Error, + `ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "fg"}`); + + }); + it("replace column sepecified with prefix", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const df1 = dfd.getDummies(df, { prefix: [ "F", "G" ], prefixSeparator: "_", columns: [ "A", "d" ] }); + const expectedColumns = [ + 'B', 'C', + 'F_1', 'F_3', + 'F_4', 'G_fat', + 'G_good', 'G_best' + ]; + + const expected = [ [ 'dog', 1.0, 1, 0, 0, 1, 0, 0 ], + [ 'fog', 2.0, 0, 1, 0, 0, 1, 0 ], + [ 'gof', 3.0, 0, 0, 1, 0, 0, 1 ] ]; + + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("getDummies auto infers and encode columns with string dtype", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + + const df1 = dfd.getDummies(df, { prefixSeparator: "_" }); + const expectedColumns = [ + 'A', 'C', + 'B_dog', 'B_fog', + 'B_gof', 'd_fat', + 'd_good', 'd_best' + ]; + const expected = [ + [ + 1, 1, 1, 0, + 0, 1, 0, 0 + ], + [ + 3, 2, 0, 1, + 0, 0, 1, 0 + ], + [ + 4, 3, 0, 0, + 1, 0, 0, 1 + ] + ]; + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("should one hot encode all other columns", function () { + + const data = [ [ 1, "dog", 1.0, "fat" ], [ 3, "fog", 2.0, "good" ], [ 4, "gof", 3.0, "best" ] ]; + const columns = [ "A", "B", "C", "d" ]; + const df = new dfd.DataFrame(data, { columns: columns }); + const rslt = [ + [ 1, 'dog', 1, 1, 0, 0 ], + [ 3, 'fog', 2, 0, 1, 0 ], + [ 4, 'gof', 3, 0, 0, 1 ] + ]; + + assert.deepEqual(dfd.getDummies(df, { columns: [ "d" ] }).values, rslt); + + }); + it("Dummification works for object DF", function () { + + let data = { + fruits: [ 'pear', 'mango', "pawpaw", "mango", "bean" ], + Count: [ 20, 30, 89, 12, 30 ], + Country: [ "NG", "NG", "GH", "RU", "RU" ] + }; + + let df = new dfd.DataFrame(data); + const expected = [ + [ + 20, 1, 0, 0, + 0, 1, 0, 0 + ], + [ + 30, 0, 1, 0, + 0, 1, 0, 0 + ], + [ + 89, 0, 0, 1, + 0, 0, 1, 0 + ], + [ + 12, 0, 1, 0, + 0, 0, 0, 1 + ], + [ + 30, 0, 0, 0, + 1, 0, 0, 1 + ] + ]; + + let dum_df = dfd.getDummies(df, { prefixSeparator: "_" }); + assert.deepEqual(dum_df.values, expected); + + }); +}); diff --git a/src/danfojs-browser/tests/transformers/label.encoder.test.js b/src/danfojs-browser/tests/transformers/label.encoder.test.js new file mode 100644 index 00000000..a1a63e60 --- /dev/null +++ b/src/danfojs-browser/tests/transformers/label.encoder.test.js @@ -0,0 +1,51 @@ +/* eslint-disable no-undef */ + +describe("LabelEncoder", function () { + + it("LabelEncoder works for Series", function () { + const sf = new dfd.Series([ 1, 2, 2, 6 ]); + const scaler = new dfd.LabelEncoder(); + scaler.fit(sf); + const expected = [ 0, 1, 1, 2 ]; + assert.deepEqual(scaler.transform(sf).values, expected); + }); + it("LabelEncoder works for 1D array", function () { + const sf = [ 1, 2, 2, "boy", "git", "git" ]; + const scaler = new dfd.LabelEncoder(); + scaler.fit(sf); + const expected = [ 0, 1, 1, 2, 3, 3 ]; + assert.deepEqual(scaler.transform(sf), expected); + }); + it("LabelEncoder works for values not found", function () { + const sf = new dfd.Series([ 1, 2, 2, 6 ]); + const scaler = new dfd.LabelEncoder(); + scaler.fit(sf); + + const expected = [ 0, 1, 1, 2, -1 ]; + assert.deepEqual((scaler.transform(new dfd.Series([ 1, 2, 2, 6, 7 ]))).values, expected); + }); + it("fitTransform works for 1D array", function () { + const sf = [ 1, 2, 2, "boy", "git", "git" ]; + const scaler = new dfd.LabelEncoder(); + const result = scaler.fitTransform(sf); + const expected = [ 0, 1, 1, 2, 3, 3 ]; + assert.deepEqual(result, expected); + }); + it("inverseTransform works for 1D array", function () { + const sf = [ 1, 2, 2, "boy", "git", "git" ]; + const scaler = new dfd.LabelEncoder(); + scaler.fit(sf); + const result = scaler.inverseTransform([ 0, 1, 1, 2, 3, 3 ]); + assert.deepEqual(result, [ 1, 2, 2, "boy", "git", "git" ]); + }); + it("Get properties from LabelEncoder", function () { + const sf = [ 1, 2, 2, "boy", "git", "git" ]; + const scaler = new dfd.LabelEncoder(); + scaler.fit(sf); + const classes = scaler.classes; + const nClasses = scaler.nClasses; + + assert.deepEqual(classes, { 1: 0, 2: 1, boy: 2, git: 3 }); + assert.equal(nClasses, 4); + }); +}); diff --git a/danfojs-browser/tests/core/merge.js b/src/danfojs-browser/tests/transformers/merge.test.js similarity index 89% rename from danfojs-browser/tests/core/merge.js rename to src/danfojs-browser/tests/transformers/merge.test.js index 284894b2..d44a97dd 100644 --- a/danfojs-browser/tests/core/merge.js +++ b/src/danfojs-browser/tests/transformers/merge.test.js @@ -14,7 +14,7 @@ describe("Merge", function () { let df1 = new dfd.DataFrame(data, { columns: colum1 }); let df2 = new dfd.DataFrame(data2, { columns: colum2 }); - let merge_df = dfd.merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "outer" }); + let merge_df = dfd.merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "outer" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], @@ -25,7 +25,6 @@ describe("Merge", function () { [ 'K2', 'K0', NaN, NaN, 'C3', 'D3' ] ]; - assert.deepEqual(merge_df.values, output_data); }); @@ -41,7 +40,7 @@ describe("Merge", function () { let df1 = new dfd.DataFrame(data, { columns: colum1 }); let df2 = new dfd.DataFrame(data2, { columns: colum2 }); - let merge_df = dfd.merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "inner" }); + let merge_df = dfd.merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "inner" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], @@ -64,7 +63,7 @@ describe("Merge", function () { let df1 = new dfd.DataFrame(data, { columns: colum1 }); let df2 = new dfd.DataFrame(data2, { columns: colum2 }); - let merge_df = dfd.merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "left" }); + let merge_df = dfd.merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "left" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], @@ -89,7 +88,7 @@ describe("Merge", function () { let df1 = new dfd.DataFrame(data, { columns: colum1 }); let df2 = new dfd.DataFrame(data2, { columns: colum2 }); - let merge_df = dfd.merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "right" }); + let merge_df = dfd.merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "right" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], diff --git a/src/danfojs-browser/tests/transformers/min.max.scaler.test.js b/src/danfojs-browser/tests/transformers/min.max.scaler.test.js new file mode 100644 index 00000000..4ae1071f --- /dev/null +++ b/src/danfojs-browser/tests/transformers/min.max.scaler.test.js @@ -0,0 +1,54 @@ +/* eslint-disable no-undef */ + +describe("MinMaxscaler", function () { + + it("Standardize values in a DataFrame using a MinMaxScaler", function () { + const data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; + const scaler = new dfd.MinMaxScaler(); + + const expected = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; + const transformedData = [ [ 1.5, 0. ] ]; + + scaler.fit(new dfd.DataFrame(data)); + const resultDf = scaler.transform(new dfd.DataFrame(data)); + assert.deepEqual(resultDf.values, expected); + assert.deepEqual(scaler.transform([ [ 2, 2 ] ]), transformedData); + }); + it("fitTransform using a MinMaxScaler", function () { + const data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; + const scaler = new dfd.MinMaxScaler(); + const resultDf = scaler.fitTransform(new dfd.DataFrame(data)); + + const expected = [ [ 0, 0 ], [ 0.25, 0.25 ], [ 0.5, 0.5 ], [ 1, 1 ] ]; + assert.deepEqual(resultDf.values, expected); + }); + it("InverseTransform with MinMaxScaler", function () { + const scaler = new dfd.MinMaxScaler(); + scaler.fit([ 1, 2, 3, 4, 5 ]); + const resultTransform = scaler.transform([ 1, 2, 3, 4, 5 ]); + const resultInverse = scaler.inverseTransform([ 0, 0.25, 0.5, 0.75, 1 ]); + + assert.deepEqual(resultTransform, [ 0, 0.25, 0.5, 0.75, 1 ]); + assert.deepEqual([ 1, 2, 3, 4, 5 ], resultInverse); + }); + it("Index and columns are kept after transformation", function () { + const data = [ [ -1, 2 ], [ -0.5, 6 ], [ 0, 10 ], [ 1, 18 ] ]; + const df = new dfd.DataFrame(data, { index: [ 1, 2, 3, 4 ], columns: [ "a", "b" ] }); + + const scaler = new dfd.MinMaxScaler(); + scaler.fit(df); + const resultDf = scaler.transform(df); + + assert.deepEqual(resultDf.index, [ 1, 2, 3, 4 ]); + assert.deepEqual(resultDf.columns, [ "a", "b" ]); + }); + it("Standardize values in a Series using a MinMaxScaler", function () { + const data = [ -1, 2, -0.5, 60, 101, 18 ]; + const scaler = new dfd.MinMaxScaler(); + const result = [ 0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677 ]; + const transformedData = [ 0.029411764815449715, 0.029411764815449715 ]; + scaler.fit(new dfd.Series(data)); + assert.deepEqual(scaler.transform(new dfd.Series(data)).values, result); + assert.deepEqual(scaler.transform([ 2, 2 ]), transformedData); + }); +}); diff --git a/src/danfojs-browser/tests/transformers/one.hot.encoder.test.js b/src/danfojs-browser/tests/transformers/one.hot.encoder.test.js new file mode 100644 index 00000000..a8b001fc --- /dev/null +++ b/src/danfojs-browser/tests/transformers/one.hot.encoder.test.js @@ -0,0 +1,82 @@ +/* eslint-disable no-undef */ + +describe("OneHotEncoder", function () { + it("OneHotEncoder works on array", function () { + const data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; + const encode = new dfd.OneHotEncoder(); + encode.fit(data); + + const expected = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ] + ]; + assert.deepEqual(encode.transform(data), expected); + assert.deepEqual(encode.transform([ "man", "cat" ]), [ [ 0, 0, 1 ], [ 0, 1, 0 ] ]); + }); + it("OneHotEncoder works on Series", function () { + const data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; + const series = new dfd.Series(data); + const encoder = new dfd.OneHotEncoder(); + encoder.fit(series); + + const expected = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ] + ]; + assert.deepEqual(encoder.transform(series).values, expected); + }); + + it("fitTransform works on OneHotEncoder", function () { + const data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; + const series = new dfd.Series(data); + const encoder = new dfd.OneHotEncoder(); + const result = encoder.fitTransform(series); + + const expected = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ] + ]; + assert.deepEqual(result.values, expected); + }); + + it("Correct index is returned after transformation", function () { + const data = [ "dog", "cat", "man", "dog", "cat", "man", "man", "cat" ]; + const series = new dfd.Series(data, + { index: [ "a", "b", "c", "d", "e", "f", "g", "h" ] + }); + const encoder = new dfd.OneHotEncoder(); + const result = encoder.fitTransform(series); + + const expected = [ + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 1, 0, 0 ], + [ 0, 1, 0 ], + [ 0, 0, 1 ], + [ 0, 0, 1 ], + [ 0, 1, 0 ] + ]; + assert.deepEqual(result.values, expected); + assert.deepEqual(result.index, [ "a", "b", "c", "d", "e", "f", "g", "h" ]); + assert.deepEqual(result.columns, [ "0", "1", "2" ]); + }); +}); diff --git a/src/danfojs-browser/tests/transformers/standard.scaler.test.js b/src/danfojs-browser/tests/transformers/standard.scaler.test.js new file mode 100644 index 00000000..1363fe71 --- /dev/null +++ b/src/danfojs-browser/tests/transformers/standard.scaler.test.js @@ -0,0 +1,55 @@ +/* eslint-disable no-undef */ + +describe("StandardScaler", function () { + + it("StandardScaler works for DataFrame", function () { + const data = [ [ 0, 0 ], [ 0, 0 ], [ 1, 1 ], [ 1, 1 ] ]; + + const scaler = new dfd.StandardScaler(); + scaler.fit(new dfd.DataFrame(data)); + + const expected = [ [ -1, -1 ], [ -1, -1 ], [ 1, 1 ], [ 1, 1 ] ]; + const resultDf = scaler.transform(new dfd.DataFrame(data)); + assert.deepEqual(resultDf.values, expected); + assert.deepEqual(scaler.transform([ [ 2, 2 ] ]), [ [ 3, 3 ] ]); + }); + it("fitTransform works for StandardScaler", function () { + const data = [ [ 0, 0 ], [ 0, 0 ], [ 1, 1 ], [ 1, 1 ] ]; + + const scaler = new dfd.StandardScaler(); + const resultDf = scaler.fitTransform(new dfd.DataFrame(data)); + + const expected = [ [ -1, -1 ], [ -1, -1 ], [ 1, 1 ], [ 1, 1 ] ]; + assert.deepEqual(resultDf.values, expected); + }); + it("inverseTransform works for StandardScaler", function () { + const data = [ [ 0, 0 ], [ 0, 0 ], [ 1, 1 ], [ 1, 1 ] ]; + + const scaler = new dfd.StandardScaler(); + scaler.fit(new dfd.DataFrame(data)); + const resultDf = scaler.inverseTransform([ [ -1, -1 ], [ -1, -1 ], [ 1, 1 ], [ 1, 1 ] ]); + + assert.deepEqual(resultDf, data); + }); + it("StandardScaler works for Array", function () { + const data = [ [ 0, 0 ], [ 0, 0 ], [ 1, 1 ], [ 1, 1 ] ]; + + const scaler = new dfd.StandardScaler(); + scaler.fit(data); + const expected = [ [ -1, -1 ], [ -1, -1 ], [ 1, 1 ], [ 1, 1 ] ]; + + assert.deepEqual(scaler.transform(data), expected); + assert.deepEqual(scaler.transform([ [ 2, 2 ] ]), [ [ 3, 3 ] ]); + }); + + it("StandardScaler works for Series", function () { + const data = [ 0, 0, 0, 0, 1, 1, 1, 1 ]; + + const scaler = new dfd.StandardScaler(); + scaler.fit(new dfd.Series(data)); + const expected = [ -1, -1, -1, -1, 1, 1, 1, 1 ]; + + assert.deepEqual(scaler.transform(new dfd.Series(data)).values, expected); + assert.deepEqual(scaler.transform([ 2, 2 ]), [ 3, 3 ]); + }); +}); diff --git a/danfojs-node/tests/core/utils.js b/src/danfojs-browser/tests/utils.test.js similarity index 59% rename from danfojs-node/tests/core/utils.js rename to src/danfojs-browser/tests/utils.test.js index 01b8c63d..d29ecf42 100644 --- a/danfojs-node/tests/core/utils.js +++ b/src/danfojs-browser/tests/utils.test.js @@ -1,19 +1,23 @@ -import { assert } from "chai"; -import { utils } from "../../dist"; +/* eslint-disable no-undef */ -describe("Utils Functions", function () { +const utils = new dfd.Utils(); + +describe("Utils", function () { it("removes an element from an array", function () { let arr = [ 1, 2, 3, 4 ]; assert.deepEqual(utils.removeElementFromArray(arr, 2), [ 1, 2, 4 ]); }); + it("Checks if variable is a string", function () { let arr = [ "1", "2" ]; assert.isTrue(utils.isString(arr[0])); }); + it("Checks if variable is a number", function () { let arr = [ 1, 2, 3, 4 ]; assert.isTrue(utils.isNumber(arr[0])); }); + it("Checks if value is null", function () { let val = null; let val2 = 1; @@ -26,25 +30,32 @@ describe("Utils Functions", function () { assert.isTrue(utils.isUndefined(arr)); }); - it("Generate number betwee two set of values", function () { - + it("Generate numbers between two set of values [both inclusive]", function () { let start = 0; let end = 5; let data = [ 0, 1, 2, 3, 4, 5 ]; assert.deepEqual(utils.range(start, end), data); }); + it("transposes an array", function () { + let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ] ]; + let result = [ [ 1, 4, 20 ], [ 2, 5, 30 ], [ 3, 6, 40 ] ]; + assert.deepEqual(utils.transposeArray(data), result); + }); + describe("inferDtype", function () { it("Returns string type present in an 1D array", function () { let data = [ 'Alice', 'Boy', 'Girl', "39" ]; let result = [ 'string' ]; assert.deepEqual(utils.inferDtype(data), result); }); + it("Returns float type present in an 1D array", function () { let data = [ 1.1, 2.1, 3.2, 4.4 ]; let result = [ 'float32' ]; assert.deepEqual(utils.inferDtype(data), result); }); + it("Returns int type present in an 1D array", function () { let data = [ 1, 2, 3, 45 ]; let result = [ 'int32' ]; @@ -55,40 +66,82 @@ describe("Utils Functions", function () { let result = [ 'float32' ]; assert.deepEqual(utils.inferDtype(data), result); }); + it("Returns float type when NaN is present in an 1D array", function () { let data = [ 1, 2, 3, 45, NaN ]; let result = [ 'float32' ]; assert.deepEqual(utils.inferDtype(data), result); }); + + it("Returns correct dtype if NaN present in data", function () { + let data = utils.transposeArray([ + [ 18.7, 17.4, 18, NaN, 19.3 ], + [ 20, NaN, 19, 18, 20 ] ]); + let result = [ 'float32', 'float32' ]; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns the data type present in an 2D array", function () { + let data = utils.transposeArray([ [ 'Alice', 'Boy', 'Girl', "39" ], [ 2, 5, 30, 89 ], [ 3.1, 6.1, 40.1, 78.2 ] ]); + let result = [ 'string', 'int32', 'float32' ]; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns the string dtype when there's a mixture of dtypes in a 2D array", function () { + let data = utils.transposeArray([ [ 'Alice', 'Boy', 'Girl', 21 ], [ 2, 5, 30, "hey" ], [ 3, 6, 40.1, 78.2 ] ]); + let result = [ 'string', 'string', 'float32' ]; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns bool type in a 1D array", function () { + let data = [ true, true, false, false, false, true ]; + let result = [ 'boolean' ]; + assert.deepEqual(utils.inferDtype(data), result); + }); + it("Returns bool type in a 2D array", function () { + let data = utils.transposeArray([ [ true, false, true ], [ "boy", "girl", "man" ], [ 20, 30, 24 ] ]); + let result = [ 'boolean', 'string', 'int32' ]; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns string type if values are all NaN", function () { + let data = utils.transposeArray([ [ true, false, true ], [ "boy", "girl", "boy" ], [ NaN, NaN, NaN ] ]); + let result = [ 'boolean', 'string', 'float32' ]; + assert.deepEqual(utils.inferDtype(data), result); + }); + }); - describe("__map_int_to_bool", function () { + describe("mapIntegersToBooleans", function () { it("map ints to bools in array of arrays", function () { let data = [ [ 1, 0, 1 ], [ 1, 1, 0 ] ]; assert.deepEqual(utils.mapIntegersToBooleans(data, 2), [ [ true, false, true ], [ true, true, false ] ]); }); + it("map ints to bools in array", function () { let data = [ 1, 0, 0, 1, 1 ]; assert.deepEqual(utils.mapIntegersToBooleans(data, 1), [ true, false, false, true, true ]); }); }); - describe("__round", function () { + describe("round", function () { it("round elements in array to 1 dp", function () { let data = [ 10.01, 2.2, 3.11, 20.505, 20.22, 40.0909 ]; assert.deepEqual(utils.round(data, 1, true), [ 10.0, 2.2, 3.1, 20.5, 20.2, 40.1 ]); }); + it("round elements in array to 2 dp", function () { let data = [ 10.019, 2.2099, 3.1145, 20.506, 20.22, 40.0909 ]; assert.deepEqual(utils.round(data, 2, true), [ 10.02, 2.21, 3.11, 20.51, 20.22, 40.09 ]); }); }); - describe("__replace_undefined_with_NaN", function () { + describe("replaceUndefinedWithNaN", function () { it("replace undefined in Series with NaN", function () { let data = [ 10.01, 2.2, undefined, 20.505, 20.22, undefined ]; assert.deepEqual(utils.replaceUndefinedWithNaN(data, true), [ 10.01, 2.2, NaN, 20.505, 20.22, NaN ]); }); + it("replace undefined in DataFrame with NaN", function () { let data = [ [ 10.01, 2.2, undefined, 20.505, 20.22, undefined ], [ 10.01, undefined, undefined, 20.505, 20, undefined ] ]; @@ -97,10 +150,12 @@ describe("Utils Functions", function () { [ 10.01, NaN, NaN, 20.505, 20, NaN ] ]; assert.deepEqual(utils.replaceUndefinedWithNaN(data, false), result); }); + it("replace null in Series with NaN", function () { let data = [ 10.01, 2.2, null, 20.505, 20.22, null ]; assert.deepEqual(utils.replaceUndefinedWithNaN(data, true), [ 10.01, 2.2, NaN, 20.505, 20.22, NaN ]); }); + it("replace null in DataFrame with NaN", function () { let data = [ [ 10.01, 2.2, null, 20.505, 20.22, null ], [ 10.01, null, null, 20.505, 20, null ] ]; @@ -111,7 +166,7 @@ describe("Utils Functions", function () { }); }); - describe("__convert_2D_to_1D", function () { + describe("convert2DArrayToSeriesArray", function () { it("convert 2D array of array to 1D of string values", function () { let data = [ [ 10.01, 2.2, "a" ], [ 20.505, 20.22, "boy" ] ]; assert.deepEqual(utils.convert2DArrayToSeriesArray(data), [ "10.01,2.2,a", "20.505,20.22,boy" ]); @@ -119,41 +174,43 @@ describe("Utils Functions", function () { }); - // describe("_throw_wrong_params_error", function () { - // it("check if the right params are passed to a function", function () { - // let params_needed = ["replace", "with", "inplace"] - // let kwargs = { "replae": 2, "with": 12, "inplace": true } - // assert.equal(utils._throw_wrong_params_error(kwargs, params_needed), false) - // }) - // it("check if the right params are passed to a function 2", function () { - // let params_needed = ["replace", "with", "inplace"] - // let kwargs = { "replace": 2, "with": 12, "inplace": true } - // assert.equal(utils._throw_wrong_params_error(kwargs, params_needed), true) - // }) - - // }) - - describe("_get_row_and_col_values", function () { + describe("throwErrorOnWrongParams", function () { + it("check if the right params are passed to a function", function () { + let paramsNeeded = [ "replace", "with", "inplace" ]; + let kwargs = { "replae": 2, "with": 12, "inplace": true }; + + assert.throws(() => { + utils.throwErrorOnWrongParams(kwargs, paramsNeeded); + }, Error, `Params Error: Required parameter not found. Your params must include the following [${paramsNeeded}]`); + }); + + it("check if the right params are passed to a function 2", function () { + let paramsNeeded = [ "replace", "with", "inplace" ]; + let kwargs = { "replace": 2, "with": 12, "inplace": true }; + utils.throwErrorOnWrongParams(kwargs, paramsNeeded); + }); + + }); + + describe("getRowAndColValues", function () { it("retreive rows and labels from column object", function () { let data = { "Alpha": [ "A", "B", "C", "D" ], count: [ 1, 2, 3, 4 ], sum: [ 20.3, 30.456, 40.90, 90.1 ] }; let res = [ [ "A", 1, 20.3 ], [ "B", 2, 30.456 ], [ "C", 3, 40.90 ], [ "D", 4, 90.1 ] ]; assert.deepEqual(utils.getRowAndColValues(data)[0], res); assert.deepEqual(utils.getRowAndColValues(data)[1], [ "Alpha", "count", "sum" ]); - }); - }); - describe("_get_duplicate", function(){ - it("obtain duplicate and their index", function(){ - + describe("getDuplicate", function () { + it("obtain duplicates and their index", function () { let data = [ 1, 2, 3, 4, 5, 3, 4, 6, 4, 5 ]; - let res = { '3': { count: 2, index: [ 2, 5 ] }, + let res = { + '3': { count: 2, index: [ 2, 5 ] }, '4': { count: 3, index: [ 3, 6, 8 ] }, - '5': { count: 2, index: [ 4, 9 ] } }; - + '5': { count: 2, index: [ 4, 9 ] } + }; assert.deepEqual(utils.getDuplicate(data), res); }); }); diff --git a/src/danfojs-browser/tsconfig.json b/src/danfojs-browser/tsconfig.json new file mode 100644 index 00000000..a17d71ae --- /dev/null +++ b/src/danfojs-browser/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "CommonJS", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "moduleResolution": "node", + "lib": ["es6", "dom"], /* Specify library files to be included in the compilation. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + "outDir": "./dist", /* Redirect output structure to the directory. */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "resolveJsonModule": true, /* Include modules imported with '.json' extension */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ + "declaration": true, + "baseUrl": "./src", + }, + "include": [ + "./src/**/*" +], +} diff --git a/danfojs-browser/webpack.config.js b/src/danfojs-browser/webpack.config.js similarity index 51% rename from danfojs-browser/webpack.config.js rename to src/danfojs-browser/webpack.config.js index 232a63a3..d1a1b413 100644 --- a/danfojs-browser/webpack.config.js +++ b/src/danfojs-browser/webpack.config.js @@ -1,38 +1,35 @@ /* eslint-disable no-undef */ const path = require("path"); -const createConfig = (target) => { +const createConfig = () => { return { mode: "production", devtool: "source-map", context: path.resolve(__dirname), entry: { - index: `./dist/index.js` + index: `./src/index.ts` }, - target: target, + target: "web", output: { path: path.resolve(__dirname, "lib"), - filename: `bundle.js`, + filename: "bundle.js", library: "dfd" }, module: { rules: [ { - // use: { - // loader: "babel-loader", - // options: { presets: [ "@babel/preset-env" ] } - // }, - test: /\.(js|jsx)$/, + test: /\.tsx?$/, + use: [ 'ts-loader', 'ify-loader' ], exclude: /node_modules/ } ] }, resolve: { - fallback: { - fs: false - } + extensions: [ '.tsx', '.ts', '.js' ] } }; }; -module.exports = [ createConfig("web") ]; +module.exports = [ + createConfig() +]; diff --git a/danfojs-browser/yarn-error.log b/src/danfojs-browser/yarn-error.log similarity index 100% rename from danfojs-browser/yarn-error.log rename to src/danfojs-browser/yarn-error.log diff --git a/src/danfojs-browser/yarn.lock b/src/danfojs-browser/yarn.lock new file mode 100644 index 00000000..5960078f --- /dev/null +++ b/src/danfojs-browser/yarn.lock @@ -0,0 +1,6704 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/cli@^7.10.5": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/cli/-/cli-7.12.10.tgz" + integrity sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ== + dependencies: + commander "^4.0.1" + convert-source-map "^1.1.0" + fs-readdir-recursive "^1.1.0" + glob "^7.0.0" + lodash "^4.17.19" + make-dir "^2.1.0" + slash "^2.0.0" + source-map "^0.5.0" + optionalDependencies: + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents" + chokidar "^3.4.0" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz" + integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== + +"@babel/core@^7.10.5", "@babel/core@^7.7.5": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== + dependencies: + "@babel/types" "^7.12.11" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== + dependencies: + "@babel/types" "^7.12.10" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-compilation-targets@^7.12.5": + version "7.12.5" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz" + integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== + dependencies: + "@babel/compat-data" "^7.12.5" + "@babel/helper-validator-option" "^7.12.1" + browserslist "^4.14.5" + semver "^5.5.0" + +"@babel/helper-create-class-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz" + integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.1" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-regexp-features-plugin@^7.12.1": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz" + integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + regexpu-core "^4.7.1" + +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz" + integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" + +"@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== + dependencies: + "@babel/types" "^7.12.10" + +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz" + integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== + dependencies: + "@babel/types" "^7.12.7" + +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": + version "7.12.5" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== + dependencies: + "@babel/types" "^7.12.5" + +"@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz" + integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== + dependencies: + "@babel/types" "^7.12.10" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-remap-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz" + integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/types" "^7.12.1" + +"@babel/helper-replace-supers@^7.12.1": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz" + integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.12.7" + "@babel/helper-optimise-call-expression" "^7.12.10" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.11" + +"@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz" + integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== + dependencies: + "@babel/types" "^7.12.11" + +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== + +"@babel/helper-wrap-function@^7.10.4": + version "7.12.3" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz" + integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.12.5": + version "7.12.5" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz" + integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== + +"@babel/plugin-proposal-async-generator-functions@^7.12.1": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz" + integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz" + integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-dynamic-import@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz" + integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + +"@babel/plugin-proposal-export-namespace-from@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz" + integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz" + integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-logical-assignment-operators@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz" + integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz" + integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-numeric-separator@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz" + integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + +"@babel/plugin-proposal-optional-catch-binding@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz" + integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz" + integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-private-methods@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz" + integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz" + integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz" + integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz" + integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-arrow-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz" + integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz" + integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + +"@babel/plugin-transform-block-scoped-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz" + integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-block-scoping@^7.12.11": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-classes@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz" + integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz" + integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-destructuring@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz" + integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz" + integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-duplicate-keys@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz" + integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-exponentiation-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz" + integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-for-of@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz" + integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-function-name@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz" + integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz" + integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz" + integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-modules-amd@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz" + integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz" + integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.12.1" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz" + integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== + dependencies: + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-identifier" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz" + integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz" + integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + +"@babel/plugin-transform-new-target@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz" + integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-object-super@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz" + integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + +"@babel/plugin-transform-parameters@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz" + integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-property-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz" + integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-regenerator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz" + integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz" + integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-runtime@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz" + integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA== + dependencies: + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + semver "^5.5.1" + +"@babel/plugin-transform-shorthand-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz" + integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz" + integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + +"@babel/plugin-transform-sticky-regex@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz" + integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-template-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz" + integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typeof-symbol@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz" + integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-escapes@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz" + integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz" + integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/preset-env@^7.10.4": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz" + integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== + dependencies: + "@babel/compat-data" "^7.12.7" + "@babel/helper-compilation-targets" "^7.12.5" + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-option" "^7.12.11" + "@babel/plugin-proposal-async-generator-functions" "^7.12.1" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-dynamic-import" "^7.12.1" + "@babel/plugin-proposal-export-namespace-from" "^7.12.1" + "@babel/plugin-proposal-json-strings" "^7.12.1" + "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.7" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.12.1" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-async-to-generator" "^7.12.1" + "@babel/plugin-transform-block-scoped-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.11" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-computed-properties" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-dotall-regex" "^7.12.1" + "@babel/plugin-transform-duplicate-keys" "^7.12.1" + "@babel/plugin-transform-exponentiation-operator" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-function-name" "^7.12.1" + "@babel/plugin-transform-literals" "^7.12.1" + "@babel/plugin-transform-member-expression-literals" "^7.12.1" + "@babel/plugin-transform-modules-amd" "^7.12.1" + "@babel/plugin-transform-modules-commonjs" "^7.12.1" + "@babel/plugin-transform-modules-systemjs" "^7.12.1" + "@babel/plugin-transform-modules-umd" "^7.12.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" + "@babel/plugin-transform-new-target" "^7.12.1" + "@babel/plugin-transform-object-super" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-property-literals" "^7.12.1" + "@babel/plugin-transform-regenerator" "^7.12.1" + "@babel/plugin-transform-reserved-words" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.7" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.10" + "@babel/plugin-transform-unicode-escapes" "^7.12.1" + "@babel/plugin-transform-unicode-regex" "^7.12.1" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.12.11" + core-js-compat "^3.8.0" + semver "^5.5.0" + +"@babel/preset-modules@^0.1.3": + version "0.1.4" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/runtime@^7.14.6", "@babel/runtime@^7.8.4": + version "7.15.4" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz" + integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.10.4", "@babel/template@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + +"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.2" + resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz" + integrity sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg== + +"@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.20" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" + integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": + version "2.1.8-no-fsevents" + resolved "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz" + integrity sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@socket.io/base64-arraybuffer@~1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz" + integrity sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ== + +"@tensorflow/tfjs-backend-cpu@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.13.0.tgz" + integrity sha512-POmzUoAP8HooYYTZ72O1ZYkpVZB0f+8PeAkbTxIG0oahcJccj6a0Vovp1A6xWKfljUoPlJb3jWVC++S603ZL8w== + dependencies: + "@types/seedrandom" "2.4.27" + seedrandom "2.4.3" + +"@tensorflow/tfjs-backend-webgl@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.13.0.tgz" + integrity sha512-ZuJS11tCoZx2F1Eq7wqiqu8euJpPW/JV0qOKBehlRpV2qQrR+wHMpBT1hhDl4qU4LdgFTtSggKIRg/L8b0ScUQ== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.13.0" + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "2.4.27" + "@types/webgl-ext" "0.0.30" + "@types/webgl2" "0.0.6" + seedrandom "2.4.3" + +"@tensorflow/tfjs-converter@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-3.13.0.tgz" + integrity sha512-H2VpDTv9Ve0HBt7ttzz46DmnsPaiT0B+yJjVH3NebGZbgY9C8boBgJIsdyqfiqEWBS3WxF8h4rh58Hv5XXMgaQ== + +"@tensorflow/tfjs-core@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-3.13.0.tgz" + integrity sha512-18qBEVIB/4u2OUK9nA5P1XT3e3LyarElD1UKNSNDpnMLxhLTUVZaCR71eHJcpl9wP2Q0cciaTJCTpJdPv1tNDQ== + dependencies: + "@types/long" "^4.0.1" + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "2.4.27" + "@types/webgl-ext" "0.0.30" + long "4.0.0" + node-fetch "~2.6.1" + seedrandom "2.4.3" + +"@tensorflow/tfjs-data@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-3.13.0.tgz" + integrity sha512-n50+lxPK0CU72nlFt4dzMCCNV44CQsQU3sSP9zdR2bYHeoFqjjy1ISp+UV5N5DNLj7bsEMs73kGS1EuJ7YcdqQ== + dependencies: + "@types/node-fetch" "^2.1.2" + node-fetch "~2.6.1" + +"@tensorflow/tfjs-layers@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-3.13.0.tgz" + integrity sha512-kTWJ/+9fbNCMDA9iQjDMYHmWivsiWz8CKNSOZdeCW7tiBwF1EiREBVQXMk1JI11ngQa8f+rYSLs7rkhp3SYl5Q== + +"@tensorflow/tfjs@^3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-3.13.0.tgz" + integrity sha512-B5HvNH+6hHhQQkn+AG+u4j5sxZBMYdsq4IWXlBZzioJcVygtZhBWXkxp01boSwngjqUBgi8S2DopBE7McAUKqQ== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.13.0" + "@tensorflow/tfjs-backend-webgl" "3.13.0" + "@tensorflow/tfjs-converter" "3.13.0" + "@tensorflow/tfjs-core" "3.13.0" + "@tensorflow/tfjs-data" "3.13.0" + "@tensorflow/tfjs-layers" "3.13.0" + argparse "^1.0.10" + chalk "^4.1.0" + core-js "3" + regenerator-runtime "^0.13.5" + yargs "^16.0.3" + +"@types/caseless@*": + version "0.12.2" + resolved "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz" + integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== + +"@types/chai@^4.2.19": + version "4.2.21" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.2.21.tgz" + integrity sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg== + +"@types/component-emitter@^1.2.10": + version "1.2.11" + resolved "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz" + integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== + +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.12" + resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz" + integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== + +"@types/d3@^3": + version "3.5.46" + resolved "https://registry.npmjs.org/@types/d3/-/d3-3.5.46.tgz" + integrity sha512-jNHfiGd41+JUV43LTMzQNidyp4Hn0XfhoSmy8baE0d/N5pGYpD+yX03JacY/MH+smFxYOQGXlz4HxkRZOuRNOQ== + +"@types/eslint-scope@^3.7.3": + version "3.7.3" + resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz" + integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.1" + resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz" + integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": + version "7.0.9" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + +"@types/long@^4.0.1": + version "4.0.1" + resolved "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz" + integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== + +"@types/mocha@^8.2.2": + version "8.2.3" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz" + integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== + +"@types/node-fetch@^2.1.2": + version "2.5.8" + resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz" + integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*", "@types/node@>=10.0.0", "@types/node@^15.12.5": + version "15.14.9" + resolved "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz" + integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== + +"@types/offscreencanvas@~2019.3.0": + version "2019.3.0" + resolved "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz" + integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q== + +"@types/papaparse@^5.2.6": + version "5.2.6" + resolved "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.2.6.tgz" + integrity sha512-xGKSd0UTn58N1h0+zf8mW863Rv8BvXcGibEgKFtBIXZlcDXAmX/T4RdDO2mwmrmOypUDt5vRgo2v32a78JdqUA== + dependencies: + "@types/node" "*" + +"@types/plotly.js-dist-min@^2.3.0": + version "2.3.0" + resolved "https://registry.npmjs.org/@types/plotly.js-dist-min/-/plotly.js-dist-min-2.3.0.tgz" + integrity sha512-MPvZbG2RA3zuU+AYgsVysJvNLyf3bvi1nt3ywHARwMW2TB38VQuYhQFD1pTRzBuqiV5ieYif7mLY5bHWGUVZqw== + dependencies: + "@types/plotly.js" "*" + +"@types/plotly.js@*": + version "1.54.17" + resolved "https://registry.npmjs.org/@types/plotly.js/-/plotly.js-1.54.17.tgz" + integrity sha512-2nk1jEDQ85Ix6SQsC7M7Otl5M8OoYwTl7V/x2ptyX373slUJAj+vQ3njYGy/h9p/rxTq7W0fn3JvXjuxXuA0Qg== + dependencies: + "@types/d3" "^3" + +"@types/request@^2.48.7": + version "2.48.7" + resolved "https://registry.npmjs.org/@types/request/-/request-2.48.7.tgz" + integrity sha512-GWP9AZW7foLd4YQxyFZDBepl0lPsWLMEXDZUjQ/c1gqVPDPECrRZyEzuhJdnPWioFCq3Tv0qoGpMD6U+ygd4ZA== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + +"@types/seedrandom@2.4.27": + version "2.4.27" + resolved "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.27.tgz" + integrity sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE= + +"@types/stream-chain@*": + version "2.0.1" + resolved "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz" + integrity sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg== + dependencies: + "@types/node" "*" + +"@types/stream-json@^1.7.1": + version "1.7.1" + resolved "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.1.tgz" + integrity sha512-BNIK/ix6iJvWvoXbDVVJhw5LNG1wie/rXcUo7jw4hBqY3FhIrg0e+RMXFN5UreKclBIStl9FDEHNSDLuuQ9/MQ== + dependencies: + "@types/node" "*" + "@types/stream-chain" "*" + +"@types/table@^6.3.2": + version "6.3.2" + resolved "https://registry.npmjs.org/@types/table/-/table-6.3.2.tgz" + integrity sha512-GJ82z3vQbx2BhiUo12w2A3lyBpXPJrGHjQ7iS5aH925098w8ojqiWBhgOUy97JS2PKLmRCTLT0sI+gJI4futig== + dependencies: + table "*" + +"@types/tough-cookie@*": + version "4.0.1" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz" + integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg== + +"@types/webgl-ext@0.0.30": + version "0.0.30" + resolved "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz" + integrity sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg== + +"@types/webgl2@0.0.6": + version "0.0.6" + resolved "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.6.tgz" + integrity sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ== + +"@typescript-eslint/eslint-plugin@^4.30.0": + version "4.30.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.30.0.tgz" + integrity sha512-NgAnqk55RQ/SD+tZFD9aPwNSeHmDHHe5rtUyhIq0ZeCWZEvo4DK9rYz7v9HDuQZFvn320Ot+AikaCKMFKLlD0g== + dependencies: + "@typescript-eslint/experimental-utils" "4.30.0" + "@typescript-eslint/scope-manager" "4.30.0" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.30.0": + version "4.30.0" + resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.30.0.tgz" + integrity sha512-K8RNIX9GnBsv5v4TjtwkKtqMSzYpjqAQg/oSphtxf3xxdt6T0owqnpojztjjTcatSteH3hLj3t/kklKx87NPqw== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.30.0" + "@typescript-eslint/types" "4.30.0" + "@typescript-eslint/typescript-estree" "4.30.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@^4.30.0": + version "4.30.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.30.0.tgz" + integrity sha512-HJ0XuluSZSxeboLU7Q2VQ6eLlCwXPBOGnA7CqgBnz2Db3JRQYyBDJgQnop6TZ+rsbSx5gEdWhw4rE4mDa1FnZg== + dependencies: + "@typescript-eslint/scope-manager" "4.30.0" + "@typescript-eslint/types" "4.30.0" + "@typescript-eslint/typescript-estree" "4.30.0" + debug "^4.3.1" + +"@typescript-eslint/scope-manager@4.30.0": + version "4.30.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.30.0.tgz" + integrity sha512-VJ/jAXovxNh7rIXCQbYhkyV2Y3Ac/0cVHP/FruTJSAUUm4Oacmn/nkN5zfWmWFEanN4ggP0vJSHOeajtHq3f8A== + dependencies: + "@typescript-eslint/types" "4.30.0" + "@typescript-eslint/visitor-keys" "4.30.0" + +"@typescript-eslint/types@4.30.0": + version "4.30.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.30.0.tgz" + integrity sha512-YKldqbNU9K4WpTNwBqtAerQKLLW/X2A/j4yw92e3ZJYLx+BpKLeheyzoPfzIXHfM8BXfoleTdiYwpsvVPvHrDw== + +"@typescript-eslint/typescript-estree@4.30.0": + version "4.30.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.30.0.tgz" + integrity sha512-6WN7UFYvykr/U0Qgy4kz48iGPWILvYL34xXJxvDQeiRE018B7POspNRVtAZscWntEPZpFCx4hcz/XBT+erenfg== + dependencies: + "@typescript-eslint/types" "4.30.0" + "@typescript-eslint/visitor-keys" "4.30.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@4.30.0": + version "4.30.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.30.0.tgz" + integrity sha512-pNaaxDt/Ol/+JZwzP7MqWc8PJQTUhZwoee/PVlQ+iYoYhagccvoHnC9e4l+C/krQYYkENxznhVSDwClIbZVxRw== + dependencies: + "@typescript-eslint/types" "4.30.0" + eslint-visitor-keys "^2.0.0" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.1.1": + version "1.1.1" + resolved "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz" + integrity sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg== + +"@webpack-cli/info@^1.4.1": + version "1.4.1" + resolved "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz" + integrity sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.6.1": + version "1.6.1" + resolved "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz" + integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +JSONStream@^1.0.3: + version "1.3.5" + resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abab@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + +accepts@~1.3.4: + version "1.3.7" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn-jsx@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + +acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: + version "1.8.2" + resolved "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0: + version "7.2.0" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.0.0, acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.4.1, acorn@^8.5.0: + version "8.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.6.2" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz" + integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@4.1.1, ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + +argparse@^1.0.10, argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert@^1.4.0: + version "1.5.0" + resolved "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +awesome-typescript-loader@^5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz" + integrity sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g== + dependencies: + chalk "^2.4.1" + enhanced-resolve "^4.0.0" + loader-utils "^1.1.0" + lodash "^4.17.5" + micromatch "^3.1.9" + mkdirp "^0.5.1" + source-map-support "^0.5.3" + webpack-log "^1.2.0" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +babel-loader@^8.1.0: + version "8.2.2" + resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz" + integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^1.4.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.5.1" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.1.3" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz" + integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== + +body-parser@^1.19.0: + version "1.19.0" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-pack@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz" + integrity sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA== + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.8.0" + defined "^1.0.0" + safe-buffer "^5.1.1" + through2 "^2.0.0" + umd "^3.0.0" + +browser-resolve@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz" + integrity sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ== + dependencies: + resolve "^1.17.0" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserify-zlib@~0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserify@16.5.2: + version "16.5.2" + resolved "https://registry.npmjs.org/browserify/-/browserify-16.5.2.tgz" + integrity sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g== + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^2.0.0" + browserify-zlib "~0.2.0" + buffer "~5.2.1" + cached-path-relative "^1.0.0" + concat-stream "^1.6.0" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "^1.2.0" + duplexer2 "~0.1.2" + events "^2.0.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "^1.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + mkdirp-classic "^0.5.2" + module-deps "^6.2.3" + os-browserify "~0.3.0" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^3.0.0" + string_decoder "^1.1.1" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "0.0.1" + url "~0.11.0" + util "~0.10.1" + vm-browserify "^1.0.0" + xtend "^4.0.0" + +browserslist@^4.14.5, browserslist@^4.16.1: + version "4.16.6" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== + dependencies: + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@~5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz" + integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: + version "1.1.0" + resolved "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz" + integrity sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA== + +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== + dependencies: + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + +caniuse-lite@^1.0.30001219: + version "1.0.30001230" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz" + integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chai@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz" + integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.0" + type-detect "^4.0.5" + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +chokidar@3.5.1: + version "3.5.1" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + +chokidar@^3.4.0, chokidar@^3.5.1: + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + +colorette@^2.0.14: + version "2.0.16" + resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + +colors@1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +colors@~0.6.0-1: + version "0.6.2" + resolved "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" + integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w= + +combine-source-map@^0.8.0, combine-source-map@~0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz" + integrity sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos= + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.0.1: + version "4.1.1" + resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +commander@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/commander/-/commander-7.0.0.tgz" + integrity sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA== + +commander@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz" + integrity sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E= + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +complex.js@^2.0.15: + version "2.0.15" + resolved "https://registry.npmjs.org/complex.js/-/complex.js-2.0.15.tgz" + integrity sha512-gDBvQU8IG139ZBQTSo2qvDFP+lANMGluM779csXOr6ny1NUtA3wkUnCFjlDNH/moAVfXtvClYt6G0zarFbtz5w== + +component-emitter@^1.2.1, component-emitter@~1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: + version "1.6.2" + resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +connect@^3.7.0: + version "3.7.0" + resolved "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +constants-browserify@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.1.0, convert-source-map@^1.1.3, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +convert-source-map@~1.1.0: + version "1.1.3" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz" + integrity sha1-SCnId+n+SbMWHzvzZziI4gRpmGA= + +cookie@~0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-compat@^3.8.0: + version "3.8.3" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz" + integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== + dependencies: + browserslist "^4.16.1" + semver "7.0.0" + +core-js@3: + version "3.8.3" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz" + integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +coveralls@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz" + integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== + dependencies: + js-yaml "^3.13.1" + lcov-parse "^1.0.0" + log-driver "^1.2.7" + minimist "^1.2.5" + request "^2.88.2" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-browserify@^3.0.0: + version "3.12.0" + resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz" + integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/d/-/d-1.0.1.tgz" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dash-ast@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz" + integrity sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA== + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +date-format@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz" + integrity sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ== + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4.3.1: + version "4.3.1" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@~4.3.1, debug@~4.3.2: + version "4.3.3" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decimal.js@^10.3.1: + version "10.3.1" + resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== + dependencies: + strip-bom "^4.0.0" + +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +deps-sort@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz" + integrity sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw== + dependencies: + JSONStream "^1.0.3" + shasum-object "^1.0.0" + subarg "^1.0.0" + through2 "^2.0.0" + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detective@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz" + integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== + dependencies: + acorn-node "^1.6.1" + defined "^1.0.0" + minimist "^1.1.1" + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/di/-/di-0.0.1.tgz" + integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serialize@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz" + integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs= + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + +domain-browser@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: + version "0.1.4" + resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz" + integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= + dependencies: + readable-stream "^2.0.2" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +electron-to-chromium@^1.3.723: + version "1.3.739" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz" + integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A== + +elliptic@^6.5.3: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +engine.io-parser@~5.0.0: + version "5.0.3" + resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz" + integrity sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg== + dependencies: + "@socket.io/base64-arraybuffer" "~1.0.2" + +engine.io@~6.1.0: + version "6.1.2" + resolved "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz" + integrity sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.0" + ws "~8.2.3" + +enhanced-resolve@^4.0.0: + version "4.5.0" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +enhanced-resolve@^5.0.0: + version "5.8.3" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz" + integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +enhanced-resolve@^5.8.3: + version "5.9.1" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.1.tgz" + integrity sha512-jdyZMwCQ5Oj4c5+BTnkxPgDZO/BJzh/ADDmKebayyzNwjVX1AFCeGkOfxNx0mHi2+8BKC5VxUYiw3TIvoT7vhw== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +ent@~2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz" + integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +errno@^0.1.3: + version "0.1.8" + resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +esbuild-android-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz#5b94a1306df31d55055f64a62ff6b763a47b7f64" + integrity sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw== + +esbuild-android-arm64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz#78acc80773d16007de5219ccce544c036abd50b8" + integrity sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA== + +esbuild-darwin-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz#e02b1291f629ebdc2aa46fabfacc9aa28ff6aa46" + integrity sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA== + +esbuild-darwin-arm64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz#01eb6650ec010b18c990e443a6abcca1d71290a9" + integrity sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ== + +esbuild-freebsd-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz#790b8786729d4aac7be17648f9ea8e0e16475b5e" + integrity sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig== + +esbuild-freebsd-arm64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz#b66340ab28c09c1098e6d9d8ff656db47d7211e6" + integrity sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ== + +esbuild-linux-32@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz#7927f950986fd39f0ff319e92839455912b67f70" + integrity sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g== + +esbuild-linux-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz#4893d07b229d9cfe34a2b3ce586399e73c3ac519" + integrity sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q== + +esbuild-linux-arm64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz#8442402e37d0b8ae946ac616784d9c1a2041056a" + integrity sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA== + +esbuild-linux-arm@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz#d5dbf32d38b7f79be0ec6b5fb2f9251fd9066986" + integrity sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA== + +esbuild-linux-mips64le@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz#95081e42f698bbe35d8ccee0e3a237594b337eb5" + integrity sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ== + +esbuild-linux-ppc64le@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz#dceb0a1b186f5df679618882a7990bd422089b47" + integrity sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q== + +esbuild-linux-riscv64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz#61fb8edb75f475f9208c4a93ab2bfab63821afd2" + integrity sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ== + +esbuild-linux-s390x@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz#34c7126a4937406bf6a5e69100185fd702d12fe0" + integrity sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ== + +esbuild-netbsd-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz#322ea9937d9e529183ee281c7996b93eb38a5d95" + integrity sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q== + +esbuild-openbsd-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz#1ca29bb7a2bf09592dcc26afdb45108f08a2cdbd" + integrity sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ== + +esbuild-sunos-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz#c9446f7d8ebf45093e7bb0e7045506a88540019b" + integrity sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA== + +esbuild-windows-32@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz#f8e9b4602fd0ccbd48e5c8d117ec0ba4040f2ad1" + integrity sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw== + +esbuild-windows-64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz#280f58e69f78535f470905ce3e43db1746518107" + integrity sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw== + +esbuild-windows-arm64@0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz#d97e9ac0f95a4c236d9173fa9f86c983d6a53f54" + integrity sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw== + +esbuild@^0.14.38: + version "0.14.38" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.38.tgz#99526b778cd9f35532955e26e1709a16cca2fb30" + integrity sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA== + optionalDependencies: + esbuild-android-64 "0.14.38" + esbuild-android-arm64 "0.14.38" + esbuild-darwin-64 "0.14.38" + esbuild-darwin-arm64 "0.14.38" + esbuild-freebsd-64 "0.14.38" + esbuild-freebsd-arm64 "0.14.38" + esbuild-linux-32 "0.14.38" + esbuild-linux-64 "0.14.38" + esbuild-linux-arm "0.14.38" + esbuild-linux-arm64 "0.14.38" + esbuild-linux-mips64le "0.14.38" + esbuild-linux-ppc64le "0.14.38" + esbuild-linux-riscv64 "0.14.38" + esbuild-linux-s390x "0.14.38" + esbuild-netbsd-64 "0.14.38" + esbuild-openbsd-64 "0.14.38" + esbuild-sunos-64 "0.14.38" + esbuild-windows-32 "0.14.38" + esbuild-windows-64 "0.14.38" + esbuild-windows-arm64 "0.14.38" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-latex@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz" + integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-scope@5.1.1, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.1.0: + version "7.18.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz" + integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.3.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^6.0.0" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.20" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.4" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/events/-/events-2.1.0.tgz" + integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== + +events@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/events/-/events-3.2.0.tgz" + integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz" + integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +executioner@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/executioner/-/executioner-2.0.1.tgz" + integrity sha1-rdMo4DvEXdWY81j7tSn8C+Dsb80= + dependencies: + mixly "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +ext@^1.1.2: + version "1.4.0" + resolved "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== + dependencies: + type "^2.0.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0, extsprintf@^1.2.0: + version "1.3.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.1.1: + version "3.2.7" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fast-safe-stringify@^2.0.7: + version "2.0.7" + resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz" + integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== + +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + +fastq@^1.6.0: + version "1.12.0" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz" + integrity sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== + dependencies: + flat-cache "^3.0.4" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^3.2.0, find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +findup@^0.1.5: + version "0.1.5" + resolved "https://registry.npmjs.org/findup/-/findup-0.1.5.tgz" + integrity sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs= + dependencies: + colors "~0.6.0-1" + commander "~2.1.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.1.0, flatted@^3.2.4: + version "3.2.4" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz" + integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + +follow-redirects@^1.0.0: + version "1.14.8" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz" + integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fraction.js@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz" + integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +from2-array@0.0.4: + version "0.0.4" + resolved "https://registry.npmjs.org/from2-array/-/from2-array-0.0.4.tgz" + integrity sha1-6vwWtl9uJxm81X/cGGkAWsEzLNY= + dependencies: + from2 "^2.0.3" + +from2@^2.0.3: + version "2.3.0" + resolved "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== + +fs-extra@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz" + integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.3.1, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +fulcon@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/fulcon/-/fulcon-1.0.2.tgz" + integrity sha1-ik39pMc/zZzGKnnVBFw5K0VUcyA= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-assigned-identifiers@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz" + integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +get-intrinsic@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz" + integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg== + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.0.0, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.1.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: + version "7.2.0" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.0, has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + +hat@^0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/hat/-/hat-0.0.3.tgz" + integrity sha1-uwFKnmSzeIrtgAWRdBPU/z1QLYo= + +he@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +htmlescape@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz" + integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.1.4: + version "1.2.1" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ify-loader@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/ify-loader/-/ify-loader-1.1.0.tgz" + integrity sha512-EiyC45FRIs+z4g98+jBzuYCfoM6TKG9p7Ek5YZUeM7rucNucaMZIseRj/5Q3I4ypkZXyC2wnU1RcYrVmshe2xw== + dependencies: + bl "^1.0.0" + findup "^0.1.5" + from2-array "0.0.4" + map-limit "0.0.1" + multipipe "^0.3.0" + read-package-json "^2.0.2" + resolve "^1.1.6" + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +inline-source-map@~0.6.0: + version "0.6.2" + resolved "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz" + integrity sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU= + dependencies: + source-map "~0.5.3" + +insert-module-globals@^7.0.0: + version "7.2.1" + resolved "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz" + integrity sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg== + dependencies: + JSONStream "^1.0.3" + acorn-node "^1.5.2" + combine-source-map "^0.8.0" + concat-stream "^1.6.1" + is-buffer "^1.1.0" + path-is-absolute "^1.0.1" + process "~0.11.0" + through2 "^2.0.0" + undeclared-identifiers "^1.1.2" + xtend "^4.0.0" + +install-peers@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/install-peers/-/install-peers-1.0.3.tgz" + integrity sha512-MAlSHlrn4p+g3fhx8ZVxQZXX+MkeinKLu/ThfAmrVnN5c2L8Vof7myb0UsgowJEiGcFNHYnTvo37r3uap5asYA== + dependencies: + executioner "^2.0.1" + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^1.1.0, is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-core-module@^2.1.0: + version "2.2.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isbinaryfile@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz" + integrity sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-processinfo@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz" + integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== + dependencies: + archy "^1.0.0" + cross-spawn "^7.0.0" + istanbul-lib-coverage "^3.0.0-alpha.1" + make-dir "^3.0.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^3.3.3" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +javascript-natural-sort@^0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz" + integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-string-escape@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz" + integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== + dependencies: + argparse "^2.0.1" + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-loader@^0.5.7: + version "0.5.7" + resolved "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz" + integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stable-stringify@~0.0.0: + version "0.0.1" + resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz" + integrity sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" + integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +karma-browserify@7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/karma-browserify/-/karma-browserify-7.0.0.tgz" + integrity sha512-SLgh1dmF2eZEj3glrmTD2CMJRGZwEiKA6k2hBr2+2JDC4JMU1dlsvBKpV66Lvi/tbj3H9qA+Vl/FdIcfPRrJpA== + dependencies: + convert-source-map "^1.1.3" + hat "^0.0.3" + js-string-escape "^1.0.0" + lodash "^4.17.14" + minimatch "^3.0.0" + os-shim "^0.1.3" + +karma-chai@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz" + integrity sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o= + +karma-chrome-launcher@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz" + integrity sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg== + dependencies: + which "^1.2.1" + +karma-mocha@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz" + integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== + dependencies: + minimist "^1.2.3" + +karma@6.3.16: + version "6.3.16" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.16.tgz#76d1a705fd1cf864ee5ed85270b572641e0958ef" + integrity sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ== + dependencies: + body-parser "^1.19.0" + braces "^3.0.2" + chokidar "^3.5.1" + colors "1.4.0" + connect "^3.7.0" + di "^0.0.1" + dom-serialize "^2.2.1" + glob "^7.1.7" + graceful-fs "^4.2.6" + http-proxy "^1.18.1" + isbinaryfile "^4.0.8" + lodash "^4.17.21" + log4js "^6.4.1" + mime "^2.5.2" + minimatch "^3.0.4" + mkdirp "^0.5.5" + qjobs "^1.2.0" + range-parser "^1.2.1" + rimraf "^3.0.2" + socket.io "^4.2.0" + source-map "^0.6.1" + tmp "^0.2.1" + ua-parser-js "^0.7.30" + yargs "^16.1.1" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +labeled-stream-splicer@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz" + integrity sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw== + dependencies: + inherits "^2.0.1" + stream-splicer "^2.0.0" + +lcov-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz" + integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + +loader-utils@^1.1.0, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz" + integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + +lodash.memoize@~3.0.3: + version "3.0.4" + resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz" + integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + +lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== + +log-symbols@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + +log-symbols@^2.1.0: + version "2.2.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + +log4js@^6.4.1: + version "6.4.1" + resolved "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz" + integrity sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg== + dependencies: + date-format "^4.0.3" + debug "^4.3.3" + flatted "^3.2.4" + rfdc "^1.3.0" + streamroller "^3.0.2" + +loglevelnext@^1.0.1: + version "1.0.5" + resolved "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz" + integrity sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A== + dependencies: + es6-symbol "^3.1.1" + object.assign "^4.1.0" + +long@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-limit@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz" + integrity sha1-63lhAxwPDo0AG/LVb6toXViCLzg= + dependencies: + once "~1.3.0" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +mathjs@9.4.4: + version "9.4.4" + resolved "https://registry.npmjs.org/mathjs/-/mathjs-9.4.4.tgz" + integrity sha512-5EEJXnWOzLDgMHSFyw623nH+MTBZxquWwXtrzTsingOouJJ6UZG2VNO1lwH31IMt9aMno1axO6TYleIP4YSDaQ== + dependencies: + "@babel/runtime" "^7.14.6" + complex.js "^2.0.15" + decimal.js "^10.3.1" + escape-latex "^1.2.0" + fraction.js "^4.1.1" + javascript-natural-sort "^0.7.1" + seedrandom "^3.0.5" + tiny-emitter "^2.1.0" + typed-function "^2.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.9: + version "3.1.10" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.0, micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.45.0: + version "1.45.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz" + integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== + +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.28" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz" + integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== + dependencies: + mime-db "1.45.0" + +mime@^2.5.2: + version "2.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mixly@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/mixly/-/mixly-1.0.0.tgz" + integrity sha1-m1ouH2Pm37oNMOZ5f/rmKrHcJO8= + dependencies: + fulcon "^1.0.1" + +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.5" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mocha@^8.3.0: + version "8.3.1" + resolved "https://registry.npmjs.org/mocha/-/mocha-8.3.1.tgz" + integrity sha512-5SBMxANWqOv5bw3Hx+HVgaWlcWcFEQDUdaUAr1AUU+qwtx6cowhn7gEDT/DwQP7uYxnvShdUOVLbTYAHOEGfDQ== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.1" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.6" + growl "1.10.5" + he "1.2.0" + js-yaml "4.0.0" + log-symbols "4.0.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.20" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +module-deps@^6.2.3: + version "6.2.3" + resolved "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz" + integrity sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA== + dependencies: + JSONStream "^1.0.3" + browser-resolve "^2.0.0" + cached-path-relative "^1.0.2" + concat-stream "~1.6.0" + defined "^1.0.0" + detective "^5.2.0" + duplexer2 "^0.1.2" + inherits "^2.0.1" + parents "^1.0.0" + readable-stream "^2.0.2" + resolve "^1.4.0" + stream-combiner2 "^1.1.1" + subarg "^1.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multipipe@^0.3.0: + version "0.3.1" + resolved "https://registry.npmjs.org/multipipe/-/multipipe-0.3.1.tgz" + integrity sha1-kmJVJXYboE/qoJYFtjgrziyR8R8= + dependencies: + duplexer2 "^0.1.2" + +nanoid@3.1.20: + version "3.1.20" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz" + integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +node-fetch@~2.6.1: + version "2.6.7" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + +node-releases@^1.1.71: + version "1.1.72" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz" + integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== + +normalize-package-data@^2.0.0: + version "2.5.0" + resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-normalize-package-bin@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nyc@^15.1.0: + version "15.1.0" + resolved "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== + dependencies: + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +once@~1.3.0: + version "1.3.3" + resolved "https://registry.npmjs.org/once/-/once-1.3.3.tgz" + integrity sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA= + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +os-browserify@~0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-shim@^0.1.3: + version "0.1.3" + resolved "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz" + integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc= + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +papaparse@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/papaparse/-/papaparse-5.3.1.tgz" + integrity sha512-Dbt2yjLJrCwH2sRqKFFJaN5XgIASO9YOFeFP8rIBRG2Ain8mqk5r1M6DkfvqEVozVcz3r3HaUGw253hA1nLIcA== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parents@^1.0.0, parents@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz" + integrity sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E= + dependencies: + path-platform "~0.11.15" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-platform@~0.11.15: + version "0.11.15" + resolved "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz" + integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.3: + version "3.1.1" + resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +plotly.js-dist-min@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/plotly.js-dist-min/-/plotly.js-dist-min-2.8.0.tgz#e489069fd6c4338832a2270c5d82c0e325135d58" + integrity sha512-6OOg/D7OEffYq1WJt4XKNHzJAd9uN3kCuKZcCr0RGvnSB3wvP7fDmfsUpxZR2q0M+3j7SKejJ8qv1HGkarnObg== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + +process@~0.11.0: + version "0.11.10" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qjobs@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz" + integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystring-es3@~0.2.0: + version "0.2.1" + resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +read-only-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz" + integrity sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A= + dependencies: + readable-stream "^2.0.2" + +read-package-json@^2.0.2: + version "2.1.2" + resolved "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz" + integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA== + dependencies: + glob "^7.1.1" + json-parse-even-better-errors "^2.3.0" + normalize-package-data "^2.0.0" + npm-normalize-package-bin "^1.0.0" + +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@^2.3.5, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz" + integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== + dependencies: + resolve "^1.9.0" + +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.2" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5: + version "0.13.7" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + +regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== + dependencies: + "@babel/runtime" "^7.8.4" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + +regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + +regjsgen@^0.5.1: + version "0.5.2" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== + +regjsparser@^0.6.4: + version "0.6.6" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz" + integrity sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ== + dependencies: + jsesc "~0.5.0" + +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz" + integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + dependencies: + es6-error "^4.0.1" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +request@^2.88.2: + version "2.88.2" + resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.1.4, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.17.0, resolve@^1.4.0, resolve@^1.9.0: + version "1.19.0" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +seedrandom@2.4.3: + version "2.4.3" + resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz" + integrity sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw= + +seedrandom@^3.0.5: + version "3.0.5" + resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz" + integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== + +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1: + version "7.3.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + +semver@^7.3.4, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: + version "2.4.11" + resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shasum-object@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz" + integrity sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg== + dependencies: + fast-safe-stringify "^2.0.7" + +shasum@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz" + integrity sha1-5wEjENj0F/TetXEhUOVni4euVl8= + dependencies: + json-stable-stringify "~0.0.0" + sha.js "~2.4.4" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.6.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + +signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +socket.io-adapter@~2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz" + integrity sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ== + +socket.io-parser@~4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz" + integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g== + dependencies: + "@types/component-emitter" "^1.2.10" + component-emitter "~1.3.0" + debug "~4.3.1" + +socket.io@^4.2.0: + version "4.4.1" + resolved "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz" + integrity sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.1.0" + socket.io-adapter "~2.3.3" + socket.io-parser "~4.0.4" + +source-map-js@^0.6.2: + version "0.6.2" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz" + integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== + +source-map-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.0.tgz" + integrity sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw== + dependencies: + abab "^2.0.5" + iconv-lite "^0.6.2" + source-map-js "^0.6.2" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.5.3, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.3: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== + dependencies: + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + which "^2.0.1" + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stream-browserify@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-combiner2@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz" + integrity sha1-+02KFCDqNidk4hrUeAOXvry0HL4= + dependencies: + duplexer2 "~0.1.0" + readable-stream "^2.0.2" + +stream-http@^3.0.0: + version "3.1.1" + resolved "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz" + integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + xtend "^4.0.2" + +stream-splicer@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz" + integrity sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.2" + +streamroller@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz" + integrity sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA== + dependencies: + date-format "^4.0.3" + debug "^4.1.1" + fs-extra "^10.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz" + integrity sha1-9izxdYHplrSPyWVpn1TAauJouNI= + dependencies: + minimist "^1.1.0" + +supports-color@8.1.1, supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +syntax-error@^1.1.1: + version "1.4.0" + resolved "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz" + integrity sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w== + dependencies: + acorn-node "^1.2.0" + +table@*, table@6.7.1, table@^6.0.4: + version "6.7.1" + resolved "https://registry.npmjs.org/table/-/table-6.7.1.tgz" + integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== + dependencies: + ajv "^8.0.1" + lodash.clonedeep "^4.5.0" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tapable@^2.1.1: + version "2.2.1" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +tapable@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz" + integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== + +terser-webpack-plugin@^5.1.3: + version "5.3.1" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz" + integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== + dependencies: + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + terser "^5.7.2" + +terser@^5.7.2: + version "5.14.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" + integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timers-browserify@^1.0.1: + version "1.4.2" + resolved "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz" + integrity sha1-ycWLV1voQHN1y14kYtrO50NZ9B0= + dependencies: + process "~0.11.0" + +tiny-emitter@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +ts-loader@^9.2.6: + version "9.2.6" + resolved "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.6.tgz" + integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + +tslib@^1.8.1, tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tty-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz" + integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.8.0, type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type-is@~1.6.17: + version "1.6.18" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.npmjs.org/type/-/type-1.2.0.tgz" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.0.0: + version "2.5.0" + resolved "https://registry.npmjs.org/type/-/type-2.5.0.tgz" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== + +typed-function@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/typed-function/-/typed-function-2.0.0.tgz" + integrity sha512-Hhy1Iwo/e4AtLZNK10ewVVcP2UEs408DS35ubP825w/YgSBK1KVLwALvvIG4yX75QJrxjCpcWkzkVRB0BwwYlA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== + +ua-parser-js@^0.7.30: + version "0.7.31" + resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz" + integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== + +umd@^3.0.0: + version "3.0.3" + resolved "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz" + integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== + +undeclared-identifiers@^1.1.2: + version "1.1.3" + resolved "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz" + integrity sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw== + dependencies: + acorn-node "^1.3.0" + dash-ast "^1.0.0" + get-assigned-identifiers "^1.2.0" + simple-concat "^1.0.0" + xtend "^4.0.1" + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.1.0" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url@~0.11.0: + version "0.11.0" + resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util@0.10.3: + version "0.10.3" + resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@~0.10.1: + version "0.10.4" + resolved "https://registry.npmjs.org/util/-/util-0.10.4.tgz" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.1.0, uuid@^3.3.2, uuid@^3.3.3: + version "3.4.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache@^2.0.3: + version "2.2.0" + resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@^1: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vm-browserify@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz" + integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + +watchpack@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +webpack-cli@4.9.2: + version "4.9.2" + resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz" + integrity sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.1.1" + "@webpack-cli/info" "^1.4.1" + "@webpack-cli/serve" "^1.6.1" + colorette "^2.0.14" + commander "^7.0.0" + execa "^5.0.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-log@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz" + integrity sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA== + dependencies: + chalk "^2.1.0" + log-symbols "^2.1.0" + loglevelnext "^1.0.1" + uuid "^3.1.0" + +webpack-merge@^5.7.3: + version "5.7.3" + resolved "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz" + integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@5.69.1: + version "5.69.1" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz" + integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.4.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.8.3" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-better-errors "^1.0.2" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.3.1" + webpack-sources "^3.2.3" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@2.0.2, which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +which@^1.2.1: + version "1.3.1" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +word-wrap@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f" + integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA== + +workerpool@6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz" + integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@~8.2.3: + version "8.2.3" + resolved "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz" + integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== + +"xlsx@https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz": + version "0.19.3" + resolved "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz#f804c1850e2da5260165db0a059dc2a6099d55f3" + +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz" + integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== + +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4, yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0, yargs@^16.0.3, yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^15.0.2: + version "15.4.1" + resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yarn@^1.22.10: + version "1.22.11" + resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.11.tgz" + integrity sha512-AWje4bzqO9RUn3sdnM5N8n4ZJ0BqCc/kqFJvpOI5/EVkINXui0yuvU7NDCEF//+WaxHuNay2uOHxA4+tq1P3cg== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/danfojs-node/.babelrc b/src/danfojs-node/.babelrc similarity index 100% rename from danfojs-node/.babelrc rename to src/danfojs-node/.babelrc diff --git a/danfojs-node/.coveralls.yml b/src/danfojs-node/.coveralls.yml similarity index 100% rename from danfojs-node/.coveralls.yml rename to src/danfojs-node/.coveralls.yml diff --git a/danfojs-browser/.eslintrc.json b/src/danfojs-node/.eslintrc.json similarity index 96% rename from danfojs-browser/.eslintrc.json rename to src/danfojs-node/.eslintrc.json index 6ad974ec..08bc17c3 100644 --- a/danfojs-browser/.eslintrc.json +++ b/src/danfojs-node/.eslintrc.json @@ -23,6 +23,9 @@ "before": false, "after": true } ], + "indent": [ "error", + 2 + ], "keyword-spacing": [ "error", { "before": true diff --git a/danfojs-node/.gitignore b/src/danfojs-node/.gitignore similarity index 59% rename from danfojs-node/.gitignore rename to src/danfojs-node/.gitignore index 7910db69..0a8e1fc9 100644 --- a/danfojs-node/.gitignore +++ b/src/danfojs-node/.gitignore @@ -5,4 +5,9 @@ coverage danfojs/data .DS_Store .idea/ -dist/* +build +lib/* +dist +*.xlsx +tensorflowlib.ts +samples/ \ No newline at end of file diff --git a/danfojs-node/.npmignore b/src/danfojs-node/.npmignore similarity index 100% rename from danfojs-node/.npmignore rename to src/danfojs-node/.npmignore diff --git a/src/danfojs-node/.prettierrc b/src/danfojs-node/.prettierrc new file mode 100644 index 00000000..ed799517 --- /dev/null +++ b/src/danfojs-node/.prettierrc @@ -0,0 +1,7 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "printWidth": 79 +} \ No newline at end of file diff --git a/danfojs-node/README.md b/src/danfojs-node/README.md similarity index 72% rename from danfojs-node/README.md rename to src/danfojs-node/README.md index 339c222a..aefc337f 100644 --- a/danfojs-node/README.md +++ b/src/danfojs-node/README.md @@ -47,70 +47,85 @@ easy and intuitive. It is heavily inspired by [Pandas](https://pandas.pydata.org - Robust data preprocessing functions like [OneHotEncoders](https://danfo.jsdata.org/api-reference/general-functions/danfo.onehotencoder), [LabelEncoders](https://danfo.jsdata.org/api-reference/general-functions/danfo.labelencoder), and scalers like [StandardScaler](https://danfo.jsdata.org/api-reference/general-functions/danfo.standardscaler) and [MinMaxScaler](https://danfo.jsdata.org/api-reference/general-functions/danfo.minmaxscaler) are supported on DataFrame and Series +## Installation +There are three ways to install and use Danfo.js in your application +* For Nodejs applications, you can install the [__danfojs-node__]() version via package managers like yarn and/or npm: -To use Danfo.js via script tags, copy and paste the CDN below to the body of your HTML file +```bash +npm install danfojs-node + +or + +yarn add danfojs-node +``` +For client-side applications built with frameworks like React, Vue, Next.js, etc, you can install the [__danfojs__]() version: + +```bash +npm install danfojs + +or + +yarn add danfojs +``` + +For use directly in HTML files, you can add the latest script tag from [JsDelivr](https://www.jsdelivr.com/package/npm/danfojs) to your HTML file: ```html - + ``` +See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) ### Example Usage in the Browser -> See the example below in [Code Sandbox](https://codepen.io/risingodegua/pen/bGwPGMG) +> Run in [Code Sandbox](https://codepen.io/risingodegua/pen/bGwPGMG) ```html - - - - - + + + + Document - - - + +
- - - + + ``` Output in Browser: ![](assets/browser-out.gif) -## How to install -Danfo.js is hosted on NPM, and can installed via package managers like npm and yarn - -```sh -npm install danfojs-node -``` - ### Example usage in Nodejs ```javascript @@ -118,7 +133,7 @@ npm install danfojs-node const dfd = require("danfojs-node") const file_url = "https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv" -dfd.read_csv(file_url) +dfd.readCSV(file_url) .then(df => { //prints the first five columns df.head().print() @@ -145,8 +160,8 @@ dfd.read_csv(file_url) //select columns by dtypes - let str_cols = df_drop.select_dtypes(["string"]) - let num_cols = df_drop.select_dtypes(["int32", "float32"]) + let str_cols = df_drop.selectDtypes(["string"]) + let num_cols = df_drop.selectDtypes(["int32", "float32"]) str_cols.print() num_cols.print() @@ -154,40 +169,47 @@ dfd.read_csv(file_url) //add new column to Dataframe let new_vals = df['Fare'].round(1) - df_drop.addColumn({ column: "fare_round", values: new_vals, inplace: true }) + df_drop.addColumn("fare_round", new_vals, { inplace: true }) df_drop.print() df_drop['fare_round'].round(2).print(5) //prints the number of occurence each value in the column - df_drop['Survived'].value_counts().print() + df_drop['Survived'].valueCounts().print() //print the last ten elementa of a DataFrame df_drop.tail(10).print() //prints the number of missing values in a DataFrame - df_drop.isna().sum().print() + df_drop.isNa().sum().print() }).catch(err => { console.log(err); }) + ``` Output in Node Console: ![](assets/node-rec.gif) - -> If you want to use Danfo in frontend frameworks like React/Vue, read this [guide](https://danfo.jsdata.org/examples/using-danfojs-in-react) - -#### You can play with Danfo.js on Dnotebooks playground [here](https://playnotebook.jsdata.org/demo) +## Notebook support +* You can use Danfo.js on Dnotebooks playground [here](https://playnotebook.jsdata.org/demo) +* VsCode nodejs notebook extension now supports Danfo.js. See guide [here](https://marketplace.visualstudio.com/items?itemName=donjayamanne.typescript-notebook) #### [See the Official Getting Started Guide](https://danfo.jsdata.org/getting-started) ## Documentation The official documentation can be found [here](https://danfo.jsdata.org) +## Danfo.js Official Book + +![image](https://user-images.githubusercontent.com/29900845/134811659-25ff6b05-8e0d-415f-a60c-03ab1d33fd71.jpeg) + + +We recently published a book titled "Building Data Driven Applications with Danfo.js". Read more about it [here](https://danfo.jsdata.org/building-data-driven-applications-with-danfo.js-book) + ## Discussion and Development -Development discussions take place on our [issues](https://github.com/opensource9ja/danfojs/issues) tab. +Development discussions take place [here](https://github.com/opensource9ja/danfojs/discussions). ## Contributing to Danfo All contributions, bug reports, bug fixes, documentation improvements, enhancements, and ideas are welcome. A detailed overview on how to contribute can be found in the [contributing guide](https://danfo.jsdata.org/contributing-guide). diff --git a/src/danfojs-node/babel.config.json b/src/danfojs-node/babel.config.json new file mode 100644 index 00000000..3f5422fd --- /dev/null +++ b/src/danfojs-node/babel.config.json @@ -0,0 +1,17 @@ +{ + "presets": [ + [ + "@babel/env", + { + "targets": { + "edge": "17", + "firefox": "60", + "chrome": "67", + "safari": "11.1" + }, + "useBuiltIns": "usage", + "corejs": "3.6.5" + } + ] + ] +} \ No newline at end of file diff --git a/src/danfojs-node/nodemon.json b/src/danfojs-node/nodemon.json new file mode 100644 index 00000000..0c84bd97 --- /dev/null +++ b/src/danfojs-node/nodemon.json @@ -0,0 +1,6 @@ +{ + "watch": ["src"], + "ext": ".ts,.js", + "ignore": [], + "exec": "yarn test" + } \ No newline at end of file diff --git a/danfojs-node/package.json b/src/danfojs-node/package.json similarity index 63% rename from danfojs-node/package.json rename to src/danfojs-node/package.json index f0621278..8df607ad 100644 --- a/danfojs-node/package.json +++ b/src/danfojs-node/package.json @@ -1,11 +1,11 @@ { "name": "danfojs-node", - "version": "0.3.4", + "version": "1.2.0", "description": "JavaScript library providing high performance, intuitive, and easy to use data structures for manipulating and processing structured data.", - "main": "dist/index.js", - "types": "types/index.d.ts", + "main": "dist/danfojs-node/src/index.js", + "types": "dist/danfojs-node/src/index.d.ts", "directories": { - "test": "tests" + "test": "test" }, "contributors": [ { @@ -16,25 +16,24 @@ } ], "files": [ - "dist/", - "types" + "dist/" ], "dependencies": { - "@tensorflow/tfjs-node": "3.11.0", + "@tensorflow/tfjs-node": "^3.13.0", "mathjs": "^9.4.4", "node-fetch": "^2.6.1", "papaparse": "^5.3.1", "request": "^2.88.2", "stream-json": "^1.7.3", "table": "6.7.1", - "xlsx": "^0.17.2" + "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz" }, "scripts": { - "test": "nyc mocha --require @babel/register tests/**/*.js", - "test:clean": "yarn run build:clean && yarn test", - "dev": "yarn run lint && babel ./src -d dist --no-comments", - "build": "babel ./src -d ./dist --no-comments", - "build:clean": "rimraf ./dist && yarn build", + "test": "nyc mocha --require ts-node/register test/**/*.test.ts", + "test:clean": "yarn build:clean && yarn test", + "dev": "nodemon", + "build": "tsc", + "build:clean": "rm -rf ./dist && node ./scripts/prebuild.js && tsc", "lint": "eslint ./src", "coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls", "coverage": "nyc report --reporter=text-lcov | coveralls && nyc report --reporter=lcov", @@ -68,12 +67,27 @@ "@babel/plugin-transform-runtime": "^7.12.10", "@babel/preset-env": "^7.10.4", "@babel/register": "^7.10.1", - "babel-plugin-add-module-exports": "^1.0.4", + "@types/chai": "^4.2.19", + "@types/chai-as-promised": "^7.1.5", + "@types/mocha": "^9.0.0", + "@types/node": "^16.9.6", + "@types/papaparse": "^5.2.6", + "@types/request": "^2.48.7", + "@types/stream-json": "^1.7.1", + "@types/table": "^6.3.2", "chai": "^4.2.0", + "chai-as-promised": "^7.1.1", "coveralls": "^3.1.0", + "dotenv": "^10.0.0", + "dts-bundle-generator": "^5.9.0", "eslint": "^7.1.0", "mocha": "^7.2.0", + "nodemon": "^2.0.7", "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-mocha": "^10.0.0", + "ts-node": "^10.0.0", + "typescript": "^4.4.2", "yarn": "^1.22.10" }, "nyc": { diff --git a/danfojs-node/types/shared/defaults.d.ts b/src/danfojs-node/scripts/prebuild.js similarity index 51% rename from danfojs-node/types/shared/defaults.d.ts rename to src/danfojs-node/scripts/prebuild.js index 72b539a5..222ba6c8 100644 --- a/danfojs-node/types/shared/defaults.d.ts +++ b/src/danfojs-node/scripts/prebuild.js @@ -1,6 +1,6 @@ /** * @license -* Copyright 2021, JsData. All rights reserved. +* Copyright 2022 JsData. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,13 +12,18 @@ * limitations under the License. * ========================================================================== */ + /** - * Default config object - */ -export declare const BASE_CONFIG: { - tableMaxRow: number; - tableMaxColInConsole: number; - dtypeTestLim: number; - lowMemoryMode: boolean; -}; -export declare const DATA_TYPES: string[]; + * Danfojs-node version uses Tensorflowjs-node package. Hence on bundling, we set the tensorflow lib + * to use the Tensorflowjs-node package. + * */ + +/* eslint-disable no-undef */ +const fs = require('fs'); + +function updateTensorflowLib(tensorflowLibPath) { + const importStatement = `const tf = require("@tensorflow/tfjs-node")\nexport default tf`; + fs.writeFileSync(tensorflowLibPath, importStatement); +} + +updateTensorflowLib('../danfojs-base/shared/tensorflowlib.ts'); diff --git a/src/danfojs-node/src/core/frame.ts b/src/danfojs-node/src/core/frame.ts new file mode 100644 index 00000000..2a38aa09 --- /dev/null +++ b/src/danfojs-node/src/core/frame.ts @@ -0,0 +1,187 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import BaseDataFrame from "../../../danfojs-base/core/frame" +import { toCSVNode, toExcelNode, toJSONNode } from "../../../danfojs-base/io/node"; +import { + BaseDataOptionType, + DataFrameInterface, + CsvOutputOptionsNode, + JsonOutputOptionsNode, + ExcelOutputOptionsNode, +} from "../../../danfojs-base/shared/types"; + +type ExtendedDataFrameInterface = DataFrameInterface & { + toCSV(options?: CsvOutputOptionsNode): string | void + toJSON(options?: JsonOutputOptionsNode): object | void + toExcel(options?: ExcelOutputOptionsNode): void +} + + +/** + * Two-dimensional ndarray with axis labels. + * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. + * Operations between DataFrame (+, -, /, , *) align values based on their associated index values– they need not be the same length. + * @param data 2D Array, JSON, Tensor, Block of data. + * @param options.index Array of numeric or string names for subseting array. If not specified, indices are auto generated. + * @param options.columns Array of column names. If not specified, column names are auto generated. + * @param options.dtypes Array of data types for each the column. If not specified, dtypes are/is inferred. + * @param options.config General configuration object for extending or setting NDframe behavior. + */ +export default class DataFrame extends BaseDataFrame implements ExtendedDataFrameInterface { + [key: string]: any + constructor(data?: any, options: BaseDataOptionType = {}) { + super(data, options) + } + + /** + * Converts a DataFrame to CSV. + * @param options Configuration object. Supports the following options: + * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. Option is only available in NodeJS. + * - `fileName`: Name of the CSV file. Defaults to `data.csv`. Option is only available in Browser. + * - `download`: If true, the CSV will be downloaded. Defaults to false. Option is only available in Browser. + * - `header`: Boolean indicating whether to include a header row in the CSV file. + * - `sep`: Character to be used as a separator in the CSV file. + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const csv = df.toCSV() + * console.log(csv) + * //output + * "A","B" + * 1,2 + * 3,4 + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const csv = df.toCSV({ header: false }) + * console.log(csv) + * //output + * 1,2 + * 3,4 + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const csv = df.toCSV({ sep: ';' }) + * console.log(csv) + * //output + * "A";"B" + * 1;2 + * 3;4 + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.toCSV({ filePath: './data.csv' }) //write to local file in NodeJS + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.toCSV({ fileName: 'data.csv', download: true }) //Downloads file in Browser + * ``` + * + */ + toCSV(options?: CsvOutputOptionsNode): string + toCSV(options?: CsvOutputOptionsNode): string | void { + return toCSVNode(this, options as CsvOutputOptionsNode) + + } + + /** + * Converts a DataFrame to JSON. + * @param options Configuration object. Supported options: + * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. Option is only available in NodeJS. + * - `fileName`: The name of the JSON file. Defaults to `data.json`. Option is only available in Browser. + * - `download`: If true, the JSON will be downloaded. Defaults to false. Option is only available in Browser. + * - `format`: The format of the JSON. Supported values are `'column'` and `'row'`. Defaults to `'column'`. + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const json = df.toJSON() + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const json = df.toJSON({ format: 'row' }) + * console.log(json) + * //output + * [{"A":1,"B":2},{"A":3,"B":4}] + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * const json = df.toJSON({ format: "column" }) + * console.log(json) + * //output + * {"A":[1,3],"B":[2,4]} + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.toJSON({ filePath: './data.json' }) // downloads to local file system as data.json in NodeJS + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.toJSON({ fileName: 'data.json', download: true }) // downloads file browser + * ``` + */ + toJSON(options?: JsonOutputOptionsNode): object + toJSON(options?: JsonOutputOptionsNode): object | void { + return toJSONNode(this, options as JsonOutputOptionsNode) + } + + + /** + * Converts a DataFrame to Excel file format. + * @param options Configuration object. Supported options: + * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. + * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. Option is only available in NodeJs + * - `fileName`: The fileName to be written to. Defaults to `'output.xlsx'`. Option is only available in Browser + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.toExcel({ filePath: './output.xlsx' }) // writes to local file system as output.xlsx in NodeJS + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.toExcel({ fileName: 'output.xlsx', download: true }) // downloads file browser + * ``` + * + * @example + * ``` + * const df = new DataFrame([[1, 2], [3, 4]], { columns: ['A', 'B']}) + * df.toExcel({ sheetName: 'Sheet2' }) // writes to Sheet2 in Excel + * ``` + * + */ + toExcel(options?: ExcelOutputOptionsNode): void { + return toExcelNode(this, options as ExcelOutputOptionsNode) + } +} \ No newline at end of file diff --git a/src/danfojs-node/src/core/series.ts b/src/danfojs-node/src/core/series.ts new file mode 100644 index 00000000..37836180 --- /dev/null +++ b/src/danfojs-node/src/core/series.ts @@ -0,0 +1,149 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ + +import BaseSeries from "../../../danfojs-base/core/series" +import { toCSVNode, toExcelNode, toJSONNode } from "../../../danfojs-base/io/node"; +import { + BaseDataOptionType, + SeriesInterface, + CsvOutputOptionsNode, + JsonOutputOptionsNode, + ExcelOutputOptionsNode +} from "../../../danfojs-base/shared/types"; + +type ExtendedSeriesInterface = SeriesInterface & { + toCSV(options?: CsvOutputOptionsNode): string | void + toJSON(options?: JsonOutputOptionsNode): object | void + toExcel(options?: ExcelOutputOptionsNode): void +} + + +/** + * One-dimensional ndarray with axis labels. + * The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. + * Operations between Series (+, -, /, , *) align values based on their associated index values – they need not be the same length. + * @param data 1D Array, JSON, Tensor, Block of data. + * @param options.index Array of numeric or string index for subseting array. If not specified, indices are auto generated. + * @param options.columns Column name. This is like the name of the Series. If not specified, column name is set to 0. + * @param options.dtypes Data types of the Series data. If not specified, dtypes is inferred. + * @param options.config General configuration object for extending or setting Series behavior. + */ +export default class Series extends BaseSeries implements ExtendedSeriesInterface { + [key: string]: any + constructor(data?: any, options: BaseDataOptionType = {}) { + super(data, options) + } + + /** + * Converts a Series to CSV. + * @param options Configuration object. Supports the following options: + * - `filePath`: Local file path to write the CSV file. If not specified, the CSV will be returned as a string. Option is only available in NodeJS. + * - `fileName`: Name of the CSV file. Defaults to `data.csv`. Option is only available in Browser. + * - `download`: If true, the CSV will be downloaded. Defaults to false. Option is only available in Browser. + * - `header`: Boolean indicating whether to include a header row in the CSV file. + * - `sep`: Character to be used as a separator in the CSV file. + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const csv = df.toCSV() + * ``` + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const csv = df.toCSV({ header: false }) + * ``` + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const csv = df.toCSV({ sep: ';' }) + * ``` + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * df.toCSV({ filePath: './data.csv' }) //write to local file in NodeJS + * ``` + */ + toCSV(options?: CsvOutputOptionsNode): string + toCSV(options?: CsvOutputOptionsNode): string | void { + return toCSVNode(this, options as CsvOutputOptionsNode) + + } + + /** + * Converts a Series to JSON. + * @param options Configuration object. Supported options: + * - `filePath`: The file path to write the JSON to. If not specified, the JSON object is returned. Option is only available in NodeJS. + * - `fileName`: The name of the JSON file. Defaults to `data.json`. Option is only available in Browser. + * - `download`: If true, the JSON will be downloaded. Defaults to false. Option is only available in Browser. + * - `format`: The format of the JSON. Supported values are `'column'` and `'row'`. Defaults to `'column'`. + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const json = df.toJSON() + * ``` + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const json = df.toJSON({ format: 'row' }) + * ``` + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * const json = df.toJSON({ format: "column" }) + * ``` + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * df.toJSON({ filePath: './data.json' }) // downloads to local file system as data.json in NodeJS + * ``` + */ + toJSON(options?: JsonOutputOptionsNode): object + toJSON(options?: JsonOutputOptionsNode): object | void { + return toJSONNode(this, options as JsonOutputOptionsNode) + } + + + /** + * Converts a Series to Excel file format. + * @param options Configuration object. Supported options: + * - `sheetName`: The sheet name to be written to. Defaults to `'Sheet1'`. + * - `filePath`: The filePath to be written to. Defaults to `'./output.xlsx'`. Option is only available in NodeJs + * - `fileName`: The fileName to be written to. Defaults to `'output.xlsx'`. Option is only available in Browser + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * df.toExcel({ filePath: './output.xlsx' }) // writes to local file system as output.xlsx in NodeJS + * ``` + * + * @example + * ``` + * const df = new Series([1, 2, 3, 4]) + * df.toExcel({ sheetName: 'Sheet2' }) // writes to Sheet2 in Excel + * ``` + * + */ + toExcel(options?: ExcelOutputOptionsNode): void { + return toExcelNode(this, options as ExcelOutputOptionsNode) + } +} \ No newline at end of file diff --git a/src/danfojs-node/src/index.ts b/src/danfojs-node/src/index.ts new file mode 100644 index 00000000..8a40e1e5 --- /dev/null +++ b/src/danfojs-node/src/index.ts @@ -0,0 +1,80 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { + NDframe, + Config, + Utils, + Str, + Dt, + MinMaxScaler, + StandardScaler, + LabelEncoder, + OneHotEncoder, + getDummies, + concat, + merge, + toDateTime, + dateRange, + tensorflow, + __version +} from "../../danfojs-base"; +import { + streamCsvTransformer, + convertFunctionTotransformer +} from "./streams/csv.stream.transformer" +import { + readCSVNode as readCSV, + streamCSVNode as streamCSV, + toCSVNode as toCSV, + readJSONNode as readJSON, + toJSONNode as toJSON, + streamJSONNode as streamJSON, + readExcelNode as readExcel, + toExcelNode as toExcel +} from "../../danfojs-base/io/node" + +import DataFrame from "./core/frame" +import Series from "./core/series" + +export { + NDframe, + Config, + Utils, + Str, + Dt, + toDateTime, + Series, + DataFrame, + readCSV, + streamCSV, + toCSV, + streamCsvTransformer, + convertFunctionTotransformer, + readJSON, + toJSON, + streamJSON, + readExcel, + toExcel, + MinMaxScaler, + StandardScaler, + LabelEncoder, + OneHotEncoder, + getDummies, + concat, + merge, + dateRange, + tensorflow, + __version +} diff --git a/src/danfojs-node/src/streams/csv.stream.transformer.ts b/src/danfojs-node/src/streams/csv.stream.transformer.ts new file mode 100644 index 00000000..457ebd60 --- /dev/null +++ b/src/danfojs-node/src/streams/csv.stream.transformer.ts @@ -0,0 +1,113 @@ +/** +* @license +* Copyright 2022 JsData. All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. + +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ========================================================================== +*/ +import { CsvInputOptionsNode, CsvOutputOptionsNode } from "../../../danfojs-base/shared/types" +import { writeCsvOutputStreamNode, openCsvInputStreamNode } from "../../../danfojs-base/io/node" +import DataFrame from "../core/frame" +import stream from "stream" + +/** + * Converts a function to a pipe transformer. + * @param func The function to convert to a pipe transformer. + * @returns A pipe transformer that applies the function to each row of object. + * @example + * ``` + * import { convertFunctionTotransformer } from "danfojs-node" + * + * const renamer = (dfRow) => { + * const dfModified = dfRow["Names"].map((name) => name.split(",")[0]) + * return dfModified + * } + * const transformer = convertFunctionTotransformer(renamer) + * ``` + * +*/ +const convertFunctionTotransformer = (func: (df: DataFrame) => DataFrame) => { + const transformStream = new stream.Transform({ objectMode: true }) + transformStream._transform = (chunk: any, encoding, callback) => { + const outputChunk = func(chunk) + transformStream.push(outputChunk) + callback() + } + return transformStream +} + + +/** + * A pipeline transformer to stream a CSV file from local storage, + * transform it with custom transformer, and write to the output stream. + * @param inputFilePath The path to the CSV file to stream from. + * @param transformer The transformer function to apply to each row. Note that each row + * of the CSV file is passed as a DataFrame with a single row to the transformer function, and + * the transformer function is expected to return a transformed DataFrame. + * @param options Configuration options for the pipeline. Includes: + * - `outputFilePath` The local file path to write the transformed CSV file to. + * - `customCSVStreamWriter` A custom CSV stream writer function. This is applied at the end of each transform. + * If not provided, the default CSV stream writer is used, and this writes to local storage. + * - `inputStreamOptions` Configuration options for the input stream. Supports all Papaparse csv reader config options. + * - `outputStreamOptions` Configuration options for the output stream. This only applies when + * using the default CSV stream writer. Supports all `toCSV` options. + * @returns A promise that resolves when the pipeline is complete. + * @example + * ``` + * import { streamCsvTransformer } from "danfojs-node" + * + * const transformer = (dfRow) => { + * const dfModified = dfRow["Names"].map((name) => name.split(",")[0]) + * return dfModified + * } + * const inputFilePath = "./data/input.csv" + * const outputFilePath = "./data/output.csv" + * + * streamCsvTransformer(inputFilePath, transformer, { outputFilePath }) + * ``` +*/ +const streamCsvTransformer = ( + inputFilePath: string, + transformer: (df: DataFrame) => DataFrame, + options: { + outputFilePath?: string, + customCSVStreamWriter?: any, + inputStreamOptions?: CsvInputOptionsNode, + outputStreamOptions?: CsvOutputOptionsNode + }) => { + const { outputFilePath, customCSVStreamWriter, inputStreamOptions, outputStreamOptions } = { + outputFilePath: "./", + inputStreamOptions: {}, + outputStreamOptions: {}, + ...options + } + + if (customCSVStreamWriter) { + openCsvInputStreamNode(inputFilePath, inputStreamOptions)?.pipe(convertFunctionTotransformer(transformer)) + .pipe(customCSVStreamWriter()) + .on("error", (err: any) => { + console.error("An error occurred while transforming the CSV file") + console.error(err) + }) + } else { + openCsvInputStreamNode(inputFilePath, inputStreamOptions)?.pipe(convertFunctionTotransformer(transformer)) + // @ts-ignore + .pipe(writeCsvOutputStreamNode(outputFilePath, outputStreamOptions)) + .on("error", (err: any) => { + console.error("An error occurred while transforming the CSV file") + console.error(err) + }) + } +} + +export { + streamCsvTransformer, + convertFunctionTotransformer +} diff --git a/src/danfojs-node/test/aggregators/groupby.test.ts b/src/danfojs-node/test/aggregators/groupby.test.ts new file mode 100644 index 00000000..d267c5cb --- /dev/null +++ b/src/danfojs-node/test/aggregators/groupby.test.ts @@ -0,0 +1,383 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame } from '../../dist/danfojs-node/src'; + + +describe("groupby", function () { + it("Check group by One column data", function () { + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let groupDf = df.groupby(["A"]); + + let groupDict = { + '1': { A: [1], B: [2], C: [3] }, + '4': { A: [4], B: [5], C: [6] }, + '20': { A: [20], B: [30], C: [40] }, + '39': { A: [39], B: [89], C: [78] } + } + assert.deepEqual(groupDf.colDict, groupDict); + }); + + it("Obtain the DataFrame of one of the group", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A"]); + let new_data = [[1, 2, 3]]; + assert.deepEqual(group_df.getGroup([1]).values, new_data); + }); + + it("Check group by Two column data", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + let new_data = { + '1-2': { A: [1], B: [2], C: [3] }, + '4-5': { A: [4], B: [5], C: [6] }, + '20-30': { A: [20], B: [30], C: [40] }, + '39-89': { A: [39], B: [89], C: [78] } + } + assert.deepEqual(group_df.colDict, new_data); + }); + + it("Obtain the DataFrame of one of the group, grouped by two column", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + let new_data = [[1, 2, 3]]; + + assert.deepEqual(group_df.getGroup([1, 2]).values, new_data); + }); + + it("Count column in group", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + let new_data = [ + [1, 2, 1], + [4, 5, 1], + [20, 30, 1], + [39, 89, 1] + ]; + + assert.deepEqual(group_df.col(["C"]).count().values, new_data); + }); + + it("sum column element in group", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + let new_data = [ + [1, 2, 3], + [4, 5, 6], + [20, 30, 40], + [39, 89, 78] + ]; + assert.deepEqual(group_df.col(["C"]).sum().values, new_data); + }); + + it("sum column element group by two column", function () { + + let data = [[1, 2, 3], [1, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + + let new_data = [ + [1, 2, 2, 3], + [1, 5, 5, 6], + [20, 30, 30, 40], + [39, 89, 89, 78] + ]; + + assert.deepEqual(group_df.col(["B", "C"]).sum().values, new_data); + }); + + it("Perform aggregate on column for groupby", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + let new_data = [ + [1, 2, 2, 1], + [4, 5, 5, 1], + [20, 30, 30, 1], + [39, 89, 89, 1] + ]; + + assert.deepEqual(group_df.agg({ B: "mean", C: "count" }).values, new_data); + }); + + it("cummulative sum for groupby", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + let new_data = [ + [1, 2, 2, 3], + [4, 5, 5, 6], + [20, 30, 30, 40], + [39, 89, 89, 78] + ]; + assert.deepEqual(group_df.col(["B", "C"]).cumSum().values, new_data); + }); + + it("cummulative max for groupby", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A"]); + let new_data = [[1, 3], [4, 6], [20, 40], [39, 78]]; + + + assert.deepEqual(group_df.col(["C"]).cumMax().values, new_data); + }); + + it("cummulative min for groupby", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A"]); + let new_data = [[1, 3], [4, 6], [20, 40], [39, 78]]; + + assert.deepEqual(group_df.col(["C"]).cumMin().values, new_data); + }); + + it("cummulative prod for groupby", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A"]); + let new_data = [[1, 3], [4, 6], [20, 40], [39, 78]]; + + assert.deepEqual(group_df.col(["C"]).cumProd().values, new_data); + }); + + it("mean for groupby", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let group_df = df.groupby(["A", "B"]); + let new_data = [ + [1, 2, 2, 3], + [4, 5, 5, 6], + [20, 30, 30, 40], + [39, 89, 89, 78] + ]; + + assert.deepEqual(group_df.col(["B", "C"]).mean().values, new_data); + }); + + it("should apply grouby operation to all column", function () { + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'two', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let grp = df.groupby(["A", "B"]); + let rslt = [ + ['foo', 'one', 2, 2], + ['foo', 'two', 2, 2], + ['foo', 'three', 1, 1], + ['bar', 'one', 1, 1], + ['bar', 'three', 1, 1], + ['bar', 'two', 1, 1] + ]; + + assert.deepEqual(grp.count().values, rslt); + }); + it("should apply function to specific column", function () { + + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'two', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["A"]); + let rslt = [ + ['foo', 5, 3], + ['foo', 6, 4], + ['foo', 7, 7], + ['foo', 9, 8], + ['foo', 10, 9], + ['bar', 4, 5], + ['bar', 3, 6], + ['bar', 8, 4] + ] + assert.deepEqual(group_df.col(['D', 'C']).apply((x) => x.add(2)).values, rslt); + }); + + it("should apply function to group column", function () { + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'two', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["A", "B"]); + let rslt = [ + ['foo', 'one', 2, 2, 2, 2], + ['foo', 'two', 2, 2, 2, 2], + ['foo', 'three', 1, 1, 1, 1], + ['bar', 'one', 1, 1, 1, 1], + ['bar', 'three', 1, 1, 1, 1], + ['bar', 'two', 1, 1, 1, 1] + ] + assert.deepEqual(group_df.apply((x) => x.count({ axis: 0 })).values, rslt); + }); + + it("should obtain the number of groups", function () { + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'two', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["A", "B"]); + let rslt = 6 + assert.equal(group_df.ngroups, rslt); + }); + it("should obtain all groups", function () { + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'two', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["A", "B"]); + let rslt = { + 'foo-one': { + A: ['foo', 'foo'], + B: ['one', 'one'], + C: [1, 6], + D: [3, 7] + }, + 'bar-one': { A: ['bar'], B: ['one'], C: [3], D: [2] }, + 'foo-two': { + A: ['foo', 'foo'], + B: ['two', 'two'], + C: [2, 5], + D: [4, 5] + }, + 'bar-three': { A: ['bar'], B: ['three'], C: [4], D: [1] }, + 'bar-two': { A: ['bar'], B: ['two'], C: [2], D: [6] }, + 'foo-three': { A: ['foo'], B: ['three'], C: [7], D: [8] } + } + assert.deepEqual(group_df.groups, rslt); + }); + + it("should obtain the first row of all groups", function () { + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'one', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["A", "B"]); + let rslt = [ + ['foo', 'one', 'foo', 'one', 1, 3], + ['foo', 'two', 'foo', 'two', 5, 5], + ['foo', 'three', 'foo', 'three', 7, 8], + ['bar', 'one', 'bar', 'one', 3, 2], + ['bar', 'three', 'bar', 'three', 4, 1], + ['bar', 'two', 'bar', 'two', 2, 6] + ] + assert.deepEqual(group_df.first().values, rslt); + }); + + it("should obtain the last row of all groups", function () { + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'one', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["A", "B"]); + let rslt = [ + ['foo', 'one', 'foo', 'one', 6, 7], + ['foo', 'two', 'foo', 'two', 5, 5], + ['foo', 'three', 'foo', 'three', 7, 8], + ['bar', 'one', 'bar', 'one', 3, 2], + ['bar', 'three', 'bar', 'three', 4, 1], + ['bar', 'two', 'bar', 'two', 2, 6] + ] + assert.deepEqual(group_df.last().values, rslt); + }); + + it("should obtain the number of rows of each groups", function () { + let data = { + 'A': ['foo', 'bar', 'foo', 'bar', + 'foo', 'bar', 'foo', 'foo'], + 'B': ['one', 'one', 'one', 'three', + 'two', 'two', 'one', 'three'], + 'C': [1, 3, 2, 4, 5, 2, 6, 7], + 'D': [3, 2, 4, 1, 5, 6, 7, 8] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["A", "B"]); + let rslt = [ + ['foo', 'one', 3], + ['foo', 'two', 1], + ['foo', 'three', 1], + ['bar', 'one', 1], + ['bar', 'three', 1], + ['bar', 'two', 1] + ] + assert.deepEqual(group_df.size().values, rslt); + }); + + it("issue 396: fix groupby when first column is int", function () { + let data = { + 'hours': [5, 6, 2, 8, 4, 3], + 'worker': ["david", "david", "john", "alice", "john", "david"], + 'day': ["monday", "tuesday", "wednesday", "thursday", "friday", "friday"] + }; + let df = new DataFrame(data); + let group_df = df.groupby(["worker"]); + let rslt = [ + ["david", 3, 3], + ["john", 2, 2], + ["alice", 1, 1] + ]; + assert.deepEqual(group_df.count().values, rslt); + }); +}) \ No newline at end of file diff --git a/danfojs-node/tests/core/date_range.js b/src/danfojs-node/test/core/daterange.test.ts similarity index 51% rename from danfojs-node/tests/core/date_range.js rename to src/danfojs-node/test/core/daterange.test.ts index fc044172..ba7edd17 100644 --- a/danfojs-node/tests/core/date_range.js +++ b/src/danfojs-node/test/core/daterange.test.ts @@ -1,26 +1,22 @@ import { assert } from "chai"; -import { date_range } from '../../src/core/date_range'; +import { describe, it } from "mocha"; +import { dateRange } from '../../dist/danfojs-node/src'; -describe("date_range", function(){ - - // it("Obtain date between start and end specified", function(){ - - // let d = new date_range({"start":'2018-04-24',"end":'2018-04-27'}) - // let rslt = [ - // '4/24/2018, 12:00:00 AM', - // '4/25/2018, 12:00:00 AM', - // '4/26/2018, 12:00:00 AM', - // '4/27/2018, 12:00:00 AM' - // ] - - // assert.deepEqual(d,rslt) +describe("dateRange", function(){ + // it("Obtain date between start and end specified", function(){ + // let d = dateRange({start:'2018-04-24',end:'2018-04-27'}) + // let rslt = [ + // '4/24/2018, 1:00:00 AM', + // '4/25/2018, 1:00:00 AM', + // '4/26/2018, 1:00:00 AM', + // '4/27/2018, 1:00:00 AM' + // ] + // assert.deepEqual(d,rslt) // }); it("Obtain date between start with end not specified, but period and freq specified", function(){ - - - let d = new date_range({ "start":'1/1/2018', period:5, freq:'M' }); + let d = dateRange({ start:'1/1/2018', period:5, freq:'M' }); let rslt = [ '1/1/2018, 12:00:00 AM', '2/1/2018, 12:00:00 AM', @@ -28,14 +24,10 @@ describe("date_range", function(){ '4/1/2018, 12:00:00 AM', '5/1/2018, 12:00:00 AM' ]; - assert.deepEqual(d, rslt); - - }); it("Obtain date between start with end not specified, but period and freq specified, plus offset", function(){ - - let d = new date_range({ start:'1/1/2018', period:5, freq:'3M' }); + let d = dateRange({ start:'1/1/2018', period:5, freq:'3M' }); let rslt = [ '1/1/2018, 12:00:00 AM', '4/1/2018, 12:00:00 AM', @@ -43,14 +35,10 @@ describe("date_range", function(){ '10/1/2018, 12:00:00 AM', '1/1/2019, 12:00:00 AM' ]; - assert.deepEqual(d, rslt); - - }); it("Obtain date between start with end not specified, but period and freq specified, plus offset, longer freq", function(){ - - let d = new date_range({ start:'1/1/2018', period:5, freq:'35m' }); + let d = dateRange({ start:'1/1/2018', period:5, freq:'35m' }); let rslt = [ "1/1/2018, 12:00:00 AM", "1/1/2018, 12:35:00 AM", @@ -58,14 +46,10 @@ describe("date_range", function(){ "1/1/2018, 1:45:00 AM", "1/1/2018, 2:20:00 AM" ]; - assert.deepEqual(d, rslt); - - }); it("Obtain date range with start not specified but end and period is given", function(){ - - let d = new date_range({ end:'1/1/2018', period:8 }); + let d = dateRange({ end:'1/1/2018', period:8 }); let rslt = [ '12/25/2017, 12:00:00 AM', '12/26/2017, 12:00:00 AM', @@ -76,18 +60,33 @@ describe("date_range", function(){ '12/31/2017, 12:00:00 AM', '1/1/2018, 12:00:00 AM' ]; - assert.deepEqual(d, rslt); - - }); it("inputing wrong freq", function(){ - assert.throws(function () { new date_range({ end:'1/1/2018', period:8, freq:"d" }); }, Error, 'invalid freq d'); + assert.throws(function () { dateRange({ end:'1/1/2018', period:8, freq:"d" }); }, Error, 'invalid freq d'); }); it("inputing wrong freq with offset", function(){ - assert.throws(function () { new date_range({ end:'1/1/2018', period:8, freq:"4d" }); }, Error, 'invalid freq d'); + assert.throws(function () { dateRange({ end:'1/1/2018', period:8, freq:"4d" }); }, Error, 'invalid freq d'); }); it("inputing wrong freq offset", function(){ - assert.throws(function () { new date_range({ end:'1/1/2018', period:8, freq:"abcm" }); }, Error, 'invalid freq offset abc'); + assert.throws(function () { dateRange({ end:'1/1/2018', period:8, freq:"abcm" }); }, Error, 'invalid freq offset abc'); }); + // it("Obtain date between start and end specified with different month", function(){ + + // let d = dateRange({start:'2018-04-24',end:'2018-05-27'}) + // let rslt = [ + // '4/24/2018, 1:00:00 AM', + // '4/25/2018, 1:00:00 AM', + // '4/26/2018, 1:00:00 AM', + // '4/27/2018, 1:00:00 AM', + // '4/28/2018, 1:00:00 AM', + // '4/29/2018, 1:00:00 AM', + // '4/30/2018, 1:00:00 AM', + // '5/1/2018, 1:00:00 AM', + // '5/2/2018, 1:00:00 AM', + // '5/3/2018, 1:00:00 AM', + // '5/27/2018, 1:00:00 AM' + // ] + // assert.deepEqual(d,rslt) + // }); }); diff --git a/src/danfojs-node/test/core/datetime.test.ts b/src/danfojs-node/test/core/datetime.test.ts new file mode 100644 index 00000000..2a2e5683 --- /dev/null +++ b/src/danfojs-node/test/core/datetime.test.ts @@ -0,0 +1,114 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { Series } from "../../dist/danfojs-node/src"; +import { toDateTime } from '../../dist/danfojs-node/src'; + +describe("TimeSeries", function () { + + it("Returns correct month number", function () { + const data = ["02Sep2019", "03Aug2019", "04July2019"]; + const dateTime = toDateTime(data); + const expected = [8, 7, 6]; + assert.deepEqual(dateTime.month().values, expected); + }); + + it("Returns correct year number", function () { + const data = ["02Sep2019", "03Aug2029", "04July2020"]; + const dateTime = toDateTime(data); + const expected = [2019, 2029, 2020]; + assert.deepEqual(dateTime.year().values, expected); + }); + + it("Return month name generated", function () { + const data = ["06-30-02019", "07-29-2019", "08-28-2019"]; + const dateTime = toDateTime(data); + const expected = ["June", "July", "August"]; + assert.deepEqual(dateTime.monthName().values, expected); + }); + + it("Return day of the week generated", function () { + const data = ["06-30-02019", "07-29-2019", "08-28-2019"]; + const dateTime = toDateTime(data); + const expected = ["Sunday", "Monday", "Wednesday"]; + assert.deepEqual(dateTime.dayOfWeekName().values, expected); + }); + + it("Return day of the month generated", function () { + const data = ["06-30-02019", "07-29-2019", "08-28-2019"]; + const dateTime = toDateTime(data); + const expected = [30, 29, 28]; + assert.deepEqual(dateTime.dayOfMonth().values, expected); + }); + + it("Return seconds generated", function () { + const data = ["06-30-02019 00:00:12", "07-29-2019 00:30:40", "08-28-2019 00:12:04"]; + const dateTime = toDateTime(data); + const expected = [12, 40, 4]; + assert.deepEqual(dateTime.seconds().values, expected); + }); + + it("Return minutes generated", function () { + const data = ["06-30-02019 00:00:12", "07-29-2019 00:30:40", "08-28-2019 00:12:04"]; + const dateTime = toDateTime(data); + const expected = [0, 30, 12]; + assert.deepEqual(dateTime.minutes().values, expected); + }); + + it("Return hours generated", function () { + const data = ["06-30-02019 05:00:12", "07-29-2019 01:30:40", "08-28-2019 06:12:04"]; + const dateTime = toDateTime(data); + const expected = [5, 1, 6]; + assert.deepEqual(dateTime.hours().values, expected); + }); + + it("Return correct date from Series format 1", function () { + const data = new Series(["12/30/19 00:01", "12/29/19 07:03", "11/12/20 18:21"]); + const dateTime = toDateTime(data); + + const expectedMonth = [11, 11, 10]; + const expectedYear = [2019, 2019, 2020]; + const expectedDayOfMonth = [30, 29, 12]; + const expectedMonthName = ["December", "December", "November"]; + + assert.deepEqual(dateTime.month().values, expectedMonth); + assert.deepEqual(dateTime.year().values, expectedYear); + assert.deepEqual(dateTime.dayOfMonth().values, expectedDayOfMonth); + assert.deepEqual(dateTime.monthName().values, expectedMonthName); + }); + + it("Return correct date from Series format 2", function () { + const data = new Series(["12.30.19", "12.22.19", "11.01.20"]); + const dateTime = toDateTime(data); + + const expectedMonth = [11, 11, 10]; + const expectedYear = [2019, 2019, 2020]; + const expectedDay = [1, 0, 0]; + const expectedMonthName = ["December", "December", "November"]; + + assert.deepEqual(dateTime.month().values, expectedMonth); + assert.deepEqual(dateTime.year().values, expectedYear); + assert.deepEqual(dateTime.dayOfWeek().values, expectedDay); + assert.deepEqual(dateTime.monthName().values, expectedMonthName); + + }); + + it("Returns date string in standard JS format", function () { + const data = ["02Sep2019", "03Aug2019", "04July2019"]; + const dateTime = toDateTime(data); + const expected = [ + '9/2/2019, 12:00:00 AM', + '8/3/2019, 12:00:00 AM', + '7/4/2019, 12:00:00 AM' + ] + + const data2 = new Series(["12.30.19", "12.22.19", "11.01.20"]); + const dateTime2 = toDateTime(data2); + const expected2 = [ + '12/30/2019, 12:00:00 AM', + '12/22/2019, 12:00:00 AM', + '11/1/2020, 12:00:00 AM' + ] + assert.deepEqual(dateTime.date().values, expected); + assert.deepEqual(dateTime2.date().values, expected2); + }); +}); diff --git a/src/danfojs-node/test/core/frame.test.ts b/src/danfojs-node/test/core/frame.test.ts new file mode 100644 index 00000000..e41bd9e5 --- /dev/null +++ b/src/danfojs-node/test/core/frame.test.ts @@ -0,0 +1,3118 @@ +import { assert, expect } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, Series } from '../../dist/danfojs-node/src'; + + +describe("DataFrame", function () { + + describe("Subsetting by column names", function () { + it("retrieves the col data created from an df with two columns", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4] }; + let df = new DataFrame(data); + assert.deepEqual(df["alpha"].values, ["A", "B", "C", "D"]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + }); + it("retrieves the column data from an df with three columns", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + assert.deepEqual(df["alpha"].values, ["A", "B", "C", "D"]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + assert.deepEqual(df["val_sum"].values, [20.3, 30.456, 40.90, 90.1]); + }); + + it("Set column count by subseting", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + df["alpha"] = ["E", "F", "G", "H"] + assert.deepEqual(df["alpha"].values, ["E", "F", "G", "H"]); + assert.deepEqual(df.values[0], ['E', 1, 20.3]); + assert.deepEqual(df.dtypes, ["string", "int32", "float32",]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + assert.deepEqual(df["val_sum"].values, [20.3, 30.456, 40.90, 90.1]); + }); + + it("Correct dtype is set after setting a column by subseting", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + df["alpha"] = [2.4, 5.6, 32.5, 1] + + assert.deepEqual(df["alpha"].values, [2.4, 5.6, 32.5, 1]); + assert.deepEqual(df.values[0], [2.4, 1, 20.3]); + assert.deepEqual(df.values[1], [5.6, 2, 30.456]); + assert.deepEqual(df.values[2], [32.5, 3, 40.90]); + assert.deepEqual(df.values[3], [1, 4, 90.1]); + + df["val_count"] = ["A", "B", "C", "D"] + assert.deepEqual(df["val_count"].values, ["A", "B", "C", "D"]); + assert.deepEqual(df.dtypes, ["float32", "string", "float32",]); + }); + + it("retrieves the col data created from an df with two columns in low memory mode", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4] }; + let df = new DataFrame(data, { config: { lowMemoryMode: true } }); + assert.deepEqual(df["alpha"].values, ["A", "B", "C", "D"]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + }); + it("retrieves the column data from an df with threee columns in low memory mode", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data, { config: { lowMemoryMode: true } }); + assert.deepEqual(df["alpha"].values, ["A", "B", "C", "D"]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + assert.deepEqual(df["val_sum"].values, [20.3, 30.456, 40.90, 90.1]); + }); + + it("Set column count by subseting (low memory mode) ", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data, { config: { lowMemoryMode: true } }); + df["alpha"] = ["E", "F", "G", "H"] + assert.deepEqual(df["alpha"].values, ["E", "F", "G", "H"]); + assert.deepEqual(df.values[0], ['E', 1, 20.3]); + assert.deepEqual(df.dtypes, ["string", "int32", "float32",]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + assert.deepEqual(df["val_sum"].values, [20.3, 30.456, 40.90, 90.1]); + }); + + it("Correct dtype is set after setting a column by subseting (low memory mode) ", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data, { config: { lowMemoryMode: true } }); + df["alpha"] = [2.4, 5.6, 32.5, 1] + assert.deepEqual(df["alpha"].values, [2.4, 5.6, 32.5, 1]); + assert.deepEqual(df.values[0], [2.4, 1, 20.3]); + assert.deepEqual(df.values[1], [5.6, 2, 30.456]); + assert.deepEqual(df.values[2], [32.5, 3, 40.90]); + assert.deepEqual(df.values[3], [1, 4, 90.1]); + assert.deepEqual(df.dtypes, ["float32", "int32", "float32",]); + }); + }) + + describe("addColumn", function () { + it("Add new array values to DataFrame works", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + const newdf = df.addColumn("new_column", ["a", "b", "c", "d"]) as DataFrame; + assert.deepEqual(newdf["new_column"].values, ["a", "b", "c", "d"]); + assert.deepEqual(newdf.columns, ["alpha", "val_count", "val_sum", "new_column"]); + assert.deepEqual(newdf.dtypes, ["string", "int32", "float32", "string"]); + assert.deepEqual(newdf.index, [0, 1, 2, 3]); + }); + it("Add new array values to DataFrame inplace works", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + df.addColumn("new_column", ["a", "b", "c", "d"], { inplace: true }); + assert.deepEqual(df["new_column"].values, ["a", "b", "c", "d"]); + assert.deepEqual(df.columns, ["alpha", "val_count", "val_sum", "new_column"]); + assert.deepEqual(df.dtypes, ["string", "int32", "float32", "string"]); + assert.deepEqual(df.index, [0, 1, 2, 3]); + }); + it("Add new Series to DataFrame works", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + const newdf = df.addColumn("new_column", new Series(["a", "b", "c", "d"])) as DataFrame; + assert.deepEqual(newdf["new_column"].values, ["a", "b", "c", "d"]); + assert.deepEqual(newdf.columns, ["alpha", "val_count", "val_sum", "new_column"]); + assert.deepEqual(newdf.dtypes, ["string", "int32", "float32", "string"]); + assert.deepEqual(newdf.index, [0, 1, 2, 3]); + }); + it("Correct column data is set", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + df.addColumn("new_column", ["a", "b", "c", "d"], { inplace: true }); + assert.deepEqual(df["new_column"].values, ["a", "b", "c", "d"]); + assert.deepEqual(df["alpha"].values, ["A", "B", "C", "D"]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + assert.deepEqual(df["val_sum"].values, [20.3, 30.456, 40.90, 90.1]); + }); + it("throw error for wrong column length", function () { + const data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + const df = new DataFrame(data); + + assert.throws( + () => df.addColumn("new_column", new Series(["a", "b", "c"])), Error, + 'ParamError: Column data length mismatch. You provided data with length 3 but Ndframe has column of length 4'); + + }); + it("Ensure add column does not mutate parent when not in place", function () { + const data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + const df = new DataFrame(data); + const dfNew = df.addColumn("new_column", ["a", "b", "c", "d"]) as DataFrame + assert.notDeepEqual(df, dfNew) + assert.deepEqual(dfNew["new_column"].values, ["a", "b", "c", "d"]); + assert.deepEqual(df["alpha"].values, ["A", "B", "C", "D"]); + assert.deepEqual(df["val_count"].values, [1, 2, 3, 4]); + assert.deepEqual(df["val_sum"].values, [20.3, 30.456, 40.90, 90.1]); + }); + it("Add new array values to DataFrame works", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + const newdf = df.addColumn("new_column", ["a", "b", "c", "d"], { atIndex: 0 }) as DataFrame; + assert.deepEqual(newdf["new_column"].values, ["a", "b", "c", "d"]); + assert.deepEqual(newdf.columns, ["new_column", "alpha", "val_count", "val_sum"]); + assert.deepEqual(newdf.dtypes, ["string", "int32", "float32", "string"]); + assert.deepEqual(newdf.index, [0, 1, 2, 3]); + }); + + it("Add new array values to specific column index", function () { + let data = { alpha: ["A", "B", "C", "D"], val_count: [1, 2, 3, 4], val_sum: [20.3, 30.456, 40.90, 90.1] }; + let df = new DataFrame(data); + const newdf = df.addColumn("new_column", ["a", "b", "c", "d"], { atIndex: 'alpha' }) as DataFrame; + assert.deepEqual(newdf["new_column"].values, ["a", "b", "c", "d"]); + assert.deepEqual(newdf.columns, ["new_column", "alpha", "val_count", "val_sum"]); + assert.deepEqual(newdf.dtypes, ["string", "int32", "float32", "string"]); + assert.deepEqual(newdf.index, [0, 1, 2, 3]); + }); + }) + + describe("drop", function () { + it("throw error for wrong column name", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(function () { + df.drop({ columns: ["3"] }); + }, + Error, + 'ParamError: specified column "3" not found in columns'); + }); + it("throw error for wrong row index", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(function () { df.drop({ index: [10] }); }, + Error, 'ParamError: specified index "10" not found in indices'); + }); + + it("drop a column inplace", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + df.drop({ columns: ["C", "B"], inplace: true }); + assert.deepEqual(df.columns, ["A"]); + assert.deepEqual(df.values, [[1], [4]]); + assert.deepEqual(df["A"].values, [1, 4]); + assert.deepEqual(df.dtypes, ["int32"]); + }); + it("drop a column inplace in low memory mode", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, config: { lowMemoryMode: true } }); + df.drop({ columns: ["C", "B"], inplace: true }); + assert.deepEqual(df.columns, ["A"]); + assert.deepEqual(df.values, [[1], [4]]); + assert.deepEqual(df["A"].values, [1, 4]); + assert.deepEqual(df.dtypes, ["int32"]); + }); + it("drop a scalar column inplace", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + df.drop({ columns: "C", inplace: true }); + assert.deepEqual(df.columns, ["A", "B"]); + assert.deepEqual(df.values, [[1, 2], [4, 5]]); + assert.deepEqual(df["A"].values, [1, 4]); + assert.deepEqual(df["B"].values, [2, 5]); + }); + it("check if data is updated after column is dropped", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + df.drop({ columns: ["C"], inplace: true }); + const new_data = [[1, 2], [4, 5]]; + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.dtypes.length, 2); + + }); + + it("check if data is updated after row is dropped", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const dfNew = new DataFrame(data, { columns: cols }); + const df = dfNew.drop({ index: [0] }) as DataFrame; + const new_data = [[4, 5, 6]]; + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.dtypes, ["int32", "int32", "int32"]); + assert.deepEqual(df["A"].values, [4]); + assert.deepEqual(df["B"].values, [5]); + assert.deepEqual(df["C"].values, [6]); + assert.deepEqual(df.columns, cols); + assert.notDeepEqual(dfNew, df) + }); + it("check if data is updated after row is dropped (inplace)", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + df.drop({ index: [0], inplace: true }); + const new_data = [[4, 5, 6]]; + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.dtypes, ["int32", "int32", "int32"]); + assert.deepEqual(df["A"].values, [4]); + assert.deepEqual(df["B"].values, [5]); + assert.deepEqual(df["C"].values, [6]); + assert.deepEqual(df.columns, cols); + }); + it("check if new dataframe is properly created after column is dropped (not-in-inplace)", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const df_drop = df.drop({ columns: ["C"], inplace: false }) as DataFrame; + + const expected_data = [[1, 2], [4, 5]]; + const expected_cols = ["A", "B"]; + const expected_df = new DataFrame(expected_data, { columns: expected_cols }); + assert.deepEqual(df_drop.values, expected_df.values); + }); + it("check that the dtype is updated after column drop", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + df.drop({ columns: ["A"], inplace: true }); + const dtype = ['int32', 'int32']; + assert.deepEqual(df.dtypes, dtype); + }); + it("drop row by single string labels", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 34, 5]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["a", "b", "c"] }); + df.drop({ index: ["a"], inplace: true }); + const new_data = [[4, 5, 6], [20, 34, 5]]; + assert.deepEqual(df.values, new_data); + }); + it("drop row by two or more string labels", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 34, 5], [2, 3.4, 5], [2.0, 340, 5]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["a", "b", "c", "d", "e"] }); + df.drop({ index: ["a", "b"], inplace: true }); + const new_data = [[20, 34, 5], [2, 3.4, 5], [2.0, 340, 5]]; + assert.deepEqual(df.values, new_data); + + }); + it("drop row by two or more string labels with numeric index", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 34, 5], [2, 3.4, 5], [2.0, 340, 5]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["a", "b", 1, "d", "e"] }); + df.drop({ index: [1, "b"], inplace: true }); + const new_data = [[1, 2, 3], [2, 3.4, 5], [2.0, 340, 5]] + assert.deepEqual(df.values, new_data); + assert.deepEqual(df.index, ["a", "d", "e"]); + + }); + }); + + describe("head", function () { + it("Gets the first n rows in a DataFrame", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.deepEqual(df.head(2).values, [[1, 2, 3], [4, 5, 6]]); + }); + it("Throws error if row specified is less than 0", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(() => df.head(-1), Error, + "ParamError: Number of rows cannot be less than 1"); + }); + it("Returns all rows when size of DataFrame is less than default (5)", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.deepEqual(df.head().values, data); + }); + + }); + + describe("tail", function () { + it("Prints the last n rows of a DataFrame", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.deepEqual(df.tail(2).values, [[20, 30, 40], [39, 89, 78]]); + }); + it("Throws error if row specified is less than 0", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(() => df.tail(-1), Error, + "ParamError: Number of rows cannot be less than 1"); + }); + it("Return last 3 row index in a DataFrame", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.deepEqual(df.tail(2).index, [2, 3]); + }); + it("Check print format on head call", function () { + const data = [[1, 2, 34, 5, 0, 6, 4, 5, 6, 7], [20, 30, 40, 39, 89, 78, 45, 56, 56, 45]]; + const df = new DataFrame(data); + assert.deepEqual(df.tail(2).values, [[1, 2, 34, 5, 0, 6, 4, 5, 6, 7], [20, 30, 40, 39, 89, 78, 45, 56, 56, 45]]); + }); + it("Returns all rows when size of DataFrame is less than default (5)", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.deepEqual(df.tail().values, data); + }); + }); + + describe("sample", function () { + it("Samples n number of random elements from a DataFrame", async function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const expected = [[1, 2, 3], [20, 30, 40]]; + const values = (await df.sample(2)).values; + assert.deepEqual(values, expected); + }); + it("Throw error if n is greater than length of Dataframe", async function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + try { + await df.sample(100); + } catch (e: any) { + expect(e).to.be.instanceOf(Error); + expect(e.message).to.eql('ParamError: Sample size cannot be bigger than number of rows'); + } + }); + it("Throw error if n is less than 0", async function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + try { + await df.sample(-2); + } catch (e: any) { + expect(e).to.be.instanceOf(Error); + expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); + } + }); + it("Throw error if n is 0", async function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + try { + await df.sample(0); + } catch (e: any) { + expect(e).to.be.instanceOf(Error); + expect(e.message).to.eql('ParamError: Sample size cannot be less than 1'); + } + }); + it("Seed works and random number is reproducible", async function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78], [100, 200, 300]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const values1 = (await df.sample(2, { seed: 453 })).values; + const values2 = (await df.sample(2, { seed: 453 })).values; + const values3 = (await df.sample(2, { seed: 1 })).values; + + assert.deepEqual(values1, values2); + assert.notDeepEqual(values1, values3); + + }); + }); + + describe("loc", function () { + + it("throw error for wrong column name", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(function () { + df.loc({ "rows": [0, 1], "columns": ["A", "D"] }); + }, + Error, + "IndexError: Specified column (D) not found"); + }); + + it(`check data after selecting { "rows": ["0", "1"], "columns": ["B", "C"] }`, function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["0", "1"] }); + + const colDf = df.loc({ "rows": ["0", "1"], "columns": ["B", "C"] }); + const expected = [[2, 3], [5, 6]]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after selecting row index", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: [0, 1] }); + + const colDf = df.loc({ "rows": ["1"], "columns": ["B"] }); + const expected = [[5]]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after selecting with single row index", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["0", "1"] }); + + const colDf = df.loc({ "rows": [`"1"`], "columns": ["B", "C"] }); + const expected = [[5, 6]]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after selecting with single column index", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["0", "1"] }); + + const colDf = df.loc({ "rows": [`"0"`], "columns": ["A"] }); + const expected = [[1]]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row and column slice", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["0", "1", "2", "3"] }); + + const colDf = df.loc({ "rows": [`'0':'2'`], "columns": ["B:C"] }); + const expected = [[2], [5]]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row slice", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.loc({ "rows": [`0:2`], "columns": ["B", "C"] }); + const expected = [[2, 3], [5, 6]]; + + assert.deepEqual(colDf.values, expected); + + }); + it(`check data after column slice ["A:C"]`, function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols, index: ["0", "1", "2", "3"] }); + + const colDf = df.loc({ "rows": ["0", "1"], "columns": ["A:C"] }); + const expected = [[1, 2], [4, 5]]; + assert.deepEqual(colDf.values, expected); + + }); + it("check data after numeric row slice", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.loc({ "rows": [0, 1], "columns": ["A:C"] }); + const expected = [[1, 2], [4, 5]]; + assert.deepEqual(colDf.values, expected); + + }); + it("loc by single string index", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + + const df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); + const subDf = df.loc({ rows: [`"a"`], columns: ["Name", "Count"] }); + const expected = [['Apples', 21]]; + assert.deepEqual(subDf.values, expected); + + }); + + it("loc by slice string index", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + + const df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); + const subDf = df.loc({ rows: [`"a":"c"`], columns: ["Name", "Count"] }); + const expected = [["Apples", 21], ["Mango", 5]]; + assert.deepEqual(subDf.values, expected); + + }); + + + }); + + describe("DataFrame iloc", function () { + + it("throw error for wrong row index (array format)", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "rows": [0, 1, 3] }); + }, + Error, + "Invalid row parameter: Specified index 3 cannot be bigger than index length 2"); + }); + + it("throw error for wrong row index (string slice format)", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "rows": ["1:5"] }); + }, + Error, + "row slice [end] index cannot be bigger than 2"); + }); + + it("throw error for wrong column index (array format)", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "columns": [1, 4] }); + }, + Error, + "Invalid column parameter: Specified index 4 cannot be bigger than index length 3"); + }); + + it("throw error for wrong column index (string slice format)", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(function () { + df.iloc({ "columns": ["A:C"] }); + }, + Error, + "Invalid column split parameter. Split parameter must be a number"); + }); + + it("iloc works for {row: [0, 1], column: [1, 2]}", function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [0, 1], "columns": [1, 2] }); + const expected = [[2, 3], [5, 6]]; + + assert.deepEqual(colDf.values, expected); + + }); + + it(`iloc works for { "rows": [1], "columns": [1, 2] }`, function () { + const data = [[1, 2, 3], [4, 5, 6]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const colDf = df.iloc({ "rows": [1], "columns": [1, 2] }); + const expected = [[5, 6]]; + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row and column slice", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": ["0:2"], "columns": ["1:2"] }); + const expected = [[2], [5]]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after row slice", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": ["0:2"], "columns": [1, 2] }); + const expected = [[2, 3], [5, 6]]; + + assert.deepEqual(colDf.values, expected); + + }); + it("check data after column slice", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [0, 1, 2], "columns": ["1:2"] }); + const expected = [[2], [5], [30]]; + assert.deepEqual(colDf.values, expected); + + }); + it("Return all columns if columns parameter is not specified", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "rows": [0, 1, 2] }); + const expected = [[1, 2, 3], [4, 5, 6], [20, 30, 40]]; + assert.deepEqual(colDf.values, expected); + + }); + it("Return all rows if rows parameter is not specified", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const colDf = df.iloc({ "columns": ["1:2"] }); + const expected = [[2], [5], [30], [89]]; + assert.deepEqual(colDf.values, expected); + + }); + it("column slice starting with 0 and returning a single result works", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250], + "index": [1, 2, 3, 4] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: ["2:3"], columns: ["0:1"] }); + const result = [["Banana"]]; + assert.deepEqual(subDf.values, result); + + }); + it("column slice with format '0:' works", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: ["2:3"], columns: ["0:"] }); + const result = [["Banana", 30, 40]]; + assert.deepEqual(subDf.values, result); + + }); + it("column slice with format ':2' works", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: ["2:3"], columns: [":2"] }); + const result = [["Banana", 30]]; + assert.deepEqual(subDf.values, result); + + }); + it("row slice with format ':2' works", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: [":2"], columns: [":1"] }); + const result = [['Apples'], ['Mango']]; + assert.deepEqual(subDf.values, result); + + }); + it("row slice with format '1:' works", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: [":2"], columns: [":2"] }); + const result = [['Apples', 21], ['Mango', 5]]; + assert.deepEqual(subDf.values, result); + + }); + + }); + + describe("toString", function () { + it("Prints a DataFrame to console", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + df.print() + }) + it("User config works when printing a DataFrame to console", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data, { + config: { + tableDisplayConfig: { + header: { + alignment: 'center', + content: 'THE HEADER\nThis is the table about something', + }, + }, + } + }); + df.print() + }) + it("Long columns are properly truncated before printing", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250], + "Name2": ["Apples", "Mango", "Banana", "Pear"], + "Count2": [21, 5, 30, 10], + "Price2": [200, 300, 40, 250], + "Name3": ["Apples", "Mango", "Banana", "Pear"], + "Count3": [21, 5, 30, 10], + "Price3": [200, 300, 40, 250], + "Name4": ["Apples", "Mango", "Banana", "Pear"], + "Count4": [21, 5, 30, 10], + "Price4": [200, 300, 40, 250], + "Name5": ["Apples", "Mango", "Banana", "Pear"], + "Count5": [21, 5, 30, 10], + "Price6": [200, 300, 40, 250], + "Name7": ["Apples", "Mango", "Banana", "Pear"], + "Count7": [21, 5, 30, 10], + "Price7": [200, 300, 40, 250], + "Name8": ["Apples", "Mango", "Banana", "Pear"], + "Count8": [21, 5, 30, 10], + "Price8": [200, 300, 40, 250], + "Name9": ["Apples", "Mango", "Banana", "Pear"], + "Count9": [21, 5, 30, 10], + "Price9": [200, 300, 40, 250], + "Name10": ["Apples", "Mango", "Banana", "Pear"], + "Count10": [21, 5, 30, 10], + "Price10": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + df.print() + }) + + it("Long rows are automatically truncated", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear", "Apples", "Mango", "Banana", "Pear", "Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10, 21, 5, 30, 10, 21, 5, 30, 10], + "Price": [200, 300, 40, 250, 200, 300, 40, 250, 200, 300, 40, 250] + }; + const df = new DataFrame(data); + df.print() + }) + }) + + describe("add", function () { + it("Return Addition of DataFrame with a single Number", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data) + assert.deepEqual(df.add(2).values, [[2, 4, 6], [362, 182, 362]]); + }); + it("Return addition of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.add(sf) as DataFrame).values, [[1, 4, 5], [361, 182, 361]]); + }); + it("Return addition of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = [1, 2, 1] + const df = new DataFrame(data); + assert.deepEqual((df.add(sf) as DataFrame).values, [[1, 4, 5], [361, 182, 361]]); + }); + it("Return addition of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], + [360, 180, 360]]; + const sf = new Series([1, 2]); + const df = new DataFrame(data); + assert.deepEqual((df.add(sf, { axis: 0 }) as DataFrame).values, [[1, 3, 5], [362, 182, 362]]); + }); + it("Return addition of a DataFrame with a Array along axis 0", function () { + const data = [[0, 2, 4], + [360, 180, 360]]; + const sf = [1, 2] + const df = new DataFrame(data); + assert.deepEqual((df.add(sf, { axis: 0 }) as DataFrame).values, [[1, 3, 5], [362, 182, 362]]); + }); + it("Return addition of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.add(df2) as DataFrame).values, [[1, 4, 8], [370, 185, 360]]); + }); + it("Return addition of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.add(df2) as DataFrame).values, [[1, 4, 8], [370, 185, 360]]); + }); + it("Return addition of a DataFrame with a Series along default axis 1 (inplace)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + df.add(sf, { axis: 1, inplace: true }) + assert.deepEqual(df.values, [[1, 4, 5], [361, 182, 361]]); + }); + + it("Return addition of a DataFrame with a DataFrame along axis 0 (inplace)", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + df1.add(df2, { axis: 0, inplace: true }) + assert.deepEqual(df1.values, [[1, 4, 8], [370, 185, 360]]); + }); + it("Adds work for DataFrame with undefined and null values", function () { + const df1 = new DataFrame([[undefined, 2, 4], [360, NaN, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + df1.add(df2, { axis: 0, inplace: true }) + assert.deepEqual(df1.values, [[NaN, 4, 8], [370, NaN, 360]]); + }); + + }); + + describe("sub", function () { + it("Return subtraction of DataFrame with a single Number", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual((df.sub(2) as DataFrame).values, [[-2, 0, 2], [358, 178, 358]]); + }); + it("Return subtraction of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.sub(sf) as DataFrame).values, [[-1, 0, 3], [359, 178, 359]]); + }); + it("Return subtraction of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2]); + const df = new DataFrame(data); + assert.deepEqual((df.sub(sf, { axis: 0 }) as DataFrame).values, [[-1, 1, 3], [358, 178, 358]]); + }); + it("Return subtraction of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.sub(df2) as DataFrame).values, [[-1, 0, 0], [350, 175, 360]]); + }); + it("Return subtraction of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.sub(df2) as DataFrame).values, [[-1, 0, 0], [350, 175, 360]]); + }); + + }); + + describe("mul", function () { + it("Return multiplication of DataFrame with a single Number", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual((df.mul(2) as DataFrame).values, [[0, 4, 8], [720, 360, 720]]); + }); + it("Return multiplication of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.mul(sf) as DataFrame).values, [[0, 4, 4], [360, 360, 360]]); + }); + it("Return multiplication of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2]); + const df = new DataFrame(data); + assert.deepEqual((df.mul(sf, { axis: 0 }) as DataFrame).values, [[0, 2, 4], [720, 360, 720]]); + }); + it("Return multiplication of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.mul(df2) as DataFrame).values, [[0, 4, 16], [3600, 900, 0]]); + }); + it("Return multiplication of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.mul(df2, { axis: 0 }) as DataFrame).values, [[0, 4, 16], [3600, 900, 0]]); + }); + + }); + + describe("div", function () { + it("Return division of DataFrame with a single Number", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual((df.div(2) as DataFrame).values, [[0, 1, 2], [180, 90, 180]]); + }); + it("Return division of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.div(sf) as DataFrame).values, [[0, 1, 4], [360, 90, 360]]); + }); + it("Return division of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2]); + const df = new DataFrame(data); + assert.deepEqual((df.div(sf, { axis: 0 }) as DataFrame).values, [[0, 2, 4], [180, 90, 180]]); + }); + it("Return division of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.div(df2) as DataFrame).values, [[0, 1, 1], [36, 36, Infinity]]); + }); + it("Return division of same DataFrame along axis 0", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + assert.deepEqual((df1.div(df1) as DataFrame).values, [[NaN, 1, 1], [1, 1, 1]]); + }); + it("Return division of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.div(df2) as DataFrame).values, [[0, 1, 1], [36, 36, Infinity]]); + }); + + }); + + describe("pow", function () { + it("Return exponential of DataFrame with a single Number", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual((df.pow(2) as DataFrame).values, [[0, 4, 16], [129600, 32400, 129600]]); + }); + it("Return exponential of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.pow(sf) as DataFrame).values, [[0, 4, 4], [360, 32400, 360]]); + }); + it("Return exponential of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const sf = new Series([1, 2]); + const df = new DataFrame(data); + assert.deepEqual((df.pow(sf, { axis: 0 }) as DataFrame).values, [[0, 2, 4], [129600, 32400, 129600]]); + }); + it("Return exponential of a DataFrame with another DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [3, 10, 4]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.pow(df2) as DataFrame).values, [[0, 4, 256], [59049, 100000, 1]]); + }); + it("Return exponential of a DataFrame with another DataFrame along axis 0", function () { + const df1 = new DataFrame([[0, 2, 4], [3, 10, 4]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.pow(df2, { axis: 0 }) as DataFrame).values, [[0, 4, 256], [59049, 100000, 1]]); + }); + + }); + + describe("diff", function () { + it("Return same DataFrame if other === 0", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const df = new DataFrame(data); + assert.deepEqual((df.diff(0) as DataFrame).values, [[0, 2, 4], [10, 10, 10], [1, 2, 3]]); + }); + it("Return difference of DataFrame with previous row", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const df = new DataFrame(data); + assert.deepEqual((df.diff(1) as DataFrame).values, [[NaN, NaN, NaN], [10, 8, 6], [-9, -8, -7]]); + }); + it("Return difference of DataFrame with following row", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const df = new DataFrame(data); + assert.deepEqual((df.diff(-1) as DataFrame).values, [[-10, -8, -6], [9, 8, 7], [NaN, NaN, NaN]]); + }); + it("Return difference of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.diff(sf) as DataFrame).values, [[-1, 0, 3], [9, 8, 9], [0, 0, 2]]); + }); + it("Return difference of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.diff(sf, {axis: 0}) as DataFrame).values, [[-1, 1, 3], [8, 8, 8], [0, 1, 2]]); + }); + it("Return difference of a DataFrame with along axis 0 (column-wise), previous column", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const df = new DataFrame(data); + assert.deepEqual((df.diff(1, { axis: 0 }) as DataFrame).values, [[NaN, 2, 2], [NaN, 0, 0], [NaN, 1, 1]]); + }); + it("Return difference of a DataFrame with along axis 0 (column-wise), following column", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const df = new DataFrame(data); + assert.deepEqual((df.diff(-1, { axis: 0 }) as DataFrame).values, [[-2, -2, NaN], [0, 0, NaN], [-1, -1, NaN]]); + }); + it("Return difference of a DataFrame with another DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [3, 10, 4]]); + const df2 = new DataFrame([[-1, -2, 4], [10, 5, 0]]); + assert.deepEqual((df1.diff(df2) as DataFrame).values, [[1, 4, 0], [-7, 5, 4]]); + }); + it("Throw error if DataFrame for diff contains string", function () { + const df = new DataFrame([["words", "words", "words"], ["words", "words", "words"]]); + assert.throws(() => { + df.diff(1); + }, Error, "TypeError: diff operation is not supported for string dtypes"); + }); + }); + + describe("pctChange", function () { + it("Return same DataFrame if other === 0", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const df = new DataFrame(data); + assert.deepEqual((df.pctChange(0) as DataFrame).values, [[0, 2, 4], [10, 10, 10], [1, 2, 3]]); + }); + it("Return difference in percentage of DataFrame with previous row", function () { + const data = [[90], [900], [900]]; + const df = new DataFrame(data); + assert.deepEqual((df.pctChange(1) as DataFrame).values, [[NaN], [9], [0]]); + }); + it("Return difference in percentage of DataFrame with following row", function () { + const data = [[0, 5, 15], [10, 10, 10], [1, 2, 5]]; + const df = new DataFrame(data); + assert.deepEqual((df.pctChange(-1) as DataFrame).values, [[-1, -0.5, 0.5], [9, 4, 1], [NaN, NaN, NaN]]); + }); + it("Return difference in percentage of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.pctChange(sf) as DataFrame).values, [[-1, 0, 3], [9, 4, 9], [0, 0, 2]]); + }); + it("Return difference in percentage of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.pctChange(sf, {axis: 0})).values, [[-1, 1, 3], [4, 4, 4], [0, 1, 2]]); + }); + it("Return difference in percentage of a DataFrame with along axis 0 (column-wise), previous column", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 3]]; + const df = new DataFrame(data); + assert.deepEqual((df.pctChange(1, { axis: 0 }) as DataFrame).values, [[NaN, -1, 1], [NaN, 0, 0], [NaN, 1, 0.5]]); + }); + it("Return difference in percentage of a DataFrame with along axis 0 (column-wise), following column", function () { + const data = [[0, 2, 4], [10, 10, 10], [1, 2, 8]]; + const df = new DataFrame(data); + assert.deepEqual((df.pctChange(-1, { axis: 0 }) as DataFrame).values, [[-1, -0.5, NaN], [0, 0, NaN], [-0.5, -0.75, NaN]]); + }); + it("Return difference in percentage of a DataFrame with another DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [3, 10, 4]]); + const df2 = new DataFrame([[-1, -2, 4], [6, 5, 0]]); + assert.deepEqual((df1.pctChange(df2) as DataFrame).values, [[-1, -2, 0], [-0.5, 1, -1]]); + }); + it("Throw error if DataFrame for pctChange contains string", function () { + const df = new DataFrame([["words", "words", "words"], ["words", "words", "words"]]); + assert.throws(() => { + df.pctChange(1); + }, Error, "TypeError: pctChange operation is not supported for string dtypes"); + }); + }); + + describe("mod", function () { + it("Return modulus of DataFrame with a single Number", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual((df.mod(2) as DataFrame).values, [[0, 0, 0], [0, 0, 0]]); + }); + it("Return modulus of a DataFrame with a Series along default axis 1", function () { + const data = [[0, 2, 4], [31, 15, 360]]; + const sf = new Series([1, 2, 1]); + const df = new DataFrame(data); + assert.deepEqual((df.mod(sf) as DataFrame).values, [[0, 0, 0], [0, 1, 0]]); + }); + it("Return modulus of a DataFrame with a Series along axis 0", function () { + const data = [[0, 2, 4], [31, 15, 360]]; + const sf = new Series([1, 2]); + const df = new DataFrame(data); + assert.deepEqual((df.mod(sf, { axis: 0 }) as DataFrame).values, [[0, 0, 0], [1, 1, 0]]); + }); + it("Return modulus of a DataFrame with a DataFrame along default axis 1", function () { + const df1 = new DataFrame([[0, 2, 4], [31, 15, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.mod(df2) as DataFrame).values, [[0, 0, 0], [1, 0, NaN]]); + }); + it("Return modulus of a DataFrame with a DataFrame along axis 0", function () { + const df1 = new DataFrame([[0, 2, 4], [360, 180, 360]]); + const df2 = new DataFrame([[1, 2, 4], [10, 5, 0]]); + assert.deepEqual((df1.mod(df2) as DataFrame).values, [[0, 0, 0], [0, 0, NaN]]); + }); + + }); + + describe("mean", function () { + it("Returns the mean of a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4], + [360, 180, 360]]; + const df = new DataFrame(data, { columns: ["col1", "col2", "col3"], index: ["row1", "row2"] }); + assert.deepEqual(df.mean().values, [2, 300]); + assert.deepEqual(df.mean().index, ["row1", "row2"]); + }); + it("Return mean of a DataFrame along axis 1 (column)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.mean({ "axis": 1 }).values, [2, 300]); + }); + it("Removes NaN before calculating mean of a DataFrame", function () { + const data = [[11, 20, 3], + [NaN, 15, 6], + [2, 30, 40], + [2, 89, 78]]; + const df = new DataFrame(data); + assert.deepEqual(df.mean({ "axis": 1 }).values, [11.333333333333334, 10.5, 24, 56.333333333333336]); + }); + it("Return mean of a DataFrame along axis 0 (column)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data, { columns: ["col1", "col2", "col3"] }); + assert.deepEqual(df.mean({ "axis": 0 }).values, [180, 91, 182]); + assert.deepEqual(df.mean({ "axis": 0 }).index, ["col1", "col2", "col3"]); + + }); + it("Removes NaN before calculating mean of a DataFrame along axis 0 (column)", function () { + const data = [[11, 20, 3], + [NaN, 15, 6], + [2, 30, 40], + [2, 89, 78]]; + const df = new DataFrame(data); + assert.deepEqual(df.mean({ "axis": 0 }).values, [5, 38.5, 31.75]); + }); + }); + + describe("median", function () { + it("Returns the median of a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.median().values, [2, 360]); + }); + it("Return median of a DataFrame along axis 0 (row)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.median({ "axis": 0 }).values, [180, 91, 182]); + }); + + }); + + describe("mode", function () { + it("Returns the mode of a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4, 2], [360, 180, 360]] + const df = new DataFrame(data) + assert.deepEqual(df.mode().values, [2, 360]) + }) + it("Returns the mode of a DataFrame with keep set to 1", function () { + const data = [[0, 2, 4, 2, 4], [360, 180, 360, 360]] + const df = new DataFrame(data) + assert.deepEqual(df.mode({ keep: 1 }).values, [4, 360]) + }) + it("Returns mode of a DataFrame along axis 0 (row)", function () { + const data = [[0, 2, 4], + [360, 180, 360], + [0, 2, 360]] + const df = new DataFrame(data) + assert.deepEqual(df.mode({ "axis": 0 }).values, [0, 2, 360]) + }) + it("Returns mode of a DataFrame along axis 0 for objects", function () { + const data = { "col1": [0, 2, 4, 0], "col2": [360, 180, 360, 360] } + const df = new DataFrame(data) + assert.deepEqual(df.mode({ "axis": 0 }).values, [0, 360]) + }) + + }) + + describe("min", function () { + it("Returns the minimum values in a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.min().values, [0, 180]); + }); + it("Returns the minimum values of a DataFrame along axis 0 (row)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.min({ "axis": 0 }).values, [0, 2, 4]); + }); + it("Returns the minimum values of a DataFrame along axis 0 (row)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.min({ "axis": 0 }).values, [0, 2, 4]); + }); + it("Returns the minimum values in a DataFrame-Default axis 1", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.min().values, [0, 180]); + }); + + }); + + describe("max", function () { + it("Returns the maximum values in a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.max().values, [4, 360]); + }); + it("Returns the maximum values of a DataFrame along axis 0 (row)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.max({ "axis": 0 }).values, [360, 180, 360]); + }); + + }); + + describe("std", function () { + it("Returns the standard deviations of values in a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.std().values, [2, 103.92304845413264]); + }); + it("Return the standard deviations of values of a DataFrame along axis 0 (row)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.std({ axis: 0 }).values, [254.55844122715712, 125.86500705120545, 251.7300141024109]); + }); + + + }); + + describe("var", function () { + it("Returns the variance of values in a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.var().values, [4, 10800]); + }); + it("Return the variance of values of a DataFrame along axis 0 (row)", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.var({ axis: 0 }).values, [64800, 15842, 63368]); + }); + + + }); + + describe("describe", function () { + it("Returns descriptive statistics of columns in a DataFrame created from an array", function () { + const data = [[0, 2, 4, "a"], + [360, 180, 360, "b"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data); + const res = [[3, 3, 3], [120.66666666666667, 62, 123.33333333333333], + [207.27115895206774, 102.19589032832974, 204.961785055979], + [0, 2, 4], [2, 4, 6], + [360, 180, 360], + [42961.33333333333, 10444, 42009.333333333336]]; + assert.deepEqual(df.describe().values, res); + }); + it("Returns descriptive statistics of columns in a DataFrame created from an Object", function () { + const data = { + "col1": [0, 2, 4], + "col2": [360, 180, 360], + "col3": [2, 4, 6], + "col4": ["boy", "girl", "man"], + "col5": ["apple", "car", "bee"] + }; + const df = new DataFrame(data); + + const res = [[3, 3, 3], [2, 300, 4], + [2, 103.92304845413264, 2], + [0, 180, 2], [2, 360, 4], + [4, 360, 6], + [4, 10800, 4]]; + assert.deepEqual(df.describe().values, res); + }); + + }); + + describe("count", function () { + it("Returns the count of non-nan values in a DataFrame (Default axis is [1:column])", function () { + const data = [[0, 2, 4], + [360, 180.1, 360.11], + [NaN, 2, 4], + [360, undefined, 360]]; + const df = new DataFrame(data); + assert.deepEqual(df.count().values, [3, 3, 2, 2]); + }); + it("Return the count of non NaN values of a DataFrame along axis 0", function () { + const data = [[0, 2, 4, NaN], + [360, undefined, 360, 70]]; + const df = new DataFrame(data); + assert.deepEqual(df.count({ axis: 0 }).values, [2, 1, 2, 1]); + }); + + }); + + describe("round", function () { + it("Rounds values in a DataFrame to 3dp", function () { + const data = [[10.1, 2.092, 4.23], [360.232244, 180.0190290, 36.902612]]; + const df = new DataFrame(data); + const expected = [[10.1, 2.092, 4.23], [360.232, 180.0190, 36.903]]; + assert.deepEqual((df.round(3) as DataFrame).values as number[][], expected); + }); + it("Rounds values in a DataFrame to 1dp, inplace", function () { + const data = [[10.1, 2.092, 4.23], [360.232244, 180.0190290, 36.902612]]; + const df = new DataFrame(data); + const expected = [[10.1, 2.1, 4.2], [360.2, 180.0, 36.9]]; + df.round(1, { inplace: true }) as DataFrame + assert.deepEqual(df.values as number[][], expected); + }); + it("Rounds values in a DataFrame to 3dp with missing values", function () { + const data = [[10.1, 2.092, null], [360.232244, null, 36.902612]]; + const df = new DataFrame(data); + const expected = [[10.1, 2.092, null], [360.232, null, 36.903]]; + assert.deepEqual((df.round(3) as DataFrame).values as number[][], expected); + }); + + }); + + describe("sortValues", function () { + it("Sort values in DataFrame by specified column in ascending order (Default)", function () { + const data = [[0, 2, 4, "a"], + [360, 180, 360, "b"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["a", 1, "c"] }); + df.sortValues("col1", { inplace: true }); + const expected = [[0, 2, 4, "a"], [2, 4, 6, "c"], [360, 180, 360, "b"]]; + assert.deepEqual(df.values, expected); + assert.deepEqual(df.index, ["a", "c", 1]); + + }); + + it("Sort values in DataFrame by specified column in ascending order (Default)", function () { + const data = [[0, 2, 4, "a"], + [360, 180, 1, "b"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); + const df_sort = df.sortValues("col3") + const expected = [[360, 180, 1, "b"], [0, 2, 4, "a"], [2, 4, 6, "c"]]; + assert.deepEqual(df_sort.values, expected); + assert.deepEqual(df_sort.index, [1, 0, 2]); + + }); + it("Sort values in DataFrame by specified column in descending order", function () { + const data = [[0, 2, 4, "a"], + [360, 180, 360, "b"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); + const expected = [[360, 180, 360, "b"], [2, 4, 6, "c"], [0, 2, 4, "a"]]; + assert.deepEqual((df.sortValues("col1", { "ascending": false }) as DataFrame).values, expected); + }); + + it("Sort values in DataFrame by specified column in descending order (second col)", function () { + const data = [[0, 2, 4, "a"], + [360, 180, 1, "b"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); + const expected = [[2, 4, 6, "c"], [0, 2, 4, "a"], [360, 180, 1, "b"]]; + assert.deepEqual((df.sortValues("col3", { "ascending": false }) as DataFrame).values, expected); + }); + it("Sort values in DataFrame by specified column containing alpha(numeric) values", function () { + const data = [[0, 2, 4, "a"], + [360, 180, 1, "b"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); + const expected = [[2, 4, 6, "c"], [360, 180, 1, "b"], [0, 2, 4, "a"]] + assert.deepEqual(df.sortValues("col4", { "ascending": false }).values, expected); + }); + + it("sort works for Date string", function () { + const data = { + date: ['1974-02-19', '1955-12-06', '1963-11-18'] + }; + const df = new DataFrame(data); + const expected1 = [['1974-02-19'], ['1963-11-18'], ['1955-12-06']] + const expected2 = [['1955-12-06'], ['1963-11-18'], ['1974-02-19']] + assert.deepEqual(df.sortValues("date", { "ascending": false }).values, expected1); + assert.deepEqual(df.sortValues("date", { "ascending": true }).values, expected2); + }); + + it("Sort duplicate DataFrame with duplicate columns", function () { + + const data = { + "A": [1, 2, 3, 4, 5, 3, 5, 6, 4, 5, 3, 4], + "B": [2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] + }; + + const df = new DataFrame(data); + const expected = [[1, 2], + [2, 3], + [3, 4], + [3, 7], + [3, 3], + [4, 5], + [4, 1], + [4, 4], + [5, 6], + [5, 8], + [5, 2], + [6, 9]]; + assert.deepEqual(df.sortValues("A", { "ascending": true }).values, expected); + }); + it("sort index in descending order and retains index", function () { + let data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + let df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); + let df2 = df.sortIndex({ ascending: false }); + let rslt = ["c", "b", "a"]; + assert.deepEqual(df2.index, rslt); + }); + + }); + + describe("copy", function () { + it("Makes a deep copy of DataFrame", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + const df_copy = df.copy(); + assert.deepEqual(df_copy.values, [[0, 2, 4], [360, 180, 360]]); + }); + it("Confirms child copy modification does not affect parent DataFrame", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + const df_copy = df.copy(); + df_copy.addColumn("col_new", ["boy", "girl"], { inplace: true }); + assert.notDeepEqual(df_copy.values, df.values); + assert.notDeepEqual(df_copy, df); + }); + + }); + + + describe("setIndex", function () { + it("Sets the index of a DataFrame created from an Object inplace", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const df = new DataFrame(data); + df.setIndex({ index: ["one", "two", "three"], inplace: true }) + assert.deepEqual(df.index, ["one", "two", "three"]); + }); + it("Sets the index of a DataFrame from column name", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const df = new DataFrame(data); + const df_new = df.setIndex({ column: "alpha" }) as DataFrame + assert.deepEqual(df_new.index, ["A", "B", "C"]); + }); + it("Sets the index of a DataFrame from column name", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const df = new DataFrame(data); + const df_new = df.setIndex({ column: "alpha" }) as DataFrame + assert.deepEqual(df_new.index, ["A", "B", "C"]); + }); + it("Sets the index of a DataFrame from column name and drop column data (inplace)", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const df = new DataFrame(data); + df.setIndex({ column: "alpha", drop: true, inplace: true }); + assert.deepEqual(df.index, ["A", "B", "C"]); + assert.deepEqual(df.columns, ["val_count"]); + assert.deepEqual(df.values, [[1], [2], [3]]); + assert.throws(() => df["alpha"], Error, + "ParamError: Column not found!. Column name must be one of val_count" + ); + }); + it("Throw error if index and column not passed", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const df = new DataFrame(data); + assert.throws(() => df.setIndex({ drop: true, inplace: true }), Error, + "ParamError: must specify either index or column" + ); + }); + + it("Sets the index of a DataFrame from column name and drop column data", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const df = new DataFrame(data); + const df_new = df.setIndex({ column: "alpha", drop: true }) as DataFrame + assert.deepEqual(df_new.index, ["A", "B", "C"]); + assert.deepEqual(df_new.columns, ["val_count"]); + assert.deepEqual(df_new.values, [[1], [2], [3]]); + assert.deepEqual(df_new["alpha"], undefined); + }); + it("Sets the index of a DataFrame created from an Array inplace", function () { + const data = [[0, 2, 4], [360, 180, 360], [0, 2, 4], [360, 180, 360], [0, 2, 4]]; + const df = new DataFrame(data); + df.setIndex({ index: ["one", "two", "three", "four", "five"], "inplace": true }); + assert.deepEqual(df.index, ["one", "two", "three", "four", "five"]); + }); + it("Throws error on wrong row length", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.throws(() => df.setIndex({ index: ["one", "two", "three", "four", "five"], "inplace": true }), Error, + "ParamError: index must be the same length as the number of rows" + ); + }) + it("Throws error on column not found", function () { + const data = [[0, 2, 4], [360, 180, 360]]; + const df = new DataFrame(data); + assert.throws(() => df.setIndex({ column: "alpha", inplace: true }), Error, + "ParamError: column not found in column names" + ); + }) + + }); + + describe("resetIndex", function () { + it("Resets the index of a DataFrame created from an Object", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const df = new DataFrame(data, { index: ["one", "two", "three"] }); + const df_reset = df.resetIndex() as DataFrame + assert.deepEqual(df_reset.index, [0, 1, 2]); + }); + it("Resets the index of a DataFrame created from an Array inplace", function () { + const data = [[0, 2, 4], [360, 180, 360], [0, 2, 4], [360, 180, 360], [0, 2, 4]]; + const df = new DataFrame(data, { index: ["one", "two", "three", "four", "five"] }); + df.resetIndex({ inplace: true }); + assert.deepEqual(df.index, [0, 1, 2, 3, 4]); + }); + }); + + + describe("apply", function () { + + it("Apply an aggregation function to a DataFrame axis = 1", function () { + const data = [[0, 2, 4], + [3, 2, 2], + [0, 2, 1]] + const df = new DataFrame(data) + + const sum = (x: any) => { + return x.reduce((a: any, b: any) => a + b, 0) + } + const expected = [6, 7, 3] + const dfApply = df.apply(sum, { axis: 1 }) + assert.deepEqual(dfApply.values, expected) + assert.deepEqual(dfApply.index, [0, 1, 2]) + + }); + it("Apply an aggregation function to a DataFrame axis = 0", function () { + const data = [[0, 2, 4], + [3, 2, 2], + [0, 2, 1]] + const df = new DataFrame(data, { columns: ["col1", "col2", "col3"] }) + + const sum = (x: any) => { + return x.reduce((a: any, b: any) => a + b, 0) + } + const expected = [3, 6, 7] + const dfApply = df.apply(sum, { axis: 0 }) + assert.deepEqual(dfApply.values, expected) + assert.deepEqual(dfApply.index, ["col1", "col2", "col3"]) + }); + + }); + + describe("applyMap", function () { + it("Apply an element-wise function to a DataFrame", function () { + const data = [[0, 2, 4], + [360, 180, 360], + [0, 2, 4]] + const df = new DataFrame(data) + + const add = (x: any) => { + return x + 1000 + } + const expected = [[1000, 1002, 1004], [1360, 1180, 1360], [1000, 1002, 1004]] + const dfApply = df.applyMap(add) as DataFrame + assert.deepEqual(dfApply.values, expected) + }); + + it("Apply an element-wise function to a DataFrame", function () { + const data = [[0, 2, 4], + [360, 180, 360], + [0, 2, 4], + [0, 2, 4]] + const df = new DataFrame(data) + + const add = (x: any) => { + return x + 1000 + } + const expected = [[1000, 1002, 1004], [1360, 1180, 1360], [1000, 1002, 1004], [1000, 1002, 1004]] + const dfApply = df.applyMap(add) as DataFrame + assert.deepEqual(dfApply.values, expected) + }); + + it("Apply an element-wise function to a DataFrame inplace", function () { + const data = [[0, 2, 4], + [360, 180, 360], + [0, 2, 4]] + const df = new DataFrame(data) + + const add = (x: any) => { + return x + 1000 + } + const expected = [[1000, 1002, 1004], [1360, 1180, 1360], [1000, 1002, 1004]] + df.applyMap(add, { inplace: true }) + assert.deepEqual(df.values, expected) + }); + + it("Apply an element-wise function to a DataFrame inplace", function () { + const data = [[0, 2, 4], + [360, 180, 360], + [0, 2, 4], + [0, 2, 4]] + const df = new DataFrame(data) + + const add = (x: any) => { + return x + 1000 + } + const expected = [[1000, 1002, 1004], [1360, 1180, 1360], [1000, 1002, 1004], [1000, 1002, 1004]] + df.applyMap(add, { inplace: true }) + assert.deepEqual(df.values, expected) + }); + }); + + describe("column", function () { + it("Obtain a column from a dataframe created from object", function () { + const data = [{ alpha: "A", val_count: 1 }, { alpha: "B", val_count: 2 }, { alpha: "C", val_count: 3 }]; + const options = { columns: ["Gender", "count"] }; + const df = new DataFrame(data, options); + const expected = df.column("count"); + const rslt_data = [1, 2, 3]; + assert.deepEqual(expected.values, rslt_data); + }); + it("Obtain a column from a dataframe", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const expected = df.column("C"); + const rslt_data = [3, 6, 40, 78]; + assert.deepEqual(expected.values, rslt_data); + }); + it("Throw Error for wrong column", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + assert.throws(() => { df.column("D"); }, Error, "ParamError: Column not found!. Column name must be one of A,B,C"); + + }); + }); + + + describe("dropNa", function () { + it("drop NaNs along axis 0", function () { + const data = [[0, 2, 4], + [360, 180, 360], + [NaN, 180, 360]] + const column = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: column }); + const df_val = [[2, 4], + [180, 360], + [180, 360]] + assert.deepEqual((df.dropNa({ axis: 0 }) as DataFrame).values, df_val); + + }); + it("drop NaNs along axis 1", function () { + const data = [[0, 2, 4], + [360, 180, 360], + [NaN, 180, 360]] + const column = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: column }); + const df_val = [[0, 2, 4], + [360, 180, 360]] + assert.deepEqual((df.dropNa({ axis: 1 }) as DataFrame).values, df_val); + + }); + it("drop NaNs along axis 1", function () { + const data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const df_val = [[5, 6, 7, 8]]; + assert.deepEqual((df.dropNa({ axis: 1 }) as DataFrame).values, df_val); + + }); + it("drop inplace at axis 0, inplace false ", function () { + const data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + + const df_val = [[1, 3], [4, 9], [6, 8]]; + + assert.deepEqual((df.dropNa({ axis: 0 }) as DataFrame).values, df_val); + + }); + it("drop inplace at axis 0, inplace true ", function () { + const data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + + const df_val = [[1, 3], [4, 9], [6, 8]]; + df.dropNa({ axis: 0, inplace: true }); + assert.deepEqual(df.values, df_val); + + }); + it("drop inplace at axis 1 at inplace true", function () { + const data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + + const df_val = [[5, 6, 7, 8]]; + + df.dropNa({ axis: 1, inplace: true }); + assert.deepEqual(df.values, df_val); + + }); + it("drop works for undefined values", function () { + let data = [[null, 1, 2, 3], [3, 4, undefined, 9], [5, 6, 7, 8]]; + let column = ["A", "B", "C", "D"]; + let df = new DataFrame(data, { columns: column }); + + let df_val = [[5, 6, 7, 8]]; + + df.dropNa({ axis: 1, inplace: true }); + assert.deepEqual(df.values, df_val); + + }); + }); + + describe("isNa", function () { + + it("check if values are empty (element-wise", function () { + const data = [[NaN, 1, 2, 3], [3, 4, undefined, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + + const df_val = [ + [true, false, false, false], + [false, false, true, false], + [false, false, false, false] + ]; + const dfNew = df.isNa() + assert.deepEqual(dfNew.values, df_val); + assert.deepEqual(dfNew.dtypes, ["boolean", "boolean", "boolean", "boolean"]); + assert.deepEqual(dfNew.columns, column); + }); + }); + + describe("fillNa", function () { + + it("replace all NaN value inplace", function () { + const data = [[NaN, 1, 2, 3], [3, 4, NaN, 9], [5, 6, 7, 8]]; + const columns = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: columns }); + + const expected = [[-999, 1, 2, 3], [3, 4, -999, 9], [5, 6, 7, 8]]; + df.fillNa(-999, { inplace: true }); + assert.deepEqual(df.values, expected); + }); + it("replace all undefined value", function () { + const data = [[undefined, 1, 2, 3], [3, 4, null, 9], [5, 6, 7, 8]]; + const columns = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: columns }); + + const expected = [[-999, 1, 2, 3], [3, 4, -999, 9], [5, 6, 7, 8]]; + + const df_filled = df.fillNa(-999) as DataFrame + assert.deepEqual(df_filled.values, expected); + }); + it("replace all undefined value with 0 works", function () { + const data = [[undefined, 1, 2, 3], [3, 4, null, 9], [5, NaN, 7, 8]]; + const columns = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: columns }); + + const expected = [[0, 1, 2, 3], [3, 4, 0, 9], [5, 0, 7, 8]]; + + const df_filled = df.fillNa(0) as DataFrame + assert.deepEqual(df_filled.values, expected); + }); + + + it("Fills only a specified column", function () { + const data = [[1, 2, 3], + [4, 5, 6], + [20, NaN, 40], + [39, NaN, NaN]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const expected = [[1, 2, 3], [4, 5, 6], [20, 2, 40], [39, 2, NaN]]; + const df_filled = df.fillNa([2], { columns: ["B"] }) as DataFrame; + + assert.deepEqual(df_filled.values, expected); + }); + it("Fills column with specified values not in place", function () { + const data = [[1, 2, 3], [4, 5, 6], [NaN, 20, 40], [NaN, -1, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const new_vals = [[1, 2, 3], [4, 5, 6], [-2, 20, 40], [-2, -1, 78]]; + const df_filled = df.fillNa([-2], { columns: ["A"] }) as DataFrame + + assert.deepEqual(df_filled.values, new_vals); + }); + + it("Fills a list of columns with specified values", function () { + const data = [[1, undefined, 3], [4, undefined, 6], [NaN, "boy", 40], [NaN, "girl", NaN]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const new_vals = [[1, "girl", 3], [4, "girl", 6], [200, "boy", 40], [200, "girl", NaN]]; + const df_filled = df.fillNa([200, "girl"], { columns: ["A", "B"] }) as DataFrame + assert.deepEqual(df_filled.values, new_vals); + }); + it("Fills a list of columns with specified values inplace", function () { + const data = [[1, undefined, 3], [4, undefined, 6], [NaN, "boy", 40], [NaN, "girl", 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const new_vals = [[1, "girl", 3], [4, "girl", 6], [200, "boy", 40], [200, "girl", 78]]; + df.fillNa([200, "girl"], { columns: ["A", "B"], inplace: true }); + assert.deepEqual(df.values, new_vals); + }); + }); + + describe("selectDtypes", function () { + + it("Returns float columns in a DataFrame", function () { + const data = [[30, 1, 2, "boy"], [3.2, 4, 30, "girl"], [5.09, 6, 7, "cat"]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes(['float32']); + assert.deepEqual(df_sub.values, [[30], [3.2], [5.09]]); + }); + + it("Returns int columns in a DataFrame", function () { + const data = [[30, 1, 2, "boy"], + [3.2, 4, 30, "girl"], + [5.09, 6, 7, "cat"]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes(['int32']); + assert.deepEqual(df_sub.values, [[1, 2], [4, 30], [6, 7]]); + }); + + it("Returns string columns in a DataFrame", function () { + const data = [[30, 1, 2, "boy"], + [3.2, 4, 30, "girl"], + [5.09, 6, 7, "cat"]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes(['string']); + assert.deepEqual(df_sub.values, [["boy"], ["girl"], ["cat"]]); + }); + + it("Returns string and float columns in a DataFrame", function () { + const data = [[30, 1, 2, "boy"], + [3.2, 4, 30, "girl"], + [5.09, 6, 7, "cat"]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes(['string', 'float32']); + assert.deepEqual(df_sub.values, [[30, "boy"], [3.2, "girl"], [5.09, "cat"]]); + }); + + it("Returns int and float columns in a DataFrame", function () { + const data = [[30, 1, 2, "boy"], + [3.2, 4, 30, "girl"], + [5.09, 6, 7, "cat"]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const df_sub = df.selectDtypes(['int32', 'float32']); + assert.deepEqual(df_sub.values, [[30, 1, 2], [3.2, 4, 30], [5.09, 6, 7]]); + }); + }); + + + describe("lt", function () { + it("Returns Less than of DataFrame and other DataFrame (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; + + const df = new DataFrame(data1); + const df2 = new DataFrame(data2); + const expected = [[true, true, true, false], + [false, false, false, false]]; + assert.deepEqual(df.lt(df2).values, expected); + }); + + it("Return Less than of series and scalar (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const sf = new DataFrame(data1); + const expected = [[true, false, false, true], + [true, true, true, true]]; + assert.deepEqual(sf.lt(30).values, expected); + }); + it("Return Less than of series and DataFrame along axis 1", function () { + const data1 = [[10, 45, 56, 10], + [23, 20, 10, 10]]; + const sf = new Series([10, 23, 56, 100]); + const df = new DataFrame(data1); + const expected = [[false, false, false, true], [false, true, true, true]]; + assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); + }); + + it("Return Less than of Array and DataFrame along axis 1", function () { + const data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; + const sf = [10, 23, 56, 100]; + const df = new DataFrame(data1); + const expected = [[false, false, false, true], [false, true, true, true]]; + assert.deepEqual(df.lt(sf, { axis: 1 }).values, expected); + }); + it("Return Less than of series and DataFrame along axis 0", function () { + const data1 = [[10, 45, 56, 10], + [23, 20, 10, 10]]; + const sf = new Series([10, 23]); + const df = new DataFrame(data1); + const expected = [[false, false, false, false], [false, true, true, true]]; + const result = df.lt(sf, { axis: 0 }) + assert.deepEqual(result.values, expected); + }); + + it("Return Less than of Array and DataFrame along axis 0", function () { + const data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; + const sf = [10, 23]; + const df = new DataFrame(data1); + const expected = [[false, false, false, false], [false, true, true, true]]; + const result = df.lt(sf, { axis: 0 }) + assert.deepEqual(result.values, expected); + }); + + }); + + describe("gt", function () { + it("Return Greater than of series and other series (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; + + const df = new DataFrame(data1); + const df2 = new DataFrame(data2); + const expected = [[false, false, false, true], [false, true, true, false]]; + assert.deepEqual(df.gt(df2).values, expected); + }); + + it("Return Greater than of series scalar (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const sf = new DataFrame(data1); + const expected = [[false, true, true, false], [false, false, false, false]]; + assert.deepEqual(sf.gt(30).values, expected); + }); + + it("Return Less than of Array and DataFrame scalar along axis 1", function () { + const data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; + const sf = [10, 23, 56, 100]; + const df = new DataFrame(data1); + const expected = [[false, true, false, false], [true, false, false, false]]; + assert.deepEqual(df.gt(sf, { axis: 1 }).values, expected); + }); + it("Return Less than of Array and DataFrame scalar along axis 0", function () { + const data1 = [[10, 45, 56, 10], [23, 20, 10, 10]]; + const sf = [10, 23]; + const df = new DataFrame(data1); + const expected = [[false, true, true, false], [false, false, false, false]]; + assert.deepEqual(df.gt(sf, { axis: 0 }).values, expected); + }); + + }); + + describe("le", function () { + it("Return Less than or Equal to of series and other series (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; + + const df = new DataFrame(data1); + const df2 = new DataFrame(data2); + const expected = [[true, true, true, false], [true, false, false, true]]; + assert.deepEqual(df.le(df2).values, expected); + }); + + it("Return Less than or Equal to of series scalar (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; + const sf = new DataFrame(data1); + const expected = [[true, false, false, true], [true, true, true, true]]; + assert.deepEqual(sf.le(30).values, expected); + }); + + }); + + describe("ge", function () { + it("Return Greater than or Equal to of series and other series (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; + + const df = new DataFrame(data1); + const df2 = new DataFrame(data2); + const expected = [[false, false, false, true], [true, true, true, true]]; + assert.deepEqual(df.ge(df2).values, expected); + }); + + it("Return Greater than or Equal to of series scalar (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; + const sf = new DataFrame(data1); + const expected = [[false, true, true, false], [false, false, true, false]]; + assert.deepEqual(sf.ge(30).values, expected); + }); + + }); + + describe("ne", function () { + it("Return Not Equal to of series and other series (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; + + const df = new DataFrame(data1); + const df2 = new DataFrame(data2); + const expected = [[true, true, true, true], [false, true, true, false]]; + assert.deepEqual(df.ne(df2).values, expected); + }); + + it("Return Not Equal to of series scalar (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; + const sf = new DataFrame(data1); + const expected = [[true, true, true, true], [true, true, false, true]]; + assert.deepEqual(sf.ne(30).values, expected); + }); + it("Return Less than of Array and DataFrame along axis 1 (column)", function () { + const data = { + 'cost': [250, 150, 100], + 'revenue': [100, 250, 300] + } + const sf = [100, 300] + const df = new DataFrame(data, { index: ['A', 'B', 'C'] }) + const expected = [[true, true], [true, true], [false, false]]; + const result = df.ne(sf, { axis: 1 }) + assert.deepEqual(result.values, expected); + }); + + }); + + describe("eq", function () { + it("Return Equal to of DataFrame and other DataFrame (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 20, 10]]; + const data2 = [[100, 450, 590, 5], [25, 2, 0, 10]]; + + const df = new DataFrame(data1); + const df2 = new DataFrame(data2); + const expected = [[false, false, false, false], [true, false, false, true]]; + assert.deepEqual(df.eq(df2).values, expected); + }); + + it("Return Equal to of DataFrame with scalar (element-wise)", function () { + const data1 = [[10, 45, 56, 10], [25, 23, 30, 10]]; + const sf = new DataFrame(data1); + const expected = [[false, false, false, false], [false, false, true, false]]; + assert.deepEqual(sf.eq(30).values, expected); + }); + it("Return Equal to of series and DataFrame scalar along axis 1", function () { + const data1 = { "Col1": [10, 45, 56, 10], "Col2": [23, 20, 10, 10] }; + const sf = new Series([10, 23]); + const df = new DataFrame(data1); + const expected = [[true, true], [false, false], [false, false], [true, false]]; + assert.deepEqual(df.eq(sf, { axis: 1 }).values, expected); + }); + it("Return Less than of Array and DataFrame along axis 0", function () { + const data = { + 'cost': [250, 150, 100], + 'revenue': [100, 250, 300] + } + const sf = [250, 250, 100] + const df = new DataFrame(data, { index: ['A', 'B', 'C'] }) + const expected = [[true, false], [false, true], [true, false]]; + const result = df.eq(sf, { axis: 0 }) + assert.deepEqual(result.values, expected); + }); + + }); + + describe("replace", function () { + it("Replace across all columns", function () { + const data1 = [[10, 45, 56, 25], [23, 20, 10, 24]]; + const df = new DataFrame(data1); + const expected = [[-999, 45, 56, 25], [23, 20, -999, 24]]; + const df_rep = df.replace(10, -999) as DataFrame + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace accross all columns inplace", function () { + const data1 = [["A", "A", "A", "B"], ["B", "C", "C", "D"]]; + const df = new DataFrame(data1); + const expected = [["boy", "boy", "boy", "B"], ["B", "C", "C", "D"]]; + df.replace("A", "boy", { inplace: true }); + assert.deepEqual(df.values, expected); + }); + it("Replace values in specified two column(s)", function () { + const data1 = [["A", "A", 1, "girl"], + ["B", "A", 2, "woman"], + ["A", "B", 3, "man"]]; + const df = new DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); + const expected = [["boy", "boy", 1, "girl"], + ["B", "boy", 2, "woman"], + ["boy", "B", 3, "man"]]; + const df_rep = df.replace("A", "boy", { columns: ["col1", "col2"] }) as DataFrame + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace values in specified single column(s)", function () { + const data1 = [[2, "A", 1, "girl"], + [3, "A", 2, "woman"], + [4, "B", 3, "man"]]; + const df = new DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); + const expected = [[2, "A", 1, "girl"], + [100, "A", 2, "woman"], + [4, "B", 3, "man"]]; + const df_rep = df.replace(3, 100, { columns: ["col1"] }) as DataFrame + assert.deepEqual(df_rep.values, expected); + assert.notDeepEqual(df_rep, df); + assert.notDeepEqual(df_rep.values, df.values); + }); + + it("Replace values in specified two column(s) inplace", function () { + const data1 = [["A", "A", 1, "girl"], + ["B", "A", 2, "woman"], + ["A", "B", 3, "man"]]; + const df = new DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); + const expected = [["boy", "boy", 1, "girl"], + ["B", "boy", 2, "woman"], + ["boy", "B", 3, "man"]]; + df.replace("A", "boy", { columns: ["col1", "col2"], inplace: true }); + assert.deepEqual(df.values, expected); + }); + + it("Replace values in specified single column(s) inplace", function () { + const data1 = [[2, "A", 1, "girl"], + [3, "A", 2, "woman"], + [4, "B", 3, "man"]]; + const df = new DataFrame(data1, { columns: ["col1", "col2", "col3", "col4"] }); + const expected = [[2, "A", 1, "girl"], + [100, "A", 2, "woman"], + [4, "B", 3, "man"]]; + df.replace(3, 100, { columns: ["col1"], inplace: true }); + assert.deepEqual(df.values, expected); + }); + + it("Replace oldValue supports falsy numbers (0)", function () { + const data1 = [[0, 19, 84, 0], [65, 0, 0, 37]]; + const df = new DataFrame(data1); + const expected = [[1, 19, 84, 1], [65, 1, 1, 37]]; + const df_rep = df.replace(0, 1) as DataFrame; + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace oldValue does not support NaN", function () { + const data1 = [[NaN, 19, 84, NaN], [65, NaN, NaN, 37]]; + const df = new DataFrame(data1); + assert.throws(() => df.replace(NaN, 1), Error, "Params Error: Param 'oldValue' does not support NaN. Use DataFrame.fillNa() instead."); + }); + + it("Replace oldValue supports falsy strings", function () { + const data1 = [['', 'hello', 'world', ''], ['foo', '', '', 'bar']]; + const df = new DataFrame(data1); + const expected = [['danfo', 'hello', 'world', 'danfo'], ['foo', 'danfo', 'danfo', 'bar']]; + const df_rep = df.replace('', 'danfo') as DataFrame; + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace oldValue supports falsy booleans", function () { + const data1 = [[false, 'hello', 'world', false], ['foo', false, false, 'bar']]; + const df = new DataFrame(data1); + const expected = [[true, 'hello', 'world', true], ['foo', true, true, 'bar']]; + const df_rep = df.replace(false, true) as DataFrame; + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace newValue supports falsy numbers (0)", function () { + const data1 = [[1, 19, 84, 1], [65, 1, 1, 37]]; + const df = new DataFrame(data1); + const expected = [[0, 19, 84, 0], [65, 0, 0, 37]]; + const df_rep = df.replace(1, 0) as DataFrame; + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace newValue supports falsy numbers (NaN)", function () { + const data1 = [[1, 19, 84, 1], [65, 1, 1, 37]]; + const df = new DataFrame(data1); + const expected = [[NaN, 19, 84, NaN], [65, NaN, NaN, 37]]; + const df_rep = df.replace(1, NaN) as DataFrame; + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace newValue supports falsy strings", function () { + const data1 = [['danfo', 'hello', 'world', 'danfo'], ['foo', 'danfo', 'danfo', 'bar']]; + const df = new DataFrame(data1); + const expected = [['', 'hello', 'world', ''], ['foo', '', '', 'bar']]; + const df_rep = df.replace('danfo', '') as DataFrame; + assert.deepEqual(df_rep.values, expected); + }); + + it("Replace newValue supports falsy booleans", function () { + const data1 = [[true, 'hello', 'world', true], ['foo', true, true, 'bar']]; + const df = new DataFrame(data1); + const expected = [[false, 'hello', 'world', false], ['foo', false, false, 'bar']]; + const df_rep = df.replace(true, false) as DataFrame; + assert.deepEqual(df_rep.values, expected); + }); + + }); + + describe("sum", function () { + it("Sum values of a DataFrame by Default axis column (axis=1)", function () { + const data1 = [[30, 40, 3.1], + [5, 5, 5.1], + [5, 5, 3.2]]; + const sf = new DataFrame(data1); + const res = [73.1, 15.1, 13.2]; + assert.deepEqual(sf.sum().values, res); + }); + it("Sum values of a DataFrame along row axis (axis=0)", function () { + const data1 = [[30, 40, 3.1], + [5, 5, 5.1], + [5, 5, 3.2]]; + const df = new DataFrame(data1); + const res = [40, 50, 11.399999999999999]; + assert.deepEqual(df.sum({ axis: 0 }).values, res); + }); + it("Sum values of a mixed DataFrame along row axis (axis=0)", function () { + const data1 = [[30, 40, 3.1, true], + [5, 5, 5.1, true], + [5, 5, 3.2, true]]; + const df = new DataFrame(data1); + const res = [40, 50, 11.399999999999999, 3]; + assert.deepEqual(df.sum({ axis: 0 }).values, res); + }); + it("Sum values of a boolean DataFrame along row axis (axis=0)", function () { + const data1 = [[true, true, false, true], + [false, false, false, false], + [false, true, true, false]]; + const df = new DataFrame(data1); + const res = [1, 2, 1, 1]; + assert.deepEqual(df.sum({ axis: 0 }).values, res); + }); + it("Sum values of a boolean DataFrame along default column axis (axis=1)", function () { + const data1 = [[true, true, false, true], + [false, false, false, false], + [false, true, true, false]]; + const df = new DataFrame(data1); + const res = [3, 0, 2]; + assert.deepEqual(df.sum().values, res); + }); + it("Sum values of a df with missing values", function () { + const data1 = [[11, 20, 3], [null, 15, 6], [2, 30, 40], [2, 89, 78]]; + const df = new DataFrame(data1); + const res = [34, 21, 72, 169] + assert.deepEqual(df.sum({ axis: 1 }).values, res); + }); + + }); + + describe("abs", function () { + it("Returns the absolute values in DataFrame of ints", function () { + const data1 = [[-10, 45, 56, 10], [-25, 23, 20, -10]]; + const df = new DataFrame(data1); + const expected = [[10, 45, 56, 10], [25, 23, 20, 10]]; + assert.deepEqual((df.abs() as DataFrame).values, expected); + }); + + it("Returns the absolute values in mixed DataFrame", function () { + const data1 = [[-10, -45.1, 56, 10], [-25, -23.2, 20, -10]]; + const df = new DataFrame(data1); + const expected = [[10, 45.1, 56, 10], [25, 23.2, 20, 10]]; + assert.deepEqual((df.abs() as DataFrame).values, expected); + }); + }); + + describe("T", function () { + it("Return the Transpose of a DataFrame", function () { + const data1 = [[10, 45, 56, 10], + [25, 23, 20, 10]]; + + const cols = ["a", "b", "c", "d"]; + const df = new DataFrame(data1, { columns: cols }); + const df_trans = df.T; + const expected_vals = [[10, 25], [45, 23], [56, 20], [10, 10]]; + const expected_index = cols; + const expected_col_names = ["0", "1"]; + assert.deepEqual(df_trans.index, expected_index); + assert.deepEqual(df_trans.values, expected_vals); + assert.deepEqual(df_trans.columns, expected_col_names); + + }); + }); + + describe("transpose", function () { + it("Return the Transpose of a DataFrame", function () { + const data1 = [[10, 45, 56, 10], + [25, 23, 20, 10]]; + + const cols = ["a", "b", "c", "d"]; + const df = new DataFrame(data1, { columns: cols }); + const df_trans = df.T; + const expected_vals = [[10, 25], [45, 23], [56, 20], [10, 10]]; + const expected_index = cols; + const expected_col_names = ["0", "1"]; + assert.deepEqual(df_trans.index, expected_index); + assert.deepEqual(df_trans.values, expected_vals); + assert.deepEqual(df_trans.columns, expected_col_names); + + }); + it("Transpose a DataFrame inplace", function () { + const data1 = [[10, 45, 56, 10], + [25, 23, 20, 10]]; + + const cols = ["a", "b", "c", "d"]; + const df = new DataFrame(data1, { columns: cols }); + df.transpose({ inplace: true }); + const expected_vals = [[10, 25], [45, 23], [56, 20], [10, 10]]; + const expected_index = cols; + const expected_col_names = ["0", "1"]; + assert.deepEqual(df.index, expected_index); + assert.deepEqual(df.values, expected_vals); + assert.deepEqual(df.columns, expected_col_names); + + }); + }); + + + describe("asType", function () { + it("set type of float column to int", function () { + const data = { + "A": [-20.1, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20.1, -20.23, 30.3, 40.11], + "D": ["a", "b", "c", "c"] + }; + const df = new DataFrame(data); + const dfNew = df.asType("A", "int32") as DataFrame + dfNew["D"] = ["a", "b", "c", "F"]; + assert.deepEqual(dfNew.dtypes, ['int32', 'int32', 'float32', 'string']); + assert.deepEqual(dfNew['A'].values, [-20, 30, 47, -20]); + assert.notDeepEqual(dfNew["D"].values, df["D"].values); + + }); + it("set type of int column to float", function () { + const data = { + "A": [-20.1, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20.1, -20.23, 30.3, 40.11], + "D": ["a", "b", "c", "c"] + }; + const df = new DataFrame(data); + const dfNew = df.asType("B", "float32") as DataFrame + + assert.deepEqual(dfNew.dtypes, ['float32', 'float32', 'float32', 'string']); + assert.deepEqual(dfNew['B'].values, [34, -4, 5, 6]); + + }); + it("set type of string column to int", function () { + const data = { + "A": [-20.1, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20.1, -20.23, 30.3, 40.11], + "D": ["20.1", "21", "23.4", "50.78"] + }; + const df = new DataFrame(data); + const dfNew = df.asType("D", "int32") as DataFrame + + assert.deepEqual(dfNew.dtypes, ['float32', 'int32', 'float32', 'int32']); + assert.deepEqual(dfNew['D'].values, [20, 21, 23, 50]); + + }); + it("set type of string column to float", function () { + const data = { + "A": [-20.1, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20.1, -20.23, 30.3, 40.11], + "D": ["20.1", "21", "23.4", "50.78"] + }; + const df = new DataFrame(data); + const dfNew = df.asType("D", "float32") as DataFrame + + assert.deepEqual(dfNew.dtypes, ['float32', 'int32', 'float32', 'float32']); + assert.deepEqual(dfNew['D'].values, [20.1, 21, 23.4, 50.78]); + + }); + }); + + describe("nUnique", function () { + it("Returns the number of unique elements along axis 1", function () { + const data = { + "A": [-20, 30, 47.3, -20, 2], + "B": [34, -4, 5, 6, 2], + "C": [20, 20, 30, 30, 2], + "D": ["a", "b", "c", "c", "d"] + }; + + const df = new DataFrame(data); + const res = [4, 4, 4, 4, 2]; + assert.deepEqual(df.nUnique(1).values, res); + + }); + it("Returns the number of unique elements along axis 0", function () { + const data = { + "A": [20, 30, 47.3, 30], + "B": [34, -4, 5, 30], + "C": [20, 20, 30, 30], + "D": ["a", "b", "c", "c"] + }; + + const df = new DataFrame(data); + const res = [3, 4, 2, 3]; + assert.deepEqual(df.nUnique(0).values, res); + + }); + + }); + + + describe("rename", function () { + it("Rename columns along axis 1", function () { + const data = { + "A": [-20, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20, 20, 30, 30], + }; + + const df = new DataFrame(data); + const dfNew = df.rename({ "A": "a1", "B": "b1" }) as DataFrame + const res = ["a1", "b1", "C",]; + assert.deepEqual(dfNew.columns, res); + + }); + it("confirms original column name is not modified along axis 1", function () { + const data = { + "A": [-20, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "D": ["a", "b", "c", "c"] + }; + + const df = new DataFrame(data); + const dfNew = df.rename({ "A": "a1", "B": "b1" }, { axis: 1 }) + const res = ["A", "B", "D"]; + assert.deepEqual(df.columns, res); + + }); + it("Rename columns along axis 1 inplace", function () { + const data = { + "A": [-20, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20, 20, 30, 30], + }; + + const df = new DataFrame(data); + df.rename({ "A": "a1", "B": "b1" }, { inplace: true }); + const res = ["a1", "b1", "C"]; + assert.deepEqual(df.columns, res); + + }); + it("Rename string index along axis 0", function () { + const data = { + "A": [-20, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20, 20, 30, 30], + }; + + const df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); + const dfNew = df.rename({ "a": 0, "b": 1 }, { axis: 0 }) as DataFrame + const res = [0, 1, "c", "d"]; + assert.deepEqual(dfNew.index, res); + + }); + it("Rename string index along axis 0 inplace", function () { + const data = { + "A": [-20, 30, 47.3, -20], + "B": [34, -4, 5, 6], + "C": [20, 20, 30, 30], + }; + + const df = new DataFrame(data, { index: ["a", "b", "c", "d"] }); + df.rename({ "a": 0, "b": 1 }, { axis: 0, inplace: true }); + const res = [0, 1, "c", "d"]; + assert.deepEqual(df.index, res); + + }); + it("Get new column via subseting works after rename (inplace)", function () { + let data = { + "A": [-20, 30, 47.3], + "B": [34, -4, 5], + "C": [20, 2, 30] + }; + let df = new DataFrame(data); + df.rename({ "A": "new_name" }, { inplace: true }); + df["new_name"].print(); + assert.deepEqual(df["new_name"].values, data["A"]); + }); + + it("Get new column via subseting works after rename (not-inplace)", function () { + let data = { + "A": [-20, 30, 47.3], + "B": [34, -4, 5], + "C": [20, 2, 30] + }; + let df = new DataFrame(data); + let new_df = df.rename({ "A": "new_name" }); + assert.deepEqual(new_df["new_name"].values, data["A"]); + }); + }); + + describe("sortIndex", function () { + + it("sort index in ascending order", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); + const df2 = df.sortIndex() as DataFrame + const rslt = [[360, 180, 360, 'a'], [0, 2, 4, 'b'], [2, 4, 6, 'c']]; + + assert.deepEqual(df2.values, rslt); + }); + it("sort index in ascending order - inplace", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); + df.sortIndex({ inplace: true }); + const rslt = [[360, 180, 360, 'a'], [0, 2, 4, 'b'], [2, 4, 6, 'c']]; + assert.deepEqual(df.values, rslt); + }); + it("sort index in descending order", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: ["b", "a", "c"] }); + const df2 = df.sortIndex({ ascending: false }) as DataFrame + const rslt = [[2, 4, 6, 'c'], [0, 2, 4, 'b'], [360, 180, 360, 'a']]; + + assert.deepEqual(df2.values, rslt); + }); + it("sort index in descending order with inplace set to true", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"], index: [4, 2, 5] }); + df.sortIndex({ ascending: false, inplace: true }); + const rslt = [[2, 4, 6, 'c'], [0, 2, 4, 'b'], [360, 180, 360, 'a']]; + assert.deepEqual(df.values, rslt); + }); + }); + + describe("append", function () { + + it("Append works for an array", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data); + const expected_val = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"], + [20, 40, 60, "d"]]; + + const newDf = df.append([20, 40, 60, "d"], ["n1"]) as DataFrame + assert.deepEqual(newDf.values, expected_val); + assert.deepEqual(newDf.index, [0, 1, 2, "n1"]); + }); + it("Append works for an array of arrays", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data); + const expected_val = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"], + [20, 40, 60, "d"], + [21, 42, 61, "y"]]; + + const newDf = df.append([[20, 40, 60, "d"], [21, 42, 61, "y"]], ["n1", "n2"]) as DataFrame + assert.deepEqual(newDf.values, expected_val); + assert.deepEqual(newDf.index, [0, 1, 2, "n1", "n2"]); + }); + + it("Append works for DataFrame", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); + const df2 = new DataFrame([[20, 40, 60, "d"]], { "columns": ["col1", "col2", "col3", "col4"] }); + + const expected_val = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"], + [20, 40, 60, "d"]]; + + const newDf = df.append(df2, ["n1"]) as DataFrame + assert.deepEqual(newDf.values, expected_val); + + }); + it("Append works for Series", function () { + const data = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"]]; + + const df = new DataFrame(data, { "columns": ["col1", "col2", "col3", "col4"] }); + const sf = new Series([20, 40, 60, "d"]); + + const expected_val = [[0, 2, 4, "b"], + [360, 180, 360, "a"], + [2, 4, 6, "c"], + [20, 40, 60, "d"]]; + + const newDf = df.append(sf, ["n1"]) as DataFrame + assert.deepEqual(newDf.values, expected_val); + + }); + }); + + describe("cumProd", function () { + + it("cumProd works for axis 1", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 2, 4, 12], + [3, 12, 132, 1188], + [5, 30, 210, 1680]] + + const newDf = df.cumProd() as DataFrame + assert.deepEqual(newDf.values, rslt); + }); + it("cumProd axis 0 works", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [6, 4, 22, 27], + [30, 24, 154, 216]] + + assert.deepEqual((df.cumProd({ axis: 0 }) as DataFrame).values, rslt); + }); + + it("cumProd works for axis 1 inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 2, 4, 12], + [3, 12, 132, 1188], + [5, 30, 210, 1680]] + + df.cumProd({ inplace: true }) + assert.deepEqual(df.values, rslt); + }); + it("cumProd axis 0 works inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [6, 4, 22, 27], + [30, 24, 154, 216]] + df.cumProd({ axis: 0, inplace: true }) + assert.deepEqual(df.values, rslt); + }); + }); + + describe("cumSum", function () { + + it("cumSum works for axis 1", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 3, 5, 8], + [3, 7, 18, 27], + [5, 11, 18, 26]] + + const newDf = df.cumSum() as DataFrame + assert.deepEqual(newDf.values, rslt); + }); + it("cumSum axis 0 works", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [5, 5, 13, 12], + [10, 11, 20, 20]] + + assert.deepEqual((df.cumSum({ axis: 0 }) as DataFrame).values, rslt); + }); + + it("cumSum works for axis 1 inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 3, 5, 8], + [3, 7, 18, 27], + [5, 11, 18, 26]] + + df.cumSum({ inplace: true }) + assert.deepEqual(df.values, rslt); + }); + it("cumSum axis 0 works inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [5, 5, 13, 12], + [10, 11, 20, 20]] + df.cumSum({ axis: 0, inplace: true }) + assert.deepEqual(df.values, rslt); + }); + }); + + describe("cumMin", function () { + + it("cumMin works for axis 1", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 1, 1], + [3, 3, 3, 3], + [5, 5, 5, 5]] + + const newDf = df.cumMin() as DataFrame + assert.deepEqual(newDf.values, rslt); + }); + it("cumMin axis 0 works", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [2, 1, 2, 3], + [2, 1, 2, 3]] + + assert.deepEqual((df.cumMin({ axis: 0 }) as DataFrame).values, rslt); + }); + + it("cumMin works for axis 1 inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 1, 1], + [3, 3, 3, 3], + [5, 5, 5, 5]] + + df.cumMin({ inplace: true }) + assert.deepEqual(df.values, rslt); + }); + it("cumMin axis 0 works inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [2, 1, 2, 3], + [2, 1, 2, 3]] + df.cumMin({ axis: 0, inplace: true }) + assert.deepEqual(df.values, rslt); + }); + }); + + describe("cumMax", function () { + + it("cumMax works for axis 1", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 2, 2, 3], + [3, 4, 11, 11], + [5, 6, 7, 8]] + + const newDf = df.cumMax() as DataFrame + assert.deepEqual(newDf.values, rslt); + }); + it("cumMax axis 0 works", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [3, 4, 11, 9], + [5, 6, 11, 9]] + + assert.deepEqual((df.cumMax({ axis: 0 }) as DataFrame).values, rslt); + }); + + it("cumMax works for axis 1 inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 2, 2, 3], + [3, 4, 11, 11], + [5, 6, 7, 8]] + + df.cumMax({ inplace: true }) + assert.deepEqual(df.values, rslt); + }); + it("cumMax axis 0 works inplace", function () { + const data = [[2, 1, 2, 3], [3, 4, 11, 9], [5, 6, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = [[2, 1, 2, 3], + [3, 4, 11, 9], + [5, 6, 11, 9]] + df.cumMax({ axis: 0, inplace: true }) + assert.deepEqual(df.values, rslt); + }); + }); + + + describe("query", function () { + + it("Get the DataFrame containing rows with the filtered column", function () { + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const query_df = df.query(df["B"].ge(5)) as DataFrame + const query_data = [[4, 5, 6], [20, 30, 40], [39, 89, 78]] + assert.deepEqual(query_df.values, query_data); + }); + it("Get the Dataframe containing rows with the filtered column in String values", function () { + const data = { "Abs": [20, 30, 47], "Count": [34, 4, 5], "country code": ["NG", "FR", "GH"] }; + const cols = ["Abs", "Count", "country code"]; + const df = new DataFrame(data, { columns: cols }); + const query_df = df.query(df["country code"].str.includes("NG")) as DataFrame + + const query_data = [[20, 34, "NG"]]; + assert.deepEqual(query_df.values, query_data); + }); + it("Get the Dataframe containing rows with the filtered column in String values inplace", function () { + const data = { "Abs": [20, 30, 47], "Count": [34, 4, 5], "country code": ["NG", "FR", "GH"] }; + const cols = ["Abs", "Count", "country code"]; + const df = new DataFrame(data, { columns: cols }); + df.query(df["country code"].eq("NG"), { inplace: true }); + const query_data = [[20, 34, "NG"]]; + assert.deepEqual(df.values, query_data); + }); + it("Confirms that query index are updated", function () { + + const data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + const query_df = df.query(df["B"].ge(5)) as DataFrame + assert.deepEqual(query_df.index, [1, 2, 3]); + }); + + it("Confirms chaining boolean queries work", function () { + + const data = [[1, 2, 3], + [4, 5, 60], + [20, 30, 4], + [39, 89, 7]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const query_df = df.query( + df["B"].ge(5).and(df["C"].lt(10)) + ) as DataFrame + const query_data = [[20, 30, 4], [39, 89, 7]]; + assert.deepEqual(query_df.values, query_data) + assert.deepEqual(query_df.index, [2, 3]); + }); + + it("Confirms chaining boolean queries work and returns empty DF", function () { + + const data = [[1, 2, 3], + [4, 5, 60], + [20, 30, 40], + [39, 89, 70]]; + const cols = ["A", "B", "C"]; + const df = new DataFrame(data, { columns: cols }); + + const query_df = df.query( + df["B"].ge(5).and(df["C"].lt(10)) + ) as DataFrame + assert.deepEqual(query_df.values, []); + assert.deepEqual(query_df.index, []); + }); + + it("Confirms that column names are not changed", function () { + + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]; + let cols = ["A", "B", "C"]; + let df = new DataFrame(data, { columns: cols }); + let df_query = df.query(df["B"].ge(5)); + assert.deepEqual(df_query.index, [1, 2, 3]); + assert.deepEqual(df_query.columns, ["A", "B", "C"]); + }); + + }); + + describe("cTypes", function () { + + it("Returns the correct dtype in a DataFrame", function () { + const data = [["boy", 1.2, 2, 3], ["girl", 4.32, 11, 9], ['4', 6.1, 7, 8]]; + const column = ["A", "B", "C", "D"]; + const df = new DataFrame(data, { columns: column }); + const rslt = ["string", "float32", "int32", "int32"] + assert.deepEqual(df.ctypes.values, rslt); + }); + }); + + describe("getDummies", function () { + it("getDummies works on DataFrame", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + const df1 = df.getDummies({ prefixSeparator: ["_", "#"], columns: ["A", "d"], prefix: "test" }) as DataFrame + const expectedColumns = ['B', 'C', 'test_1', 'test_3', 'test_4', 'test#fat', 'test#good', 'test#best'] + const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], + ['fog', 2.0, 0, 1, 0, 0, 1, 0], + ['gof', 3.0, 0, 0, 1, 0, 0, 1]] + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + it("Throw error if the prefix specified is not equal to the column specified", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + assert.throws(function () { df.getDummies({ prefix: ["fg"], prefixSeparator: "_", columns: ["A", "d"] }); }, Error, + `ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "fg"}`); + + }); + it("replace column sepecified with prefix", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + const df1 = df.getDummies({ prefix: ["F", "G"], prefixSeparator: "_", columns: ["A", "d"] }) as DataFrame + const expectedColumns = [ + 'B', 'C', + 'F_1', 'F_3', + 'F_4', 'G_fat', + 'G_good', 'G_best' + ]; + + const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], + ['fog', 2.0, 0, 1, 0, 0, 1, 0], + ['gof', 3.0, 0, 0, 1, 0, 0, 1]] + + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("getDummies auto infers and encode columns with string dtype", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + const df1 = df.getDummies({ prefixSeparator: "_" }) as DataFrame + const expectedColumns = [ + 'A', 'C', + 'B_dog', 'B_fog', + 'B_gof', 'd_fat', + 'd_good', 'd_best' + ]; + const expected = [ + [ + 1, 1, 1, 0, + 0, 1, 0, 0 + ], + [ + 3, 2, 0, 1, + 0, 0, 1, 0 + ], + [ + 4, 3, 0, 0, + 1, 0, 0, 1 + ] + ]; + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("should one hot encode all other columns", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }) + const rslt = [ + [1, 'dog', 1, 1, 0, 0], + [3, 'fog', 2, 0, 1, 0], + [4, 'gof', 3, 0, 0, 1] + ] + + assert.deepEqual((df.getDummies({ columns: ["d"] }) as DataFrame).values, rslt) + + }); + }); + + describe("iat", function () { + it("iat works on DataFrame", function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]; + const columns = ["a", "b", "c", "d"]; + const df = new DataFrame(data, { columns }); + assert.equal(df.iat(0, 0), 1); + assert.equal(df.iat(1, 1), 6); + assert.equal(df.iat(2, 3), 12); + }); + it("throws error on string indices", function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]; + const columns = ["a", "b", "c", "d"]; + const index = ["A", "B", "C"]; + const df = new DataFrame(data, { columns, index }); + /* @ts-ignore */ + assert.throws(function () { df.iat("A", 0); }, Error, "ParamError: row and column index must be an integer. Use .at to get a row or column by label."); + /* @ts-ignore */ + assert.throws(function () { df.iat(0, "A"); }, Error, "ParamError: row and column index must be an integer. Use .at to get a row or column by label."); + }); + }) + + describe("at", function () { + it("at works on DataFrame", function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]; + const columns = ["a", "b", "c", "d"]; + const index = ["A", "B", "C"] + const df = new DataFrame(data, { columns, index }); + assert.equal(df.at("A", "a"), 1); + assert.equal(df.at("B", "b"), 6); + assert.equal(df.at("C", "c"), 11); + + }); + it("throws error on numeric column index", function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]; + const columns = ["a", "b", "c", "d"]; + const index = [0, "B", "C"] + const df = new DataFrame(data, { columns, index }); + + assert.equal(df.at(0, "b"), 2); + /* @ts-ignore */ + assert.throws(function () { df.at(0, 1); }, Error, "ParamError: column index must be a string. Use .iat to get a row or column by index."); + /* @ts-ignore */ + assert.throws(function () { df.at("B", 0); }, Error, "ParamError: column index must be a string. Use .iat to get a row or column by index."); + + }); + + }); + + describe("DateTime datetime is supported", function () { + it("DateTime datetime is supported", function () { + let data = [["Alice", 2, new Date(2029, 1, 1)], + ["Bob", 5, new Date(2019, 1, 2)], + ["Charlie", 30, new Date(2019, 1, 3)], + ["Dennis", 89, new Date(2019, 1, 4)]]; + + let columns = ["Name", "Count", "Date"]; + + let df = new DataFrame(data, { columns: columns }); + assert.deepEqual(df.dtypes, ["string", "int32", "datetime"]); + + const dateValues = [new Date(2029, 1, 1), new Date(2019, 1, 2), new Date(2019, 1, 3), new Date(2019, 1, 4)] + assert.deepEqual(df["Date"].values, dateValues); + }); + + it("datetime column properties can be accessed", function () { + let data = [["Alice", 2, new Date("2029-01-01 01:00:00")], + ["Bob", 5, new Date("2019-01-02")], + ["Charlie", 30, new Date("2020-01-03 01:00:20")], + ["Dennis", 89, new Date("2022-02-04 02:16:00")]]; + + let columns = ["Name", "Count", "Date"]; + + let df = new DataFrame(data, { columns: columns }); + + assert.deepEqual(df["Date"].dt.year().values, [2029, 2019, 2020, 2022]); + assert.deepEqual(df["Date"].dt.month().values, [0, 0, 0, 1]); + assert.deepEqual(df["Date"].dt.dayOfMonth().values, [1, 2, 3, 4]); + assert.deepEqual(df["Date"].dt.hours().values, [1, 0, 1, 2]); + assert.deepEqual(df["Date"].dt.minutes().values, [0, 0, 0, 16]); + assert.deepEqual(df["Date"].dt.seconds().values, [0, 0, 20, 0]); + + }) + + it("datetime column created from dtype passed", function () { + let data = [["Alice", 2, "2029-01-01 01:00:00"], + ["Bob", 5, "2019-01-02"], + ["Charlie", 30, "2020-01-03 01:00:20"], + ["Dennis", 89, "2022-02-04 02:16:00"]]; + + let columns = ["Name", "Count", "Date"]; + let dtypes = ["string", "int32", "datetime"] + + let df = new DataFrame(data, { columns, dtypes }); + + assert.deepEqual(df["Date"].dt.year().values, [2029, 2019, 2020, 2022]); + assert.deepEqual(df["Date"].dt.month().values, [0, 0, 0, 1]); + assert.deepEqual(df["Date"].dt.dayOfMonth().values, [1, 2, 3, 4]); + assert.deepEqual(df["Date"].dt.hours().values, [1, 0, 1, 2]); + assert.deepEqual(df["Date"].dt.minutes().values, [0, 0, 0, 16]); + assert.deepEqual(df["Date"].dt.seconds().values, [0, 0, 20, 0]); + + }); + }); +}); diff --git a/src/danfojs-node/test/core/generic.test.ts b/src/danfojs-node/test/core/generic.test.ts new file mode 100644 index 00000000..300db8d6 --- /dev/null +++ b/src/danfojs-node/test/core/generic.test.ts @@ -0,0 +1,441 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { NDframe } from '../../dist/danfojs-node/src'; +import { tensor } from '@tensorflow/tfjs-node'; + + +describe("Generic (NDFrame)", function () { + describe("NDframe Created from Array", function () { + it("prints the shape of a 1D array", function () { + let data = [1, 2, 3, "Boy", "Girl"]; + let ndframe = new NDframe({ data, isSeries: true }); + assert.deepEqual(ndframe.shape, [5, 1]); + }); + it("prints the default assigned column name in a series", function () { + let data = ["Boy", 20, 25]; + let ndframe = new NDframe({ data, isSeries: true }); + assert.deepEqual(ndframe.columns, ["0"]); + }); + it("prints the assigned column name in a series", function () { + let data = ["Boy", 20, 25]; + let ndframe = new NDframe({ data, columns: ["Records"], isSeries: true }); + assert.deepEqual(ndframe.columns, ["Records"]); + }); + it("prints the shape of a 2D array", function () { + let data = [["Boy", 20], ["Girl", 25]]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.shape, [2, 2]); + }); + it("prints the default assigned column names in 2D frame", function () { + let data = [["Boy", 20], ["Girl", 25]]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.columns, ["0", "1"]); + }); + it("prints the assigned column names", function () { + let data = [["Boy", 20], ["Girl", 25]]; + let options = { "columns": ["Gender", "Age"], "isSeries": false }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.columns, ["Gender", "Age"]); + }); + it("prints the size of a frame", function () { + let data = [["Boy", 20, 1], ["Girl", 25, 3]]; + let options = { "columns": ["Gender", "Age", "count"], "isSeries": false }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.size, 6); + }); + it("prints the dimension of a frame", function () { + let data = [["Boy", 20, 1], ["Girl", 25, 3]]; + let options = { "columns": ["Gender", "Age", "count"], "isSeries": false }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.ndim, 2); + }); + it("prints the values of a frame", function () { + let data = [[21, 20, 1], [20, 25, 3]]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, data); + }); + it("prints the values of a frame", function () { + let data = [[21, 20, 1], [20, 25, 3]]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, data); + }); + + it("Throws error on duplicate column name", function () { + let data = [[21, 20, 1], [20, 25, 3]]; + assert.throws( + () => new NDframe({ data, isSeries: false, columns: ["A", "A", "C"] }), Error, + "ColumnIndexError: Column index must contain unique values"); + }); + + it("Throws error on duplicate index", function () { + let data = [[21, 20, 1], [20, 25, 3], [19, 30, 5]]; + assert.throws( + () => new NDframe({ data, isSeries: false, index: [1, 1, 2] }), Error, + "IndexError: Row index must contain unique values"); + }); + + it("Successfully create a 2D Frame when first value is empty", function () { + let data = [[null, 20, 1], [20, 25, 3]]; + let ndframe = new NDframe({ data, isSeries: false }); + //@ts-ignore + assert.deepEqual(ndframe.values, data); + }); + it("Successfully create a 1D Frame when first value is empty", function () { + let data = [null, 'bval2', 'bval3', 'bval4']; + let ndframe = new NDframe({ data, isSeries: true }); + //@ts-ignore + assert.deepEqual(ndframe.values, data); + }); + }) + + describe("NDframe Created from JavaScript Object", function () { + + it("prints the shape of a 2D frame created from an Object", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.shape, [3, 2]); + }); + it("prints the column names of frame created from an Object", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.columns, ["alpha", "count"]); + }); + it("prints the shape of a 1D frame created from an Object", function () { + let data = [{ alpha: "A", count: 1 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.shape, [1, 2]); + }); + + it("prints the size of a frame created from an Object", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.size, 6); + }); + it("prints the dimension of a frame created from an Object", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.ndim, 2); + }); + it("prints the values of a frame created from an Object", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values as any, [["A", 1], ["B", 2]]); + }); + it("prints the values of a frame created from an Object with undefined values", function () { + let data = [{ alpha: "A", count: undefined }, { alpha: undefined, count: 2 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values as any, [["A", undefined], [undefined, 2]]); + }); + + it("prints the values of a frame created from an Object with NaN values", function () { + let data = [{ alpha: "A", count: NaN }, { alpha: NaN, count: 2 }]; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values as any, [["A", NaN], [NaN, 2]]); + }); + }); + + describe("Replacing row data", function () { + it("retrieves the col data after row data is replaced in a DataFrame", function () { + let data = { alpha: ["A", "B"], count: [1, 2] }; + let ndframe = new NDframe({ data, isSeries: false }); + ndframe.$setValues([["A", 20], ["D", 211]]) + assert.deepEqual(ndframe.values, [["A", 20], ["D", 211]]); + + }); + it("Correct dtypes is inferred after row data is replaced in a DataFrame", function () { + let data = { alpha: ["A", "B"], count: [1, 2] }; + let ndframe = new NDframe({ data, isSeries: false }); + ndframe.$setValues([[20, 20], [11.4, 211]]) + assert.deepEqual(ndframe.dtypes, ["float32", "int32"]); + + }); + it("Throws row length error on invalid data length in DataFrame", function () { + let data = { alpha: ["A", "B"], count: [1, 2] }; + let ndframe = new NDframe({ data, isSeries: false }); + assert.throws( + () => { + ndframe.$setValues([[20, 20], [11.4, 211], [11.4, 211]]) + }, + Error, + "Row data length mismatch. You provided data with length 3 but Ndframe has row of length 2" + ); + }); + it("Throws column length error on invalid data length in DataFrame", function () { + let data = { alpha: ["A", "B"], count: [1, 2] }; + let ndframe = new NDframe({ data, isSeries: false }); + assert.throws( + () => { + ndframe.$setValues([[20, 211], [20, 20, 11.4, 211]]) + }, + Error, + "Column data length mismatch. You provided data with length 2 but Ndframe has column of length 2" + ); + }); + it("retrieves the col data after row data is replaced in a Series", function () { + let data = ["A", "B", 1, 2] + let ndframe = new NDframe({ data, isSeries: true }); + ndframe.$setValues(["A", "D", "E", "O"]) + assert.deepEqual(ndframe.values, ["A", "D", "E", "O"]); + + }); + it("Correct dtypes is inferred after updating values", function () { + let data = ["A", "D", "E", "O"] + let ndframe = new NDframe({ data, isSeries: true }); + ndframe.$setValues([1, 2, 3, 4]) + assert.deepEqual(ndframe.values, [1, 2, 3, 4]); + assert.deepEqual(ndframe.dtypes[0], "int32"); + }); + it("Correct dtypes is inferred after updating values in low memory mode", function () { + let data = ["A", "D", "E", "O"] + let ndframe = new NDframe({ data, isSeries: true, config: { lowMemoryMode: true } }); + ndframe.$setValues([1, 2, 3, 4]) + assert.deepEqual(ndframe.values, [1, 2, 3, 4]); + assert.deepEqual(ndframe.dtypes[0], "int32"); + }); + it("Throws row length error on invalid data length", function () { + let data = ["A", "D", "E", "O"] + let ndframe = new NDframe({ data, isSeries: true, config: { lowMemoryMode: true } }); + assert.throws( + () => { + ndframe.$setValues([1, 2, 3, 4, 1, 3]) + }, + Error, + "Row data length mismatch. You provided data with length 6 but Ndframe has row of length 4" + ); + }); + + }) + + describe("NDframe Created from a Tensor", function () { + + it("prints the shape of a 2D frame created from a 2D tensor", function () { + let data = tensor([1, 2, 3, 4]); + let ndframe = new NDframe({ data, isSeries: true }); + assert.deepEqual(ndframe.ndim, 1); + assert.deepEqual(ndframe.values, [1, 2, 3, 4]); + + }); + it("prints the shape of a 2D frame created from a 1D tensor", function () { + let data = tensor([[2, 3, 4], [4, 5, 6]]); + let ndframe = new NDframe({ data, columns: ["alpha", "count", "sum"], isSeries: false }); + assert.deepEqual(ndframe.columns, ["alpha", "count", "sum"]); + }); + + }); + + describe("index", function () { + it("Returns the index of an NDframe", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; + let df = new NDframe({ data, isSeries: false }); + assert.deepEqual(df.index, [0, 1, 2]); + }); + it("Returns the index of an NDframe created from an Array", function () { + let data = [[12, 2, 20], [90, 5, 23], [45, 56, 70], [9, 10, 19]]; + let df = new NDframe({ data, isSeries: false }); + assert.deepEqual(df.index, [0, 1, 2, 3]); + }); + }); + + describe("NDframe Created from JavaScript Object of Arrays", function () { + + it("retrieves the col data created from OA ", function () { + let data = { alpha: ["A", "B", "C", "D"], count: [1, 2, 3, 4] }; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, [['A', 1], ['B', 2], ['C', 3], ['D', 4]]); + }); + it("retrieves the data 2", function () { + let data = { alpha: ["A", "B", "C", "D"], count: [1, 2, 3, 4], sum: [20.3, 30.456, 40.90, 90.1] }; + let ndframe = new NDframe({ data, isSeries: false }); + let res = [ + ['A', 1, 20.3], + ['B', 2, 30.456], + ['C', 3, 40.9], + ['D', 4, 90.1] + ] + assert.deepEqual(ndframe.values, res); + }); + it("retrieves the row data created from OA ", function () { + let data = { alpha: ["A", "B"], count: [1, 2] }; + let ndframe = new NDframe({ data, isSeries: false }); + assert.deepEqual(ndframe.values, [["A", 1], ["B", 2]]); + }); + }); + + describe("setIndex", function () { + it("sets the index of an NDframe", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }, { alpha: "C", count: 3 }]; + let df = new NDframe({ data, isSeries: false }); + df.$setIndex(["A", "B", "C"]); + assert.deepEqual(df.index, ["A", "B", "C"]); + }); + it("Returns the index of an NDframe created from an Array", function () { + let data = [[12, 2, 20], [90, 5, 23], [45, 56, 70], [9, 10, 19]]; + let df = new NDframe({ data, isSeries: false }); + df.$setIndex([10, 20, 30, 40]); + assert.deepEqual(df.index, [10, 20, 30, 40]); + }); + }); + + + describe("dtype", function () { + it("Returns int dtype set during creation of 1DFrame (Series) from an Object", function () { + let data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let options = { dtypes: ['int32'], isSeries: true }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, ['int32']); + }); + + it("Returns string dtype set during creation of 1DFrame (Series) from an Array", function () { + let data = ["Alice", "Yemi", "Rising", "Mark"]; + let options = { dtypes: ['string'], isSeries: true }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, ["string"]); + }); + + it("Returns string dtype automatically inferred from 1DFrame (Series)", function () { + let data = ["Alice", "Yemi", "Rising", "Mark"]; + let options = { columns: ['Names'], isSeries: true }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, ["string"]); + }); + + it("Returns int dtype automatically inferred from 1DFrame (Series)", function () { + let data = [20, 30, 20, 20]; + let options = { columns: ['Size'], isSeries: true }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, ["int32"]); + }); + it("Returns float dtype automatically inferred from 1DFrame (Series)", function () { + let data = [20.1, 30.4, 20.2, 4.23, 20.1]; + let options = { columns: ['Size'], isSeries: true }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, ["float32"]); + }); + + + it("Returns dtype set during creation of 2DFrame from an Object", function () { + let data = [{ alpha: "A", count: 1 }, { alpha: "B", count: 2 }]; + let options = { dtypes: ['string', 'int32'] }; + let ndframe = new NDframe({ data, ...options, isSeries: false }); + assert.deepEqual(ndframe.dtypes, ['string', 'int32']); + }); + it("Returns dtype set during creation of 2DFrame from an Array", function () { + let data = [["Alice", 2, 3.0], ["Boy", 5, 6.1], ["Girl", 30, 40], [39, 89, 78.2]]; + let cols = ["Name", "Count", "Score"]; + let options = { columns: cols, dtypes: ['string', 'int32', 'float32'] }; + let ndframe = new NDframe({ data, ...options, isSeries: false }); + assert.deepEqual(ndframe.dtypes, ["string", "int32", "float32"]); + }); + + it("Returns dtype automatically inferred from 2DFrame", function () { + let data = [["Alice", 2, 3.1], ["Boy", 5, 6.1], ["Girl", 30, 40.2], [39, 89, 78.2]]; + let cols = ["Name", "Count", "Score"]; + let options = { columns: cols, isSeries: false }; + let ndframe = new NDframe({ data, ...options }); + assert.deepEqual(ndframe.dtypes, ["string", "int32", "float32"]); + }); + + }); + + describe("Empty NDFrame", function () { + it("Can successfully create an empty NDframe from empty array", function () { + let data: any = []; + let df = new NDframe({ data, isSeries: false }); + assert.deepEqual(df.shape, [0, 0]); + assert.deepEqual(df.columns, []); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new NDframe({ data, isSeries: true }); + assert.deepEqual(sf.shape, [0, 0]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + it("Can successfully create an empty NDframe from undefined data", function () { + let data = undefined; + let df = new NDframe({ data, isSeries: false }); + assert.deepEqual(df.shape, [0, 0]); + assert.deepEqual(df.columns, []); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new NDframe({ data, isSeries: true }); + assert.deepEqual(sf.shape, [0, 0]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty NDframe", function () { + let df = new NDframe({ data: [], isSeries: false }); + assert.deepEqual(df.shape, [0, 0]); + assert.deepEqual(df.columns, []); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new NDframe({ data: [], isSeries: true }); + assert.deepEqual(sf.shape, [0, 0]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty NDframe with columns names", function () { + let data: any = []; + let df = new NDframe({ data, columns: [ "A", "B", "C" ], isSeries: false }); + assert.deepEqual(df.shape, [ 0, 3 ]); + assert.deepEqual(df.columns, [ "A", "B", "C" ]); + assert.deepEqual(df.dtypes, []); + assert.deepEqual(df.values, []); + let sf = new NDframe({ data, columns: [ "A" ], isSeries: true }); + assert.deepEqual(sf.shape, [ 0, 1 ]); + assert.deepEqual(sf.columns, [ "A" ]); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty NDframe with columns names and dtypes", function () { + let data: any = []; + let df = new NDframe({ data, columns: [ "A", "B", "C" ], dtypes: [ "string", "string", "int32" ], isSeries: false }); + assert.deepEqual(df.shape, [ 0, 3 ]); + assert.deepEqual(df.columns, [ "A", "B", "C" ]); + assert.deepEqual(df.dtypes, [ "string", "string", "int32" ]); + assert.deepEqual(df.values, []); + let sf = new NDframe({ data, columns: [ "A" ], dtypes: [ "string" ], isSeries: true }); + assert.deepEqual(sf.shape, [ 0, 1 ]); + assert.deepEqual(sf.columns, [ "A" ]); + assert.deepEqual(sf.dtypes, [ "string" ]); + assert.deepEqual(sf.values, []); + }); + + it("Cannot successfully create an empty NDframe with only columns dtypes", function () { + let data: any = []; + assert.throws( + () => new NDframe({ data, dtypes: [ "string", "string", "int32" ], isSeries: false }), + Error, + "DtypeError: columns parameter must be provided when dtypes parameter is provided" + ); + assert.throws( + () => new NDframe({ data, dtypes: [ "string" ], isSeries: true }), + Error, + "DtypeError: columns parameter must be provided when dtypes parameter is provided" + ); + }); + + }); + + describe("DataFrame supports date object", function (){ + it("Can successfully create a DataFrame from an Array with date object", function () { + let data = [["Alice", 2, new Date(2019, 1, 1)], + ["Bob", 5, new Date(2019, 1, 2)], + ["Charlie", 30, new Date(2019, 1, 3)], + ["Dennis", 89, new Date(2019, 1, 4)]]; + let columns = ["Name", "Count", "Date"]; + + let df = new NDframe({ data, columns, isSeries: false }); + let dfDtypes = ['string', 'int32', 'datetime'] + assert.deepEqual(df.dtypes, dfDtypes); + // @ts-ignore + assert.deepEqual(df.values, data); + assert.deepEqual(df.columns, columns); + }); + }) +}); diff --git a/src/danfojs-node/test/core/indexing.test.ts b/src/danfojs-node/test/core/indexing.test.ts new file mode 100644 index 00000000..1164cf14 --- /dev/null +++ b/src/danfojs-node/test/core/indexing.test.ts @@ -0,0 +1,433 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, Series } from "../../dist/danfojs-node/src"; + +describe("Iloc and Loc based Indexing", function () { + describe("Iloc Index", function () { + it("throw error for wrong row index value", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + + assert.throws(function () { df.iloc(0 as any) }, Error, `rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); + }); + + it("throw error for wrong string split parameter", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc(["0;1"]); }, Error, `Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + }); + + it("throw error for wrong string split value", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc(["0:a"]); }, Error, `Invalid row split parameter. Split parameter must be a number`); + }); + + it("throw error for string split values greater than 2", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc(["0:4:2"]); }, Error, `Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + }); + + it("throw error for row index larger than series length", function () { + let data = [1, 2, 34, 5, 6]; + + let df = new Series(data); + assert.throws(function () { df.iloc([0, 8]); }, Error, "Invalid row parameter: Specified index 8 cannot be bigger than index length 5"); + }); + + it("throw error for non-numeric row index", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc([0, "4"]); }, Error, "Invalid row parameter: row index 4 must be a number"); + }); + + + it("df.iloc works for rows:[0,1]", function () { + let data = [1, 2, 34, 5, 6]; + + let df = new Series(data); + + let sf = df.iloc([0, 1]); + let expected = [1, 2]; + + assert.deepEqual(sf.values, expected); + }); + + it("df.iloc works for rows:[1]", function () { + let data = [1, 2, 34, 5, 6]; + + let df = new Series(data); + + let sf = df.iloc([1]); + let expected = [2]; + + assert.deepEqual(sf.values, expected); + }); + + it("correct index is returned for df.iloc rows:[1, 2]", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data, { index: ["a", "b", "c", "d", "e"] }); + + let sf = df.iloc([1, 4]); + let expected = ["b", "e"]; + + assert.deepEqual(sf.index, expected); + }); + + + it("row slice with string param works [0:2]", function () { + let data = [1, 2, 4, 5, 6, 20, 30, 40, 39, 89, 78]; + let df = new Series(data); + + let sf = df.iloc(["0:2"]); + let expected = [1, 2]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [1:]", function () { + let data = [1, 2, 34, 5, 620, 30, 409, 89, 78]; + let df = new Series(data); + + let sf = df.iloc(["1:"]); + let expected = [2, 34, 5, 620, 30, 409, 89, 78]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:2]", function () { + let data = [1, 2, 34, 5, 6, 20, 30, 40, 39, 89, 78]; + let df = new Series(data); + let sf = df.iloc([":2"]); + let expected = [1, 2]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:]", function () { + let data = [1, 2, 3, 5, 20, 30, 4039, 89, 78]; + let df = new Series(data); + let expected = [1, 2, 3, 5, 20, 30, 4039, 89, 78]; + + let sf = df.iloc([":"]); + assert.deepEqual(sf.values, expected); + + }); + + it(`throw error for wrong start index size ["0:20"]`, function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc(["0:20"]); }, Error, `row slice [end] index cannot be bigger than 5`); + }); + + it(`throw error for wrong start index size ["-1:2"]`, function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc(["-1:2"]); }, Error, `row slice [start] index cannot be less than 0`); + }); + + it("check data after column slice", function () { + let data = [1, 2, 34, 5, 620, 30, 4039, 89, 78]; + let df = new Series(data); + + let sf = df.iloc([0, 1, 6]); + let expected = [1, 2, 4039]; + assert.deepEqual(sf.values, expected); + + }); + + it("iloc works for boolean array", function () { + let data = [1, 2, 34, 5, 620]; + let df = new Series(data); + + let sf = df.iloc([true, true, false, true, false]); + let expected = [1, 2, 5]; + assert.deepEqual(sf.values, expected); + + }); + + it("iloc works for boolean array (all true)", function () { + let data = [1, 2, 34, 5, 620]; + let df = new Series(data); + + let sf = df.iloc([true, true, true, true, true]); + let expected = [1, 2, 34, 5, 620]; + assert.deepEqual(sf.values, expected); + + }); + it("iloc works for boolean array (all false)", function () { + let data = [1, 2, 34, 5, 620]; + let df = new Series(data); + + let sf = df.iloc([false, false, false, false, false]); + let expected: any = []; + assert.deepEqual(sf.values, expected); + + }); + + it("boolean iloc works for DataFrame", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: [false, false, false, true] }); + const result = [['Pear', 10, 250]]; + assert.deepEqual(subDf.values, result); + + }); + + + it("boolean iloc works for DataFrame with specified columns", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: [false, false, false, true], columns: [0, 2] }); + const result = [['Pear', 250]]; + assert.deepEqual(subDf.values, result); + + }); + + it("boolean iloc works for DataFrame with Series bool selector", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.iloc({ rows: df["Count"].gt(10), columns: [0, 2] }); + const result = [['Apples', 200], ['Banana', 40]] + assert.deepEqual(subDf.values, result); + + }); + }) + + describe("Loc Index", function () { + it("throw error for wrong row index value", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.loc(0 as any) }, Error, `rows parameter must be an Array. For example: rows: [1,2] or rows: ["0:10"]`); + }); + + it("throw error for wrong string split parameter", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.loc(["a;1"]); }, Error, `IndexError: Specified index (a;1) not found`); + }); + it(`throw error for wrong string split parameter ("0;1")`, function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.loc(["0;1"]); }, Error, `IndexError: Specified index (0;1) not found`); + }); + + it("throw error for wrong string split end value", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.loc(["0:a"]); }, Error, `IndexError: Specified end index not found`); + }); + + it("throw error for string split values greater than 2", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.loc(["0:4:2"]); }, Error, `Invalid row split parameter: If using row split string, it must be of the form; rows: ["start:end"]`); + }); + + it("throw error for row index larger than series length", function () { + let data = [1, 2, 34, 5, 6]; + + let df = new Series(data); + assert.throws(function () { df.loc([0, 8]); }, Error, "IndexError: Specified index (8) not found"); + }); + + it("throw error for non-numeric row index not found", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.loc([0, "4"]); }, Error, "IndexError: Specified index (4) not found"); + }); + + + it("df.iloc works for rows:[0,1]", function () { + let data = [1, 2, 34, 5, 6]; + + let df = new Series(data); + + let sf = df.loc([0, 1]); + let expected = [1, 2]; + + assert.deepEqual(sf.values, expected); + }); + + it("df.iloc works for rows:[1]", function () { + let data = [1, 2, 34, 5, 6]; + + let df = new Series(data); + + let sf = df.loc([1]); + let expected = [2]; + + assert.deepEqual(sf.values, expected); + }); + + it("correct index is returned for df.loc([1, 4])", function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data, { index: ["a", "b", "c", "d", "e"] }); + + let sf = df.loc(["b", "e"]); + let expected = ["b", "e"]; + assert.deepEqual(sf.index, expected); + }); + + it("row slice with string param works [0:2]", function () { + let data = [1, 2, 4, 5, 6, 20, 30, 40, 39, 89, 78]; + let df = new Series(data); + + let sf = df.loc(["0:2"]); + let expected = [1, 2]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [1:]", function () { + let data = [1, 2, 34, 5, 620, 30, 409, 89, 78]; + let df = new Series(data); + + let sf = df.loc(["1:"]); + let expected = [2, 34, 5, 620, 30, 409, 89, 78]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:2]", function () { + let data = [1, 2, 34, 5, 6, 20, 30, 40, 39, 89, 78]; + let df = new Series(data); + let sf = df.loc([":2"]); + let expected = [1, 2]; + + assert.deepEqual(sf.values, expected); + + }); + it("row slice with string param works [:]", function () { + let data = [1, 2, 3, 5, 20, 30, 4039, 89, 78]; + let df = new Series(data); + let expected = [1, 2, 3, 5, 20, 30, 4039, 89, 78]; + + let sf = df.loc([":"]); + assert.deepEqual(sf.values, expected); + + }); + + it(`throw error for wrong start index size ["0:20"]`, function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc(["0:20"]); }, Error, `row slice [end] index cannot be bigger than 5`); + }); + + it(`throw error for wrong start index size ["-1:2"]`, function () { + let data = [1, 2, 34, 5, 6]; + let df = new Series(data); + assert.throws(function () { df.iloc(["-1:2"]); }, Error, `row slice [start] index cannot be less than 0`); + }); + + it("check data after column slice", function () { + let data = [1, 2, 34, 5, 620, 30, 4039, 89, 78]; + let df = new Series(data); + + let sf = df.loc([0, 1, 6]); + let expected = [1, 2, 4039]; + assert.deepEqual(sf.values, expected); + + }); + + it("loc works for boolean array", function () { + let data = [1, 2, 34, 5, 620]; + let df = new Series(data); + + let sf = df.loc([true, true, false, true, false]); + let expected = [1, 2, 5]; + assert.deepEqual(sf.values, expected); + + }); + + it("loc works for boolean array (all true)", function () { + let data = [1, 2, 34, 5, 620]; + let df = new Series(data); + + let sf = df.loc([true, true, true, true, true]); + let expected = [1, 2, 34, 5, 620]; + assert.deepEqual(sf.values, expected); + + }); + it("loc works for boolean array (all false)", function () { + let data = [1, 2, 34, 5, 620]; + let df = new Series(data); + + let sf = df.loc([false, false, false, false, false]); + let expected: any = []; + assert.deepEqual(sf.values, expected); + + }); + + it("boolean loc works for DataFrame", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.loc({ rows: [false, false, false, true] }); + const result = [['Pear', 10, 250]]; + assert.deepEqual(subDf.values, result); + + }); + + + it("boolean loc works for DataFrame with specified columns", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.loc({ rows: [false, false, false, true], columns: ["Name", "Price"] }); + const result = [['Pear', 250]]; + assert.deepEqual(subDf.values, result); + + }); + + it("boolean loc works for DataFrame with Series bool selector", function () { + const data = { + "Name": ["Apples", "Mango", "Banana", "Pear"], + "Count": [21, 5, 30, 10], + "Price": [200, 300, 40, 250] + }; + const df = new DataFrame(data); + const subDf = df.loc({ rows: df["Count"].gt(10), columns: ["Name", "Price"] }); + const result = [['Apples', 200], ['Banana', 40]] + assert.deepEqual(subDf.values, result); + + }); + + it("loc with no matches create a Empty DataFrame conserving columns information", function () { + const data = { + "Name": [ "Apples", "Mango", "Banana", "Pear" ], + "Count": [ 21, 5, 30, 10 ], + "Price": [ 200, 300, 40, 250 ] + }; + const df = new DataFrame(data); + const subDf = df.loc({ rows: df["Count"].gt(50) }); + + assert.deepEqual(subDf.values, []); + assert.deepEqual(subDf.shape, [ 0, 3 ]); + assert.deepEqual(subDf.columns, [ "Name", "Count", "Price" ]); + assert.deepEqual(subDf.dtypes, [ "string", "int32", "int32" ]); + + }); + + }) + +}); \ No newline at end of file diff --git a/src/danfojs-node/test/core/series.test.ts b/src/danfojs-node/test/core/series.test.ts new file mode 100644 index 00000000..ac17d092 --- /dev/null +++ b/src/danfojs-node/test/core/series.test.ts @@ -0,0 +1,1758 @@ +import { assert, expect } from "chai"; +import { describe, it } from "mocha"; +import { Series } from "../../dist/danfojs-node/src"; + +describe("Series Functions", () => { + + describe("head", function () { + it("Gets the first 2 rows in a Series", function () { + const data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; + const cols = ["A"]; + const sf = new Series(data, { columns: cols }); + assert.deepEqual(sf.head(2).values, [1, 2]); + assert.deepEqual(sf.head(5).values, [1, 2, 3, 4, 5]); + }); + + it("throw error when row specified is less than 0", function () { + const data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; + const sf = new Series(data); + assert.throws(function () { assert.deepEqual(sf.head(-1).values, data) }, Error, `ParamError: Number of rows cannot be less than 1`); + }); + it("Returns all rows when DataFrame length is less than rows", function () { + const data = [ 1, 2, 5 ]; + const sf = new Series(data); + assert.deepEqual(sf.head().values, data); + + }); + }); + + + describe("tail", function () { + it("Prints the last n rows of a Series", function () { + const data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; + const sf = new Series(data); + assert.deepEqual(sf.tail(2).values, [89, 78]); + assert.deepEqual(sf.tail(4).values, [40, 39, 89, 78]); + + }); + + it("throw error when row specified is less than 0", function () { + const data = ["Boy", "Girl", "Man", "Woman", "Tall"]; + const cols = ["Items"]; + const sf = new Series(data, { columns: cols }); + assert.throws(function () { assert.deepEqual(sf.tail(-1).values, data) }, Error, `ParamError: Number of rows cannot be less than 1`); + }); + + it("Returns all rows when DataFrame length is less than rows", function () { + const data = [ 1, 2, 5 ]; + const sf = new Series(data); + assert.deepEqual(sf.tail().values, data); + + }); + }); + + describe("sample", function () { + it("Samples n number of random elements from a DataFrame", async function () { + const data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; + const sf = new Series(data); + assert.deepEqual((await sf.sample(7)).values.length, 7); + }); + it("Return all values if n of sample -1", async function () { + const data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; + const sf = new Series(data); + assert.deepEqual((await sf.sample(-1)).values.length, data.length); + }); + + it("Throw error if n is greater than length of Series", async function () { + const data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; + const sf = new Series(data); + try { + await sf.sample(100); + } catch (e: any) { + expect(e.message).to.eql('Sample size n cannot be bigger than size of dataset'); + } + }); + }); + + describe("add", function () { + it("Return Addition of series with another series", function () { + const data = [1, 2, 3, 4, 5, 6]; + const data2 = [30, 40, 39, 1, 2, 1]; + const sf = new Series(data); + const sf2 = new Series(data2); + assert.deepEqual((sf.add(sf2)).values, [31, 42, 42, 5, 7, 7]); + }); + it("Return Addition of series with a single value (Broadcasting)", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + assert.deepEqual((sf.add(1)).values, [2, 3, 4, 5, 6]); + }); + it("Return Addition of series with another series inplace", function () { + const data = [1, 2, 3, 4, 5, 6]; + const data2 = [30, 40, 39, 1, 2, 1]; + const sf = new Series(data); + const sf2 = new Series(data2); + sf.add(sf2, { inplace: true }) + assert.deepEqual(sf.values, [31, 42, 42, 5, 7, 7]); + }); + it("Return Addition of series with a single value (Broadcasting) inplace", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + sf.add(1, { inplace: true }) + assert.deepEqual(sf.values, [2, 3, 4, 5, 6]); + }); + it("Dtype is properly updated on addition of series with a single float value inplace", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + sf.add(1.23, { inplace: true }) + assert.deepEqual(sf.dtypes[0], "float32"); + assert.deepEqual(sf.values, [2.23, 3.23, 4.23, 5.23, 6.23]); + }); + it("Add works properly when using tfjs add function", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + sf.add(1.23, { inplace: true }) + assert.deepEqual(sf.dtypes[0], "float32"); + assert.deepEqual(sf.values, [2.23, 3.23, 4.23, 5.23, 6.23]); + }); + it("Add works properly when using tfjs add function on Series", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + const sf2 = new Series([1.23, 1.23, 1.23, 1.23, 1.23]); + sf.add(sf2, { inplace: true }) + assert.deepEqual(sf.values, [2.23, 3.23, 4.23, 5.23, 6.23]); + }); + it("Throws type error on addition of string type", function () { + const data = [1, 2, 3, 4]; + const data2 = ["A", "B", "C", "d"]; + const sf = new Series(data); + const sf2 = new Series(data2); + assert.throws( + () => { + sf.add(sf2); + }, + Error, + "DtypeError: String data type does not support add operation" + ); + }); + it("Throws length error if series length mixmatch", function () { + const data = [1, 2, 3, 4] + const data2 = [1, 2, 3, 4, 5, 6] + const sf = new Series(data) + const sf2 = new Series(data2) + assert.throws(() => { sf.add(sf2) }, Error, "Row length mismatch. Length of other (6), must be the same as Ndframe (4)") + }) + }); + + describe("sub", function () { + it("Return Subtraction of series with another series", function () { + const data1 = [30, 40, 39, 1, 2, 1]; + const data2 = [1, 2, 3, 4, 5, 6]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual((sf1.sub(sf2)).values, [29, 38, 36, -3, -3, -5]); + }); + it("Return Subtraction of series with a single value (Broadcasting)", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + assert.deepEqual((sf.sub(1)).values, [0, 1, 2, 3, 4]); + }); + it("Throws type error on Subtraction of string type", function () { + const data = [1, 2, 3, 4]; + const data2 = ["A", "B", "C", "d"]; + const sf = new Series(data); + const sf2 = new Series(data2); + assert.throws( + () => { + sf.sub(sf2); + }, + Error, + "DtypeError: String data type does not support sub operation" + ); + }); + it("Throws length error if series length mixmatch", function () { + const data = [1, 2, 3, 4] + const data2 = [1, 2, 3, 4, 5, 6] + const sf = new Series(data) + const sf2 = new Series(data2) + assert.throws(() => { sf.sub(sf2) }, Error, "Row length mismatch. Length of other (6), must be the same as Ndframe (4)") + }) + }); + + describe("mul", function () { + it("Return multiplication of series with another series", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [1, 2, 3, 4]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual((sf1.mul(sf2)).values, [30, 80, 9, 20]); + }); + it("Return multiplication of series with a single value (Broadcasting)", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + assert.deepEqual((sf.mul(1)).values, [1, 2, 3, 4, 5]); + }); + it("Throws type error on multiplication of string type", function () { + const data = [1, 2, 3, 4] + const data2 = ["A", "B", "C", "d"] + const sf = new Series(data) + const sf2 = new Series(data2) + assert.throws(() => { sf.mul(sf2) }, Error, "DtypeError: String data type does not support mul operation") + }) + it("Throws length error if series length mixmatch", function () { + const data = [1, 2, 3, 4] + const data2 = [1, 2, 3, 4, 5, 6] + const sf = new Series(data) + const sf2 = new Series(data2) + assert.throws(() => { sf.mul(sf2) }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)") + }) + }); + + + describe("div", function () { + it("Return float division of series with another series", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [1, 2, 3, 4]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual((sf1.div(sf2)).values, [30, 20, 1, 1.25]); + }); + it("Return integer division of series with another series", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [1, 2, 3, 4]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual((sf1.div(sf2)).values, [30, 20, 1, 1.25]); + }); + it("Return division of series with a single value (Broadcasting)", function () { + const data = [10, 2, 3, 90]; + const sf = new Series(data); + assert.deepEqual((sf.div(2)).values, [5, 1, 1.5, 45]); + }); + it("Throws type error on division of string type", function () { + const data = [1, 2, 3, 4] + const data2 = ["A", "B", "C", "d"] + const sf = new Series(data) + const sf2 = new Series(data2) + assert.throws(() => { sf.div(sf2) }, Error, `DtypeError: String data type does not support div operation`) + }) + it("Throws length error if series length mixmatch", function () { + const data = [1, 2, 3, 4] + const data2 = [1, 2, 3, 4, 5, 6] + const sf = new Series(data) + const sf2 = new Series(data2) + assert.throws(() => { sf.div(sf2) }, Error, "ParamError: Row length mismatch. Length of other (6), must be the same as Ndframe (4)") + }) + }); + + describe("pow", function () { + it("Return Exponetial power of series with another series", function () { + const data1 = [2, 3, 4, 5]; + const data2 = [1, 2, 3, 0]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual((sf1.pow(sf2)).values, [2, 9, 64, 1]); + }); + it("Return Exponetial power of series with a single value (Broadcasting)", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + assert.deepEqual((sf.pow(2)).values, [1, 4, 9, 16, 25]); + }); + }); + + describe("mod", function () { + it("Return modulo of series with another float series", function () { + const data1 = [2, 30, 4, 5]; + const data2 = [1.1, 2.2, 3.3, 2.4]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + const expected = [ + 0.8999999999999999, + 1.3999999999999977, + 0.7000000000000002, + 0.20000000000000018 + ]; + assert.deepEqual((sf1.mod(sf2)).values, expected); + }); + it("Return modulo of series with another int series", function () { + const data1 = [2, 30, 4, 5]; + const data2 = [1, 2, 3, 1]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual((sf1.mod(sf2)).values, [0, 0, 1, 0]); + }); + it("Return modulo power of series with a single value (Broadcasting)", function () { + const data = [1, 2, 3, 4, 5]; + const sf = new Series(data); + assert.deepEqual((sf.mod(2)).values, [1, 0, 1, 0, 1]); + }); + }); + + describe("toString", function () { + it("Prints a series to the console", async function () { + const data = [1, 2, 3, 4, 5, 620, 30, 40, 39, 89, 78]; + const sf = new Series(data); + sf.print() + }); + it("Prints a series to the console", async function () { + const data = ["This is a long text group and I want it to print in full", + "This is a long text group and I want it to print in full"]; + const sf = new Series(data); + sf.print() + }); + }); + + describe("Empty Series", function () { + it("Can successfully create an empty Series from empty array", function () { + const data: any = []; + const sf = new Series(data); + assert.deepEqual(sf.shape, [0, 0]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + + it("Can successfully create an empty Series", function () { + const sf = new Series(); + assert.deepEqual(sf.shape, [0, 0]); + assert.deepEqual(sf.columns, []); + assert.deepEqual(sf.dtypes, []); + assert.deepEqual(sf.values, []); + }); + }); + + describe("mean", function () { + it("Computes the mean of elements in a int series", function () { + const data1 = [30, 40, 3, 5, NaN]; + const sf = new Series(data1); + assert.deepEqual(sf.mean(), 19.5); + }); + it("Computes the mean of elements in a int series", function () { + const data1 = [30, 40, 3, 5, NaN]; + const sf = new Series(data1); + assert.deepEqual(sf.mean(), 19.5); + }); + it("Computes the mean of elements in a float series", function () { + const data1 = [30.1, 40.2, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(sf.mean(), 19.625); + }); + it("Computes the mean of elements in a float series with NaN", function () { + const data1 = [30.1, 40.2, 3.1, 5.1, NaN]; + const sf = new Series(data1); + assert.deepEqual(sf.mean(), 19.625); + }); + it("Computes the mean of a boolean series", function () { + const data1 = [true, false, false, false, true, true, false, true]; + const sf = new Series(data1); + assert.deepEqual(sf.mean(), 0.5); + }); + it("Throws error if dtype is string", function () { + const data1 = ["boy", "girl", "Man"]; + const sf = new Series(data1); + assert.throws( + () => { + sf.mean(); + }, + Error, + "DtypeError: String data type does not support mean operation" + ); + }); + }); + + describe("median", function () { + it("Computes the median value of elements across int Series", function () { + const data1 = [30, 40, 3, 5]; + const sf = new Series(data1); + assert.deepEqual(sf.median(), 17.5); + }); + it("Computes the median value of elements across float Series", function () { + const data1 = [30.1, 40.2, 3.1, 5.1, NaN]; + const sf = new Series(data1); + assert.deepEqual(sf.median(), 17.6); + }); + }); + + describe("sum", function () { + it("Sum values of a Int Series", function () { + const data1 = [30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3]; + const sf = new Series(data1); + assert.deepEqual(sf.sum(), 131); + }); + it("Sum values of a Float Series", function () { + const data1 = [30.1, 3.1, 40.2, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(sf.sum(), 81.6); + }); + it("Sum values of a bool Series", function () { + const data1 = [true, true, false, false, false]; + const sf = new Series(data1); + assert.deepEqual(sf.sum(), 2); + }); + it("Sum values a Series with missing values", function () { + const data1 = [11, NaN, 2, 2]; + const sf = new Series(data1); + assert.deepEqual(sf.sum(), 15); + }); + }); + + describe("mode", function () { + it("Computes the multi-modal values of a Series", function () { + const data1 = [30, 40, 3, 5, 5, 5, 5, 5, 3, 3, 3, 21, 3]; + const sf = new Series(data1); + assert.deepEqual(sf.mode(), [5, 3]); + }); + it("Computes the modal value of a Series", function () { + const data1 = [30.1, 3.1, 40.2, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(sf.mode(), [3.1]); + }); + }); + + describe("min", function () { + it("Returns the single smallest elementin a Series", function () { + const data = [30, 40, 3, 5]; + const sf = new Series(data); + assert.deepEqual(sf.min(), 3); + }); + it("Computes the minimum of elements across an float Series", function () { + const data1 = [30.1, 40.2, 3.12, 5.1]; + const sf = new Series(data1, { dtypes: ["float32"] }); + assert.deepEqual(Number(sf.min().toFixed(2)), 3.12); + }); + }); + + describe("max", function () { + it("Computes the maximum of elements across dimensions of a Series", function () { + const data1 = [30, 40, 3, 5]; + const sf = new Series(data1); + assert.deepEqual(sf.max(), 40); + }); + it("Return sum of float values in a series", function () { + const data1 = [30.1, 40.21, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(Number(sf.max().toFixed(2)), 40.21); + }); + it("Throws error on addition of string Series", function () { + const data1 = ["boy", "gitl", "woman", "man"]; + const sf = new Series(data1); + assert.throws( + () => { + sf.max(); + }, + Error, + "DtypeError: String data type does not support max operation" + ); + }); + }); + + describe("count", function () { + it("Returns the count of non NaN values in a string Series", function () { + const data = ["boy", "gitl", "woman", NaN]; + const sf = new Series(data); + assert.deepEqual(sf.count(), 3); + }); + it("Returns the count of values in a string Series without NaN", function () { + const data = ["boy", "gitl", "woman", "Man"]; + const sf = new Series(data); + assert.deepEqual(sf.count(), 4); + }); + it("Returns the count of non NaN values in a int Series", function () { + const data = [20, 30, NaN, 2, NaN, 30, 21]; + const sf = new Series(data); + assert.deepEqual(sf.count(), 5); + }); + it("Returns the count of non NaN values in a float Series", function () { + const data = [20.1, 30.4, NaN, 2.1, NaN, 30.0, 21.3]; + const sf = new Series(data); + assert.deepEqual(sf.count(), 5); + }); + }); + + describe("std", function () { + it("Computes the standard of elements in a int series", function () { + const data1 = [30, 40, 3, 5]; + const sf = new Series(data1); + assert.deepEqual(sf.std(), 18.375708603116962); + }); + it("Computes the standard deviation of elements in a float series", function () { + const data1 = [30.1, 40.2, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(sf.std(), 18.412925713566906); + }); + it("Computes the standard deviation of elements in a float series with missing values", function () { + const data1 = [30, 40, 3, 5, undefined]; + const sf = new Series(data1); + assert.deepEqual(sf.std(), 18.375708603116962); + }); + }); + + describe("var", function () { + it("Computes the variance of elements in a int series", function () { + const data1 = [30, 40, 3, 5]; + const sf = new Series(data1); + assert.deepEqual(sf.var(), 337.6666666666667); + }); + it("Computes the variance of elements in a float series", function () { + const data1 = [30.1, 40.2, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(sf.var(), 339.03583333333336); + }); + it("Computes the variance of elements in a int series with missing values", function () { + const data1 = [30, undefined, 40, 3, 5]; + const sf = new Series(data1); + assert.deepEqual(sf.var(), 337.6666666666667); + }); + }); + + describe("round", function () { + it("Rounds elements in a Series to nearest whole number", function () { + const data1 = [30.21091, 40.190901, 3.564, 5.0212]; + const sf = new Series(data1); + assert.deepEqual((sf.round()).values, [30.2, 40.2, 3.6, 5]); + }); + it("Rounds elements in a Series to 1dp", function () { + const data1 = [30.21091, 40.190901, 3.564, 5.0212]; + const sf = new Series(data1); + assert.deepEqual((sf.round(1)).values, [30.2, 40.2, 3.6, 5.0]); + }); + it("Rounds elements in a Series to 2dp", function () { + const data1 = [30.2191, 40.190901, 3.564, 5.0212]; + const sf = new Series(data1); + assert.deepEqual((sf.round(2)).values, [30.22, 40.19, 3.56, 5.02]); + }); + + it("Rounds elements in a Series to 2dp inplace", function () { + const data1 = [30.2191, 40.190901, 3.564, 5.0212]; + const sf = new Series(data1); + sf.round(2, { inplace: true }) + assert.deepEqual(sf.values, [30.22, 40.19, 3.56, 5.02]); + }); + + it("Rounds elements in a Series with missing values to 2dp", function () { + const data1 = [30.2191, undefined, 3.564, NaN]; + const sf = new Series(data1); + sf.round(2, { inplace: true }) + assert.deepEqual(sf.values as number[], [30.22, undefined, 3.56, NaN]); + }); + + }); + + describe("maximum", function () { + it("Returns the maximum of two series", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [10, 41, 2, 0]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual(sf1.maximum(sf2).values, [30, 41, 3, 5]); + }); + it("Returns the maximum of series and Array", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [10, 41, 2, 0]; + const sf1 = new Series(data1); + assert.deepEqual(sf1.maximum([10, 41, 2, 0]).values, [30, 41, 3, 5]); + }); + it("Returns the maximum of series and scalar", function () { + const data1 = [30, 40, 3, 5]; + const sf1 = new Series(data1); + assert.deepEqual(sf1.maximum(10).values, [30, 40, 10, 10]); + }); + it("Throws error on checking maximum of incompatible Series", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [10, 41, 2]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.throws( + () => { + sf1.maximum(sf2); + }, + Error, + "ParamError: Row length mismatch. Length of other (3), must be the same as Ndframe (4)" + ); + }); + }); + + describe("minimum", function () { + it("Returns the minimum of two series", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [10, 41, 2, 0]; + const sf1 = new Series(data1); + const sf2 = new Series(data2); + assert.deepEqual(sf1.minimum(sf2).values, [10, 40, 2, 0]); + }); + it("Returns the minimum of series and array", function () { + const data1 = [30, 40, 3, 5]; + const data2 = [10, 41, 2, 0]; + const sf1 = new Series(data1); + assert.deepEqual(sf1.minimum(data2).values, [10, 40, 2, 0]); + }); + it("Returns the minimum of two series", function () { + const data1 = [30, 40, 3, 5]; + const sf1 = new Series(data1); + assert.deepEqual(sf1.minimum(10).values, [10, 10, 3, 5]); + }); + }); + + describe("isNa", function () { + it("Return a boolean same-sized object indicating if string Series contain NaN", function () { + const data1 = [NaN, undefined, "girl", "Man"]; + const sf = new Series(data1); + assert.deepEqual(sf.isNa().values, [true, true, false, false]); + }); + it("Return a boolean same-sized object indicating if float Series values are NaN", function () { + const data1 = [30.21091, NaN, 3.564, undefined]; + const sf = new Series(data1); + assert.deepEqual(sf.isNa().values, [false, true, false, true]); + }); + it("Return a boolean same-sized object indicating if int Series values are NaN", function () { + const data1 = [30, 40, 3, 5, null, undefined]; + const sf = new Series(data1); + assert.deepEqual(sf.isNa().values, [ + false, + false, + false, + false, + true, + true + ]); + }); + }); + + describe("fillNa", function () { + it("replace all NaN value with specified value", function () { + const data = [NaN, 1, 2, 33, 4, NaN, 5, 6, 7, 8]; + const sf = new Series(data); + const sfVal = [-999, 1, 2, 33, 4, -999, 5, 6, 7, 8]; + sf.fillNa(-999, { inplace: true }); + assert.deepEqual(sf.values, sfVal); + }); + it("replace all NaN value in string Series with specified value", function () { + const data = [NaN, "boy", null, "hey", "Man", undefined]; + const sf = new Series(data); + const sfVal = ["filled", "boy", "filled", "hey", "Man", "filled"]; + const sfFill = sf.fillNa("filled"); + assert.deepEqual((sfFill).values, sfVal); + }); + it("Data is in right format after filling", function () { + const data = [NaN, "boy", NaN, "hey", "Man", undefined]; + const sf = new Series(data); + const sfVal = ["filled", "boy", "filled", "hey", "Man", "filled"]; + const sfFill = sf.fillNa("filled"); + assert.deepEqual((sfFill).values, sfVal); + }); + }); + + describe("sortValues", function () { + it("Sort values in a Series in ascending order (not inplace)", function () { + const sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); + const result = [0, 1, 2, 4, 4, 20, 30, 57, 89]; + const sortedSf = sf.sortValues(); + assert.deepEqual((sortedSf).values, result); + + }); + it("confirms that sortValues in ascending order does not happen inplace", function () { + const sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); + const result = [0, 1, 2, 4, 4, 20, 30, 57, 89]; + const expectedIndex = [7, 2, 3, 8, 4, 0, 1, 5, 6]; + sf.sortValues({ ascending: true, inplace: true }); + assert.deepEqual(sf.values, result); + assert.deepEqual(sf.index, expectedIndex); + }); + it("Sort values in a Series in Descending order", function () { + const sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); + const result = [89, 57, 30, 20, 4, 4, 2, 1, 0]; + const sortedSf = sf.sortValues({ ascending: false }); + assert.deepEqual((sortedSf).values, result); + }); + it("confirms that sortValues in descending order happens inplace", function () { + const sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); + const result = [89, 57, 30, 20, 4, 4, 2, 1, 0]; + sf.sortValues({ ascending: false, inplace: true }); + assert.deepEqual(sf.values, result); + }); + it("Confirms that series index is sorted in ascending order (not in inplace)", function () { + const sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); + const result = [7, 2, 3, 8, 4, 0, 1, 5, 6]; + const sortedSf = sf.sortValues() + assert.deepEqual(sortedSf.index, result); + }); + it("Confirms that series index is sorted in descending order (not in inplace)", function () { + const sf = new Series([20, 30, 1, 2, 4, 57, 89, 0, 4]); + const result = [6, 5, 1, 0, 4, 8, 3, 2, 7]; + const sortedSf = sf.sortValues({ ascending: false }) + assert.deepEqual(sortedSf.index, result); + }); + it("Sort string values in a Series", function () { + const sf = new Series(["boy", "zebra", "girl", "man"]); + const result = ["boy", "girl", "man", "zebra"]; + const sortedSf = sf.sortValues({ ascending: false }) + assert.deepEqual(sortedSf.values, result); + }); + it("Index is retained after sort (ascending=true)", function () { + let index = ["apple", "banana", "orange", "grape"]; + let value = [3, 6, 2, 9]; + + let sf = new Series(value, { index }); + sf.sortValues().print(); + const expectedValues = [2, 3, 6, 9]; + const expectedIndex = ["orange", "apple", "banana", "grape"]; + const sortedSf = sf.sortValues() + assert.deepEqual(sortedSf.values, expectedValues); + assert.deepEqual(sortedSf.index, expectedIndex); + }); + it("Index is retained after sort (ascending=false)", function () { + let index = ["apple", "banana", "orange", "grape"]; + let value = [3, 6, 2, 9]; + + let sf = new Series(value, { index }); + sf.sortValues().print(); + const expectedValues = [9, 6, 3, 2]; + const expectedIndex = ["grape", "banana", "apple", "orange"]; + const sortedSf = sf.sortValues({ ascending: false }) + assert.deepEqual(sortedSf.values, expectedValues); + assert.deepEqual(sortedSf.index, expectedIndex); + }); + + it("Index is retained after inplace sort (ascending=false)", function () { + let index = ["apple", "banana", "orange", "grape"]; + let value = [3, 6, 2, 9]; + + let sf = new Series(value, { index }); + sf.sortValues().print(); + const expectedValues = [9, 6, 3, 2]; + const expectedIndex = ["grape", "banana", "apple", "orange"]; + sf.sortValues({ ascending: false, inplace: true }); + assert.deepEqual(sf.values, expectedValues); + assert.deepEqual(sf.index, expectedIndex); + }); + }); + + describe("describe", function () { + it("Computes the descriptive statistics on an int Series", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1) + assert.deepEqual(sf.describe().round().values, [ + 7, + 27, + 17.4, + 10, + 23, + 56, + 302 + ]); + }); + it("Computes the descriptive statistics on a float Series", function () { + const data1 = [30.1, 40.2, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(sf.describe().round().values, [ + 4, + 19.6, + 18.4, + 3.1, + 17.6, + 40.2, + 339 + ]); + }); + it("Computes the descriptive statistics on a float Series", function () { + const data1 = [30.1, 40.2, 3.1, 5.1]; + const sf = new Series(data1); + assert.deepEqual(sf.describe().index, [ + "count", + "mean", + "std", + "min", + "median", + "max", + "variance" + ]); + }); + }); + + describe("resetIndex", function () { + it("resets the index of a Series", function () { + const data = [ + { alpha: "A", count: 1 }, + { alpha: "B", count: 2 }, + { alpha: "C", count: 3 } + ]; + const df = new Series(data, { index: ["one", "two", "three"] }); + const dfReset = df.resetIndex() + assert.deepEqual(dfReset.index, [0, 1, 2]); + }); + it("Reset the index of a Series created from an Array", function () { + const data = [1, 2, 3, 4, 5, 6]; + const df = new Series(data, { index: ["one", "two", "three", "four", "five", "six"] }); + const dfNew = df.resetIndex() + assert.deepEqual(dfNew.index, [0, 1, 2, 3, 4, 5]); + }); + it("checks that the original series changed after reseting new index inplace", function () { + const data = [ + { index: "A", count: 1 }, + { index: "B", count: 2 }, + { index: "C", count: 3 } + ]; + const df = new Series(data, { index: ["one", "two", "three"] }); + df.resetIndex({ inplace: true }); + assert.deepEqual(df.index, [0, 1, 2]); + }); + }); + + describe("setIndex", function () { + it("sets the index of an Series", function () { + const data = [ + { alpha: "A", count: 1 }, + { alpha: "B", count: 2 }, + { alpha: "C", count: 3 } + ]; + const df = new Series(data); + const dfNew = df.setIndex(["one", "two", "three"]) + assert.deepEqual(dfNew.index, ["one", "two", "three"]); + assert.notDeepEqual(df.index, dfNew.index); + }); + it("checks that the original series is not modified after setting new index not-inplace", function () { + const data = [ + { alpha: "A", count: 1 }, + { alpha: "B", count: 2 }, + { alpha: "C", count: 3 } + ]; + const df = new Series(data); + const dfNew = df.setIndex(["one", "two", "three"]) + assert.notDeepEqual(df.index, dfNew.index); + }); + it("sets the index of an Series inplace", function () { + const data = [12, 2, 20, 50]; + const df = new Series(data); + df.setIndex(["one", "two", "three", "four"], { inplace: true }); + assert.deepEqual(df.index, ["one", "two", "three", "four"]); + }); + it("Throws index not found error", function () { + const data = [12, 2, 20, 50]; + const df = new Series(data); + assert.throws(() => { + // @ts-ignore: + df.setIndex() + }, Error, + "Param Error: Must specify index array" + ) + }); + }); + + describe("Map", function () { + it("map series element to object keys", function () { + const sf = new Series([1, 2, 3, 4]); + const map = { 1: "ok", 2: "okie", 3: "frit", 4: "gop" }; + const rslt = ["ok", "okie", "frit", "gop"]; + assert.deepEqual((sf.map(map)).values, rslt); + }); + it("map series element to object keys inplace", function () { + const sf = new Series([1, 2, 3, 4]); + const map = { 1: "ok", 2: "okie", 3: "frit", 4: "gop" }; + const rslt = ["ok", "okie", "frit", "gop"]; + sf.map(map, { inplace: true }) + assert.deepEqual(sf.values, rslt); + }); + it("map series element to incomplete object keys", function () { + const sf = new Series([1, 2, 3, 4]); + const map = { 1: "ok", 2: "okie", 4: "gop" }; + const rslt = ["ok", "okie", 3, "gop"]; + sf.map(map, { inplace: true }) + assert.deepEqual(sf.values, rslt); + }); + it("map series element to a function statement", function () { + const sf = new Series([1, 2, 3, 4]); + const func_map = (x: any) => { + return x + 1; + }; + const rslt = [2, 3, 4, 5]; + assert.deepEqual((sf.map(func_map)).values, rslt); + }); + + it("map series element to a function statement inplace", function () { + const sf = new Series([1, 2, 3, 4]); + const func_map = (x: any) => { + return x + 1; + }; + const rslt = [2, 3, 4, 5]; + sf.map(func_map, { inplace: true }) + assert.deepEqual(sf.values, rslt); + }); + + it("map passes along the index", function () { + const sf = new Series([1, 2, 3, 4]); + const func_map = (x: any, i: any) => { + return x + i; + }; + const rslt = [1, 3, 5, 7]; + sf.map(func_map, { inplace: true }); + assert.deepEqual(sf.values, rslt); + }); + }); + + describe("Apply", function () { + it("apply a function to a series element", function () { + const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8]); + const applyFunc = (x: any) => { + return x + x; + }; + + const rslt = [2, 4, 6, 8, 10, 12, 14, 16]; + assert.deepEqual((sf.apply(applyFunc)).values, rslt); + }); + + it("apply a function to a series element inplace", function () { + const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8]); + const applyFunc = (x: any) => { + return x + x; + }; + + const rslt = [2, 4, 6, 8, 10, 12, 14, 16]; + sf.apply(applyFunc, { inplace: true }) + assert.deepEqual(sf.values, rslt); + }); + }); + + describe("unique", function () { + it("returns the unique values in a Series of type int", function () { + const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5]); + const expected = [1, 2, 3, 4, 5, 6, 7, 8, 22]; + assert.deepEqual(sf.unique().values, expected); + }); + it("returns the unique values in a Series of type string", function () { + const sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); + const expected = ["a", "b", "c", "d", "e"]; + assert.deepEqual(sf.unique().values, expected); + }); + it("returns the unique values in a Series of type string", function () { + const sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); + const expected = ["a", "b", "c", "d", "e"]; + assert.deepEqual(sf.unique().values, expected); + }); + }); + + describe("nUnique", function () { + it("returns the number of unique values in a Series of type string", function () { + const sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); + assert.deepEqual(sf.nUnique(), 5); + }); + it("returns the number of unique values in a Series of type int32", function () { + const sf = new Series([1, 2, 3, 4, 3, 4, 3, 50, 4, 4, 4, 1]); + assert.deepEqual(sf.nUnique(), 5); + }); + }); + + describe("valueCounts", function () { + it("returns the unique values and their counts in a Series of type int", function () { + const sf = new Series([1, 2, 3, 4, 5, 6, 7, 8, 1, 1, 22, 8, 5, 5, 5]); + const expectedIndex = [1, 2, 3, 4, 5, 6, 7, 8, 22]; + const expectedVals = [3, 1, 1, 1, 4, 1, 1, 2, 1]; + assert.deepEqual(sf.valueCounts().values, expectedVals); + assert.deepEqual(sf.valueCounts().index, expectedIndex); + }); + it("returns the unique values and their counts in a Series of type string", function () { + const sf = new Series(["a", "a", "b", "c", "c", "d", "e", "d", "d", "e"]); + const expectedVals = [2, 1, 2, 3, 2]; + const expectedIndex = ["a", "b", "c", "d", "e"]; + assert.deepEqual(sf.valueCounts().values, expectedVals); + assert.deepEqual(sf.valueCounts().index, expectedIndex); + }); + it("returns the unique values and their counts in a Series of type boolean", function () { + const sf = new Series([true, false, false, true, true]); + const expectedVals = [3, 2]; + const expectedIndex = ["true", "false"]; + assert.deepEqual(sf.valueCounts().values, expectedVals); + assert.deepEqual(sf.valueCounts().index, expectedIndex); + }); + }); + + describe("abs", function () { + it("Returns the absolute values in Series", function () { + const data1 = [-10, 45, 56, -25, 23, -20, 10]; + const sf = new Series(data1); + assert.deepEqual((sf.abs()).values, [10, 45, 56, 25, 23, 20, 10]); + }); + it("Computes the descriptive statistics on a float Series", function () { + const data1 = [-30.1, -40.2, -3.1, -5.1]; + const sf = new Series(data1); + assert.deepEqual((sf.abs()).values, [30.1, 40.2, 3.1, 5.1]); + }); + }); + + describe("cumSum", function () { + it("Return cumulative sum over a Series", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + assert.deepEqual((sf.cumSum()).values, [10, 55, 111, 136, 159, 179, 189]); + }); + it("Return cumulative sum over a Series inplace", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + sf.cumSum({ inplace: true }); + assert.deepEqual(sf.values, [10, 55, 111, 136, 159, 179, 189]); + }); + }); + + describe("cumMax", function () { + it("Return cumulative maximum over a Series", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + assert.deepEqual((sf.cumMax()).values, [10, 45, 56, 56, 56, 56, 56]); + }); + it("Return cumulative maximum over a Series inplace", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + sf.cumMax({ inplace: true }); + assert.deepEqual(sf.values, [10, 45, 56, 56, 56, 56, 56]); + }); + }); + + describe("cumMin", function () { + it("Return cumulative minimum over a Series", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + assert.deepEqual((sf.cumMin()).values, [10, 10, 10, 10, 10, 10, 10]); + }); + }); + + describe("cumProd", function () { + it("Return cumulative product over a Series", function () { + const data1 = [1, 2, 10, 3, 12, 14, 1]; + const sf = new Series(data1); + const rslt = [1, 2, 20, 60, 720, 10080, 10080]; + assert.deepEqual((sf.cumProd()).values, rslt); + }); + }); + + describe("lt", function () { + it("Return Less than of series and other series (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const data2 = [100, 450, 590, 5, 25, 2, 0]; + + const sf = new Series(data1); + const sf2 = new Series(data2); + const expected = [true, true, true, false, true, false, false]; + assert.deepEqual(sf.lt(sf2).values, expected); + }); + + it("Return Less than of series scalar (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + const expected = [true, false, false, true, true, true, true]; + assert.deepEqual(sf.lt(30).values, expected); + }); + + it("Correct index is returned after operation", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1, { index: ["one", "two", "three", "four", "five"] }); + + const expected = ["one", "two", "three", "four", "five"]; + assert.deepEqual(sf.lt(data2).index, expected); + }); + }); + + describe("gt", function () { + it("Return Greater than of series and other series (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const data2 = [100, 450, 590, 5, 25, 2, 0]; + + const sf = new Series(data1); + const sf2 = new Series(data2); + const expected = [false, false, false, true, false, true, true]; + assert.deepEqual(sf.gt(sf2).values, expected); + }); + + it("Return Greater than of series scalar (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + const expected = [false, true, true, false, false, false, false]; + assert.deepEqual(sf.gt(30).values, expected); + }); + + it("Correct index is returned after operation", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1, { index: ["one", "two", "three", "four", "five"] }); + + const expected = ["one", "two", "three", "four", "five"]; + assert.deepEqual(sf.and(data2).index, expected); + }); + }); + + describe("le", function () { + it("Return Less than or Equal to of series and other series (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const data2 = [100, 450, 590, 5, 25, 2, 0]; + + const sf = new Series(data1); + const sf2 = new Series(data2); + const expected = [true, true, true, false, true, false, false]; + assert.deepEqual(sf.le(sf2).values, expected); + }); + + it("Return Less than or Equal to of series scalar (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + const expected = [true, false, false, true, true, true, true]; + assert.deepEqual(sf.le(30).values, expected); + }); + }); + + describe("ge", function () { + it("Return Greater than or Equal to of series and other series (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const data2 = [100, 450, 56, 5, 25, 20, 0]; + + const sf = new Series(data1); + const sf2 = new Series(data2); + const expected = [false, false, true, true, false, true, true]; + assert.deepEqual(sf.ge(sf2).values, expected); + }); + + it("Return Greater than or Equal to of series scalar (element-wise)", function () { + const data1 = [30, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + const expected = [true, true, true, false, false, false, false]; + assert.deepEqual(sf.ge(30).values, expected); + }); + }); + + describe("ne", function () { + it("Return Not Equal to of series and other series (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const data2 = [10, 450, 56, 5, 25, 2, 0]; + + const sf = new Series(data1); + const sf2 = new Series(data2); + const expected = [false, true, false, true, true, true, true]; + assert.deepEqual(sf.ne(sf2).values, expected); + }); + + it("Return Not Equal to of series scalar (element-wise)", function () { + const data1 = [10, 30, 56, 30, 23, 20, 10]; + const sf = new Series(data1); + const expected = [true, false, true, false, true, true, true]; + assert.deepEqual(sf.ne(30).values, expected); + }); + }); + + describe("eq", function () { + it("Return Equal to of series and other series (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const data2 = [100, 450, 590, 25, 25, 2, 0]; + + const sf = new Series(data1); + const sf2 = new Series(data2); + const expected = [false, false, false, true, false, false, false]; + assert.deepEqual(sf.eq(sf2).values, expected); + }); + + it("Return Equal to of series scalar (element-wise)", function () { + const data1 = [10, 45, 56, 25, 23, 20, 30]; + const sf = new Series(data1); + const expected = [false, false, false, false, false, false, true]; + assert.deepEqual(sf.eq(30).values, expected); + }); + }); + + describe("replace", function () { + it("Replace values with new value", function () { + const data1 = [10, 45, 56, 25, 23, 20, 10]; + const sf = new Series(data1); + const expected = [-50, 45, 56, 25, 23, 20, -50]; + const dfRep = sf.replace(10, -50) + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace values given in replace param with value (String type)", function () { + const data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; + const sf = new Series(data1); + const expected = ["boy", "boy", "boy", "B", "B", "C", "C", "D"]; + sf.replace("A", "boy", { inplace: true }); + assert.deepEqual(sf.values, expected); + }); + + it("Replace values given in replace param with value (boolean type)", function () { + const data1 = [true, true, false, false]; + const sf = new Series(data1); + const expected = [false, false, false, false]; + sf.replace(true, false, { inplace: true }); + assert.deepEqual(sf.values, expected); + }); + + it("Replace oldValue supports falsy numbers (0)", function () { + const data1 = [0, 45, 56, 25, 23, 20, 0]; + const sf = new Series(data1); + const expected = [1, 45, 56, 25, 23, 20, 1]; + const dfRep = sf.replace(0, 1) + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace oldValue does not support NaN", function () { + const data1 = [NaN, 45, 56, 25, 23, 20, NaN]; + const sf = new Series(data1); + assert.throws(() => sf.replace(NaN, 1), Error, "Params Error: Param 'oldValue' does not support NaN. Use Series.fillNa() instead."); + + }); + + it("Replace oldValue supports falsy strings", function () { + const data1 = ['', 'bar', 'baz']; + const sf = new Series(data1); + const expected = ['foo', 'bar', 'baz']; + const dfRep = sf.replace('', 'foo') + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace oldValue supports falsy booleans", function () { + const data1 = [true, false, true, false]; + const sf = new Series(data1); + const expected = [true, true, true, true]; + const dfRep = sf.replace(false, true) + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace newValue supports falsy numbers (0)", function () { + const data1 = [1, 45, 56, 25, 23, 20, 1]; + const sf = new Series(data1); + const expected = [0, 45, 56, 25, 23, 20, 0]; + const dfRep = sf.replace(1, 0) + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace newValue supports falsy numbers (NaN)", function () { + const data1 = [1, 45, 56, 25, 23, 20, 1]; + const sf = new Series(data1); + const expected = [NaN, 45, 56, 25, 23, 20, NaN]; + const dfRep = sf.replace(1, NaN) + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace newValue supports falsy strings", function () { + const data1 = ['foo', 'bar', 'baz']; + const sf = new Series(data1); + const expected = ['', 'bar', 'baz']; + const dfRep = sf.replace('foo', '') + assert.deepEqual(dfRep.values, expected); + }); + + it("Replace newValue supports falsy booleans", function () { + const data1 = [true, false, true, false]; + const sf = new Series(data1); + const expected = [false, false, false, false]; + const dfRep = sf.replace(true, false) + assert.deepEqual(dfRep.values, expected); + }); + + // it("Throw error on wrong param passed", function () { + // const data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; + // const sf = new Series(data1); + // assert.throws( + // () => { + // sf.replace(null, "boy", { inplace: true }); + // }, + // Error, + // "Params Error: Must specify param 'oldValue' to replace" + // ); + // }); + }); + + describe("dropDuplicates", function () { + it("Return Series with duplicate values removed (Default, first values kept)", function () { + const data1 = [10, 45, 56, 10, 23, 20, 10, 10]; + const sf = new Series(data1); + const expected = [10, 45, 56, 23, 20]; + const expectedIndex = [0, 1, 2, 4, 5]; + const df_drop = sf.dropDuplicates() + assert.deepEqual(df_drop.values, expected); + assert.deepEqual(df_drop.index, expectedIndex); + }); + + it("Return Series with duplicate values removed (last values kept)", function () { + const data1 = [10, 45, 56, 10, 23, 20, 10, 10]; + const sf = new Series(data1); + const expected = [45, 56, 23, 20, 10]; + const expectedIndex = [1, 2, 4, 5, 7]; + const df_drop = sf.dropDuplicates({ keep: "last" }) + assert.deepEqual(df_drop.values, expected); + assert.deepEqual(df_drop.index, expectedIndex); + }); + + it("Return Series with duplicate values removed (String)", function () { + const data1 = ["A", "A", "A", "B", "B", "C", "C", "D"]; + const sf = new Series(data1); + const expected = ["A", "B", "C", "D"]; + const expectedIndex = [0, 3, 5, 7]; + sf.dropDuplicates({ keep: "first", inplace: true }); + assert.deepEqual(sf.values, expected); + assert.deepEqual(sf.index, expectedIndex); + }); + }); + + describe("dropNa", function () { + it("Return a new Series with missing values removed (Int)", function () { + const data1 = [10, 45, undefined, 10, 23, 20, undefined, 10]; + const sf = new Series(data1); + const expected = [10, 45, 10, 23, 20, 10]; + const expectedIndex = [0, 1, 3, 4, 5, 7]; + const sfDrop = sf.dropNa() + assert.deepEqual(sfDrop.values, expected); + assert.deepEqual(sfDrop.index, expectedIndex); + assert.deepEqual(sfDrop.shape, [6, 1]); + }); + + it("Return a new Series with missing values removed (String)", function () { + const data1 = ["A", NaN, "A", "B", "B", NaN, "C", undefined]; + const sf = new Series(data1); + const expected = ["A", "A", "B", "B", "C"]; + const expectedIndex = [0, 2, 3, 4, 6]; + + sf.dropNa({ inplace: true }) + assert.deepEqual(sf.values, expected); + assert.deepEqual(sf.index, expectedIndex); + assert.deepEqual(sf.shape, [5, 1]); + }); + }); + + describe("argSort", function () { + it("Return the integer indices that would sort the Series values", function () { + const data1 = [10, 45, 20, 10, 23, 20, 30, 11]; + const sf = new Series(data1); + const expected = [3, 0, 7, 5, 2, 4, 6, 1]; + const sf_sort = sf.argSort(); + assert.deepEqual(sf_sort.values, expected); + }); + + it("Return the integer indices that would sort the Series values", function () { + const data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; + const sf = new Series(data1); + const expected = [6, 4, 5, 7, 0, 3, 1, 2]; + const sf_sort = sf.argSort({ ascending: false }); + assert.deepEqual(sf_sort.values, expected); + }); + }); + + describe("argMax", function () { + it("Return int position of the largest value in the Series.", function () { + const data1 = [10, 45, 20, 10, 23, 20, 30, 11]; + const sf = new Series(data1); + const expected = 1; + const argMax = sf.argMax(); + assert.deepEqual(argMax, expected); + }); + + it("Return int position of the largest value in the Float Series.", function () { + const data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; + const sf = new Series(data1); + const expected = 6; + const argMax = sf.argMax(); + assert.deepEqual(argMax, expected); + }); + }); + + describe("argMin", function () { + it("Return int position of the smallest value in the Series", function () { + const data1 = [10, 45, 20, 122, 23, 20, 30, 11]; + const sf = new Series(data1); + const expected = 0; + const argMin = sf.argMin(); + assert.deepEqual(argMin, expected); + }); + + it("Return int position of the smallest value in a Float Series", function () { + const data1 = [10.22, 4.5, 2.0, 10, 23.23, 20.1, 30, 11]; + const sf = new Series(data1); + const expected = 2; + const argMin = sf.argMin(); + assert.deepEqual(argMin, expected); + }); + }); + + describe("Str", function () { + it("Converts all characters to lowercase inplace", function () { + const data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; + const res = ["lower", "capitals", "this is a sentence", "swapcase"]; + const sf = new Series(data); + sf.str.toLowerCase({ inplace: true }) + assert.deepEqual(sf.values, res); + }); + it("Converts all characters to lowercase", function () { + const data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; + const res = ["lower", "capitals", "this is a sentence", "swapcase"]; + const sf = new Series(data); + assert.deepEqual((sf.str.toLowerCase()).values, res); + }); + it("Converts all characters to capital case.", function () { + const data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; + const res = ["Lower", "Capitals", "This is a sentence", "Swapcase"]; + const sf = new Series(data); + assert.deepEqual((sf.str.capitalize()).values, res); + }); + + it("Returns the character at the specified index (position)", function () { + const data = ["lower", "CAPITALS", "this is a sentence", "SwApCaSe"]; + const res = ["w", "P", "i", "A"]; + const sf = new Series(data); + assert.deepEqual((sf.str.charAt(2)).values, res); + }); + + it("Throws error on concat of numeric series", function () { + const data = [1, 2, 3, 4, 5, 6]; + const sf = new Series(data); + assert.throws( + () => { + sf.str.concat("20", 1); + }, + Error, + "Cannot call accessor str on non-string type" + ); + + }); + }); + + describe("dt", function () { + it("check month generated", function () { + const data = ["02Sep2019", "03Dec2019", "04Jan2019"]; + const sf = new Series(data); + const expected = [8, 11, 0]; + assert.deepEqual(sf.dt.month().values, expected); + }); + + it("check month Name generated", function () { + const data = ["06-30-2019", "07-29-2019", "08-28-2019"]; + const sf = new Series(data); + const expected = ["June", "July", "August"]; + assert.deepEqual(sf.dt.monthName().values, expected); + }); + + it("check days of the weeks generated", function () { + const data = ["06-30-2019", "07-29-2019", "08-28-2019"]; + const sf = new Series(data); + const expected = ["Sunday", "Monday", "Wednesday"]; + assert.deepEqual(sf.dt.dayOfWeekName().values, expected); + }); + + it("check day of the month generated", function () { + const data = ["06-30-2019", "07-29-2019", "08-28-2019"]; + const sf = new Series(data); + const expected = [30, 29, 28]; + assert.deepEqual(sf.dt.dayOfMonth().values, expected); + }); + }); + + describe("astype", function () { + it("set type of float column to int", function () { + const data = [-20.1, 30, 47.3, -20]; + const ndframe = new Series(data); + const df = ndframe.asType("int32") + + assert.deepEqual(df.dtypes[0], "int32"); + assert.deepEqual(df.values, [-20, 30, 47, -20]); + }); + it("set type of int column to float", function () { + const data = [34, -4, 5, 6]; + const ndframe = new Series(data); + const df = ndframe.asType("float32") + assert.deepEqual(df.dtypes[0], "float32"); + assert.deepEqual(df.values, [34, -4, 5, 6]); + }); + it("set type of string column to int", function () { + const data = ["20.1", "21", "23.4", "50.78"]; + const ndframe = new Series(data); + const df = ndframe.asType("int32") + + assert.deepEqual(df.dtypes[0], "int32"); + assert.deepEqual(df.values, [20, 21, 23, 50]); + }); + it("set type of string column to float", function () { + const data = ["20.1", "21", "23.4", "50.78"]; + const ndframe = new Series(data); + const df = ndframe.asType("float32") + + assert.deepEqual(df.dtypes[0], "float32"); + assert.deepEqual(df.values, [20.1, 21, 23.4, 50.78]); + }); + it("set type of float column to string", function () { + const data = [-20.1, 30, 47.3, -20]; + const ndframe = new Series(data); + const df = ndframe.asType("string") + assert.deepEqual(df.dtypes[0], "string"); + assert.deepEqual(df.values, ["-20.1", "30", "47.3", "-20"]); + }); + it("set type of int column to string", function () { + const data = [34, -4, 5, 6]; + const ndframe = new Series(data); + const df = ndframe.asType("string") + assert.deepEqual(df.dtypes[0], "string"); + assert.deepEqual(df.values, ["34", "-4", "5", "6"]); + }); + it("set type of int column to string inplace", function () { + const data = [34, -4, 5, 6]; + const ndframe = new Series(data); + ndframe.asType("string", { inplace: true }); + assert.deepEqual(ndframe.dtypes[0], "string"); + assert.deepEqual(ndframe.values, ["34", "-4", "5", "6"]); + }); + }); + + describe("append", function () { + it("Add a new single value to the end of a Series inplace", function () { + const data = [1, 2, 3, 4, "a", "b", "c"]; + const sf = new Series(data); + const expected_val = [1, 2, 3, 4, "a", "b", "c", "d"]; + sf.append("d", 7, { inplace: true }); + assert.deepEqual(sf.values, expected_val); + }); + it("Add a new array of values to the end of a Series inplace", function () { + const data = [1, 2, 3, 4]; + const to_add = ["a", "b", "c"]; + const index = [4, 5, 6]; + const sf = new Series(data); + const expected_val = [1, 2, 3, 4, "a", "b", "c"]; + sf.append(to_add, index, { inplace: true }); + assert.deepEqual(sf.values, expected_val); + }); + it("Add a Series to the end of another Series inplace", function () { + const sf1 = new Series([1, 2, 3, 4]); + const sf2 = new Series(["a", "b", "c"]); + const index = [4, 5, 6]; + const expected_val = [1, 2, 3, 4, "a", "b", "c"]; + sf1.append(sf2, index, { inplace: true }); + assert.deepEqual(sf1.values, expected_val); + }); + it("Add a new single value to the end of a Series", function () { + const data = [1, 2, 3, 4, "a", "b", "c"]; + const sf = new Series(data); + const expected_val = [1, 2, 3, 4, "a", "b", "c", "d"]; + const sf2 = sf.append("d", 7) + assert.deepEqual(sf2.values, expected_val); + }); + it("Add a new array of values to the end of a Series", function () { + const data = [1, 2, 3, 4]; + const to_add = ["a", "b", "c"]; + const index = [4, 5, 6]; + const sf = new Series(data); + const expected_val = [1, 2, 3, 4, "a", "b", "c"]; + const sf2 = sf.append(to_add, index); + assert.deepEqual(sf2.values, expected_val); + }); + it("Add a Series to the end of another Series", function () { + const sf1 = new Series([1, 2, 3, 4]); + const sf2 = new Series(["a", "b", "c"]); + const index = [4, 5, 6]; + const expected_val = [1, 2, 3, 4, "a", "b", "c"]; + const sf3 = sf1.append(sf2, index); + assert.deepEqual(sf3.values, expected_val); + }); + it("Confirm index Change after append", function () { + const sf1 = new Series([1, 2, 3, 4]); + const sf2 = new Series(["a", "b", "c"]); + const index = [4, 5, 6]; + const sf3 = sf1.append(sf2, index); + assert.deepEqual(sf3.index, [0, 1, 2, 3, 4, 5, 6]); + }); + it("Confirm index Change after append inplace", function () { + const sf1 = new Series([1, 2, 3, 4]); + const sf2 = new Series(["a", "b", "c"]); + const index = [4, 5, 6]; + sf1.append(sf2, index, { inplace: true }); + assert.deepEqual(sf1.index, [0, 1, 2, 3, 4, 5, 6]); + }); + it("Can append a value of zero", function() { + const data = [1, 2, 3, 4, "a", "b", "c"]; + const sf = new Series(data); + const expected_val = [1, 2, 3, 4, "a", "b", "c", 0]; + sf.append(0, 7, { inplace: true }); + assert.deepEqual(sf.values, expected_val); + }) + }); + + describe("and", function () { + it("Return logical AND of series and other series (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1); + const sf2 = new Series(data2); + + const expected = [true, false, true, false, false]; + assert.deepEqual(sf.and(sf2).values, expected); + }); + + it("Return logical AND of series and other scalar", function () { + const data1 = [true, true, true, false, false]; + const sf = new Series(data1); + + const expected = [true, true, true, false, false]; + assert.deepEqual(sf.and(true).values, expected); + }); + + it("Return logical AND of series and other array (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1); + + const expected = [true, false, true, false, false]; + assert.deepEqual(sf.and(data2).values, expected); + }); + + it("Chaining works for logical AND of series and other array (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const data3 = [true, false, false, true, false]; + + const sf = new Series(data1); + const expected = [true, false, false, false, false]; + assert.deepEqual(sf.and(data2).and(data3).values, expected); + }); + + it("Chaining works for logical AND and OR combined", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const data3 = [true, false, false, true, false]; + + const sf = new Series(data1); + const expected = [true, false, true, true, false]; + assert.deepEqual(sf.and(data2).or(data3).values, expected); + }); + }); + + describe("or", function () { + it("Return logical OR of series and other series (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1); + const sf2 = new Series(data2); + + const expected = [true, true, true, true, false]; + assert.deepEqual(sf.or(sf2).values, expected); + }); + + it("Return logical OR of series and other scalar", function () { + const data1 = [true, true, true, false, false]; + const sf = new Series(data1); + + const expected = [true, true, true, true, true]; + assert.deepEqual(sf.or(true).values, expected); + }); + + it("Return logical OR of series and other array (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1); + + const expected = [true, true, true, true, false]; + assert.deepEqual(sf.or(data2).values, expected); + }); + }); + + describe("and", function () { + it("Return logical AND of series and other series (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1); + const sf2 = new Series(data2); + + const expected = [true, false, true, false, false]; + assert.deepEqual(sf.and(sf2).values, expected); + }); + + it("Return logical AND of series and other scalar", function () { + const data1 = [true, true, true, false, false]; + const sf = new Series(data1); + + const expected = [true, true, true, false, false]; + assert.deepEqual(sf.and(true).values, expected); + }); + + it("Return logical AND of series and other array (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1); + + const expected = [true, false, true, false, false]; + assert.deepEqual(sf.and(data2).values, expected); + }); + + it("Chaining works for logical AND of series and other array (element-wise)", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const data3 = [true, false, false, true, false]; + + const sf = new Series(data1); + const expected = [true, false, false, false, false]; + assert.deepEqual(sf.and(data2).and(data3).values, expected); + }); + + it("Chaining works for logical AND and OR combined", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const data3 = [true, false, false, true, false]; + + const sf = new Series(data1); + const expected = [true, false, true, true, false]; + assert.deepEqual(sf.and(data2).or(data3).values, expected); + }); + + it("Correct index is returned after operation", function () { + const data1 = [true, true, true, false, false]; + const data2 = [true, false, true, true, false]; + const sf = new Series(data1, { index: ["one", "two", "three", "four", "five"] }); + + const expected = ["one", "two", "three", "four", "five"]; + assert.deepEqual(sf.and(data2).index, expected); + }); + }); + + describe("iat", function () { + it("iat works on Series", function () { + const data = [1, 2, 3, 4]; + const index = ["a", "b", "c", "d"]; + const df = new Series(data, { index }); + assert.equal(df.iat(0), 1); + assert.equal(df.iat(1), 2); + assert.equal(df.iat(2), 3); + }); + it("iat can return undefined", function () { + const data = [1, undefined, null, NaN]; + const df = new Series(data); + assert.equal(df.iat(1), undefined); + assert.equal(df.iat(2), null); + /* @ts-ignore */ + assert.equal(isNaN(df.iat(3)), true); + }); + it("throws error on string indices", function () { + const data = [1, 2, 3, 4]; + const index = ["a", "b", "c", "d"]; + const df = new Series(data, { index }); + /* @ts-ignore */ + assert.throws(function () { df.iat("A"); }, Error, "ParamError: row index must be an integer. Use .at to get a row by label."); + }); + }) + + describe("at", function () { + it("at works on Series", function () { + const data = [1, 2, 3, 4]; + const index = ["a", "b", "c", "d"]; + const df = new Series(data, { index }); + assert.equal(df.at("a"), 1); + assert.equal(df.at("b"), 2); + assert.equal(df.at("c"), 3); + }); + it("at can return undefined", function () { + const data = [1, undefined, null, NaN]; + const index = ["a", "b", "c", "d"]; + const df = new Series(data, { index }); + assert.equal(df.at("b"), undefined); + assert.equal(df.at("c"), null); + /* @ts-ignore */ + assert.equal(isNaN(df.at("d")), true); + }); + it("throws error on string indices", function () { + const data = [1, 2, 3, 4]; + const index = ["a", "b", "c", "d"]; + const df = new Series(data, { index }); + /* @ts-ignore */ + assert.throws(function () { df.at(0); }, Error, "ParamError: row index must be a string. Use .iat to get a row by index."); + }); + + }); +}) \ No newline at end of file diff --git a/src/danfojs-node/test/core/strings.test.ts b/src/danfojs-node/test/core/strings.test.ts new file mode 100644 index 00000000..55b57182 --- /dev/null +++ b/src/danfojs-node/test/core/strings.test.ts @@ -0,0 +1,167 @@ +import { assert, expect } from "chai"; +import { describe, it } from "mocha"; +import { Series} from "../../dist/danfojs-node/src"; + +describe("Str", function () { + it("Converts all characters to lowercase.", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = ['lower', 'capitals', 'this is a sentence', 'swapcase']; + let str = new Series(data).str + assert.deepEqual((str.toLowerCase()as Series).values, res); + }); + it("Converts all characters to uppercase.", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = ['LOWER', 'CAPITALS', 'THIS IS A SENTENCE', 'SWAPCASE']; + let str = new Series(data).str; + assert.deepEqual((str.toUpperCase()as Series).values, res); + }); + it("Converts all characters to capital case.", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = ['Lower', 'Capitals', 'This is a sentence', 'Swapcase']; + let str = new Series(data).str; + assert.deepEqual((str.capitalize()as Series).values, res); + }); + + it("Returns the character at the specified index (position)", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = ["w", "P", "i", "A"]; + let str = new Series(data).str; + assert.deepEqual((str.charAt(2)as Series).values, res); + }); + it("Joins two or more strings. 0 joins from the start", function () { + let data = ['lower', 'CAPITALS', 'sentence', 'SwApCaSe']; + let data2 = ['XX', 'YY', 'BB', '01']; + + let res = ['XXlower', 'YYCAPITALS', 'BBsentence', '01SwApCaSe']; + let str = new Series(data).str; + assert.deepEqual((str.concat(data2, 0)as Series).values, res); + }); + + it("Joins two or more strings. 1 joins from the end", function () { + let data = ['lower', 'CAPITALS', 'sentence', 'SwApCaSe']; + let data2 = ['XX', 'YY', 'BB', '01']; + + let res = ['lowerXX', 'CAPITALSYY', 'sentenceBB', 'SwApCaSe01']; + let str = new Series(data).str; + assert.deepEqual((str.concat(data2, 1)as Series).values, res); + }); + + it("Joins two arrays of strings. 0 joins from the start", function () { + let data = ['lower', 'CAPITALS', 'sentence', 'SwApCaSe']; + let res = ['prelower', 'preCAPITALS', 'presentence', 'preSwApCaSe']; + let str = new Series(data).str; + assert.deepEqual((str.concat("pre", 0)as Series).values, res); + }); + + it("Joins two or more strings. 1 joins from the end", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = ['lowerpost', 'CAPITALSpost', 'this is a sentencepost', 'SwApCaSepost']; + let str = new Series(data).str; + assert.deepEqual((str.concat("post", 1)as Series).values, res); + }); + + it("Checks whether a string begins with specified characters", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = [true, false, false, false]; + let str = new Series(data).str; + assert.deepEqual((str.startsWith("l")as Series).values, res); + }); + it("Checks whether a string ends with specified characters", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = [false, false, true, true]; + let str = new Series(data).str; + assert.deepEqual((str.endsWith("e")as Series).values, res); + }); + + it("Checks whether a string contains the specified string/characters", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = [false, false, true, false]; + let str = new Series(data).str; + assert.deepEqual((str.includes("sentence")as Series).values, res); + }); + + it("Returns the position of the first found occurrence of a specified value in a string", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = [-1, 0, -1, 4]; + let str = new Series(data).str; + assert.deepEqual((str.indexOf("C")as Series).values, res); + }); + + it("Returns the position of the last found occurrence of a specified value in a string", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = [4, -1, -1, -1]; + let str = new Series(data).str; + assert.deepEqual((str.lastIndexOf("r")as Series).values, res); + }); + + it("Returns a new string with a specified number of copies of an existing string", function () { + let data = ['a', 'b', 'c', 'd']; + let res = ['aaa', 'bbb', 'ccc', 'ddd']; + let str = new Series(data).str; + assert.deepEqual((str.repeat(3)as Series).values, res); + }); + + it("Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = ['lower', 'CXXXPITALS', 'this is a sentence', 'SwXXXpCaSe']; + let str = new Series(data).str; + assert.deepEqual((str.replace("A", "XXX")as Series).values, res); + }); + + it("Searches a string for a specified value, or regular expression, and returns the position of the match", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = [-1, 1, -1, 2]; + let str = new Series(data).str; + assert.deepEqual((str.search("A")as Series).values, res); + }); + + it("Extracts a part of a string and returns a new string", function () { + let data = ['lower', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = ['ow', 'AP', 'hi', 'wA']; + let str = new Series(data).str; + assert.deepEqual((str.slice(1, 3)as Series).values, res); + }); + + it("Splits a string into an array of substrings", function () { + let data = ['lower part', 'CAPITALS city', 'is a sentence', 'SwAp CaSe']; + let res = ["lower,part", "CAPITALS,city", "is,a,sentence", "SwAp,CaSe"]; + let str = new Series(data).str; + assert.deepEqual((str.split(" ")as Series).values, res); + }); + + it("Extracts the characters from a string, beginning at a specified start position, and through the specified number of character", function () { + let data = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; + let res = [" p", "AL", "is", "Ca"]; + let str = new Series(data).str; + assert.deepEqual((str.substr(5, 2)as Series).values, res); + }); + + it("Extracts the characters from a string, between two specified indices", function () { + let data = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; + let res = ["w", "P", "i", "A"]; + let str = new Series(data).str; + assert.deepEqual((str.substring(2, 3)as Series).values, res); + }); + + it("Removes whitespace from both ends of a string", function () { + let data = ['lower part ', ' CAPITALS city', ' this is a sentence', ' SwAp CaSe']; + let res = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; + let str = new Series(data).str; + assert.deepEqual((str.trim()as Series).values, res); + }); + + it("Joins strings to specified value", function () { + let data = ['lower part', 'CAPITALS city', 'this is a sentence', 'SwAp CaSe']; + let res = ['lower part,new', 'CAPITALS city,new', 'this is a sentence,new', 'SwAp CaSe,new']; + let str = new Series(data).str; + assert.deepEqual((str.join("new", ",")as Series).values, res); + }); + + it("Counts the number of characters in string", function () { + let data = ['lower part', 'CAPITALS', 'this is a sentence', 'SwApCaSe']; + let res = [10, 8, 18, 8]; + let str = new Series(data).str; + assert.deepEqual((str.len()as Series).values, res); + }); + +}); diff --git a/src/danfojs-node/test/io/csv.reader.test.ts b/src/danfojs-node/test/io/csv.reader.test.ts new file mode 100644 index 00000000..4cfef8dd --- /dev/null +++ b/src/danfojs-node/test/io/csv.reader.test.ts @@ -0,0 +1,245 @@ +import path from "path"; +import chai, { assert, expect } from "chai"; +import { describe, it } from "mocha"; +import chaiAsPromised from "chai-as-promised"; +import { DataFrame, readCSV, Series, streamCSV, toCSV, toJSON } from "../../dist/danfojs-node/src"; +import fs from 'fs'; +import process from 'process'; + +chai.use(chaiAsPromised); + +describe("readCSV", function () { + this.timeout(10000); + + const testSamplesDir = path.join(process.cwd(), "test", "samples"); + + it("Read local csv file works", async function () { + const filePath = path.join(testSamplesDir, "titanic.csv"); + let df = await readCSV(filePath, { header: true, preview: 5 }); + assert.deepEqual(df.shape, [5, 8]); + assert.deepEqual(df.columns, [ + 'Survived', + 'Pclass', + 'Name', + 'Sex', + 'Age', + 'Siblings/Spouses Aboard', + 'Parents/Children Aboard', + 'Fare' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'int32', + 'string', 'string', + 'int32', 'int32', + 'int32', 'float32' + ]); + }); + + it("Read local CSV file with config works", async function () { + const filePath = path.join(testSamplesDir, "titanic.csv"); + const frameConfig = { + columns: [ + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H' + ] + }; + let df = await readCSV(filePath, { frameConfig, header: true, preview: 5 }); + assert.deepEqual(df.shape, [5, 8]); + assert.deepEqual(df.columns, [ + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H' + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'int32', + 'string', 'string', + 'int32', 'int32', + 'int32', 'float32' + ]); + }); + + it("Read local csv with correct types and format works", async function () { + const filePath = path.join(testSamplesDir, "iris.csv"); + let df = await readCSV(filePath, { header: true, preview: 5 }); + const values = [ + [5.1, 3.5, 1.4, 0.2, 0.0], + [4.9, 3.0, 1.4, 0.2, 0.0], + [4.7, 3.2, 1.3, 0.2, 0.0], + [4.6, 3.1, 1.5, 0.2, 0.0], + [5.0, 3.6, 1.4, 0.2, 0.0] + ]; + assert.deepEqual(df.values, values); + }); + + it("Throws error if file not found", async function () { + const filePath = "notfound.csv"; + await expect(readCSV(filePath)).to.be.rejectedWith("ENOENT: no such file or directory"); + }); + + it("Throws error if file not found over http", async function () { + const filePath = "https://getdata.com/notfound.csv"; + await expect(readCSV(filePath)).to.be.rejectedWith(/HTTP \d+:/); + }); + + it("Throws error when reading empty CSV file", async function () { + const filePath = path.join(testSamplesDir, "empty.csv"); + // Create empty file + fs.writeFileSync(filePath, ""); + await expect(readCSV(filePath)).to.be.rejectedWith("No data found in CSV file"); + fs.unlinkSync(filePath); // Clean up + }); + + it("Throws error when reading malformed CSV", async function () { + const filePath = path.join(testSamplesDir, "malformed.csv"); + // Create malformed CSV file + fs.writeFileSync(filePath, "a,b,c\n1,2\n3,4,5,6"); + await expect(readCSV(filePath)).to.be.rejectedWith("CSV parsing errors"); + fs.unlinkSync(filePath); // Clean up + }); + + it("Throws error when DataFrame creation fails", async function () { + const filePath = path.join(testSamplesDir, "invalid.csv"); + await expect(readCSV(filePath)).to.be.rejectedWith("ENOENT: no such file or directory"); + }); + + it("Preserves leading zeros when dtype is string", async function () { + const filePath = path.join(testSamplesDir, "leading_zeros.csv"); + // Create test CSV file + fs.writeFileSync(filePath, "codes\n012345\n001234"); + + try { + const df = await readCSV(filePath, { + frameConfig: { + dtypes: ["string"] + } + }); + + assert.deepEqual(df.values, [["012345"], ["001234"]]); + assert.deepEqual(df.dtypes, ["string"]); + + // Verify the values are actually strings + const jsonData = toJSON(df); + assert.deepEqual(jsonData, [{ codes: "012345" }, { codes: "001234" }]); + + // Clean up + fs.unlinkSync(filePath); + } catch (error) { + // Clean up even if test fails + fs.unlinkSync(filePath); + throw error; + } + }); + + it("Converts to numbers when dtype is not string", async function () { + const filePath = path.join(testSamplesDir, "leading_zeros.csv"); + // Create test CSV file + fs.writeFileSync(filePath, "codes\n012345\n001234"); + + try { + const df = await readCSV(filePath); // default behavior without string dtype + + // Values should be converted to numbers + assert.deepEqual(df.values, [[12345], [1234]]); + assert.deepEqual(df.dtypes, ["int32"]); + + // Verify JSON output + const jsonData = toJSON(df); + assert.deepEqual(jsonData, [{ codes: 12345 }, { codes: 1234 }]); + + // Clean up + fs.unlinkSync(filePath); + } catch (error) { + // Clean up even if test fails + fs.unlinkSync(filePath); + throw error; + } + }); +}); + +describe("streamCSV", function () { + this.timeout(100000); + + const testSamplesDir = path.join(process.cwd(), "test", "samples"); + + it("Streaming local csv file with callback works", async function () { + const filePath = path.join(testSamplesDir, "titanic.csv"); + await streamCSV(filePath, (df) => { + if (df) { + assert.deepEqual(df.shape, [1, 8]); + assert.deepEqual(df.columns, [ + 'Survived', + 'Pclass', + 'Name', + 'Sex', + 'Age', + 'Siblings/Spouses Aboard', + 'Parents/Children Aboard', + 'Fare' + ]); + } else { + assert.deepEqual(df, null); + } + }, { header: true }); + }); + + it("Throws error when streaming non-existent file", async function () { + const filePath = "notfound.csv"; + await expect(streamCSV(filePath, () => {})).to.be.rejectedWith("ENOENT: no such file or directory"); + }); + + it("Throws error when streaming malformed CSV", async function () { + const filePath = path.join(testSamplesDir, "malformed_stream.csv"); + // Create malformed CSV file + fs.writeFileSync(filePath, "a,b,c\n1,2\n3,4,5,6"); + await expect(streamCSV(filePath, () => {})).to.be.rejectedWith("CSV parsing errors"); + fs.unlinkSync(filePath); // Clean up + }); +}); + +describe("toCSV", function () { + const testSamplesDir = path.join(process.cwd(), "test", "samples"); + + it("toCSV works", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]; + let df = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + assert.deepEqual(toCSV(df, {}), `a,b,c,d\n1,2,3,4\n5,6,7,8\n9,10,11,12\n`); + }); + + it("toCSV works for specified separator", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]; + let df = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + assert.deepEqual(toCSV(df, { sep: "+" }), `a+b+c+d\n1+2+3+4\n5+6+7+8\n9+10+11+12\n`); + }); + + it("toCSV write to local file works", async function () { + const data = [[1, 2, 3, "4"], [5, 6, 7, "8"], [9, 10, 11, "12"]]; + let df = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + const filePath = path.join(testSamplesDir, "test_write.csv"); + toCSV(df, { sep: ",", filePath }); + // Clean up + fs.unlinkSync(filePath); + }); + + it("toCSV works for series", async function () { + const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let df = new Series(data); + assert.deepEqual(toCSV(df, { sep: "+" }), `1+2+3+4+5+6+7+8+9+10+11+12`); + }); + + it("calling df.toCSV works", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]; + let df = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + assert.deepEqual(df.toCSV(), `a,b,c,d\n1,2,3,4\n5,6,7,8\n9,10,11,12\n`); + }); +}); diff --git a/src/danfojs-node/test/io/excel.reader.test.ts b/src/danfojs-node/test/io/excel.reader.test.ts new file mode 100644 index 00000000..8e4df028 --- /dev/null +++ b/src/danfojs-node/test/io/excel.reader.test.ts @@ -0,0 +1,128 @@ +import fs from "fs"; +import path from "path" +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, readExcel, Series, toExcel } from "../../dist/danfojs-node/src"; + +describe("readExcel", function () { + this.timeout(100000); + it("Read local excel file works", async function () { + const filePath = path.join(process.cwd(), "test", "samples", "sample.xlsx"); + let df: any = await readExcel(filePath, {}); + assert.deepEqual(df.columns, [ + 'Year', + 'Stocks', + 'T.Bills', + 'T.Bonds', + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'float32', + 'float32', 'float32', + ]); + assert.deepEqual(df.shape, [82, 4]) + }); + it("Read local excel file with config works", async function () { + const filePath = path.join(process.cwd(), "test", "samples", "sample.xlsx"); + const frameConfig = { + columns: [ + 'A', + 'B', + 'C', + 'D', + ] + } + let df: any = await readExcel(filePath, { frameConfig }); + assert.deepEqual(df.columns, [ + 'A', + 'B', + 'C', + 'D', + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'float32', + 'float32', 'float32', + ]); + assert.deepEqual(df.shape, [82, 4]) + }); + it("Read local excel file works for selected sheet", async function () { + const filePath = path.join(process.cwd(), "test", "samples", "sample.xlsx"); + let df: any = await readExcel(filePath, { sheet: 1 }); + assert.deepEqual(df.columns, []); + assert.deepEqual(df.shape, [0, 0]) + }); + + // it("Read remote excel file works", async function () { + // const remoteFile = "https://github.com/javascriptdata/danfojs/raw/dev/src/danfojs-node/test/samples/sample.xlsx" + // let df: any = await readExcel(remoteFile, {}); + // assert.deepEqual(df.columns, [ + // 'Year', + // 'Stocks', + // 'T.Bills', + // 'T.Bonds', + // ]); + // assert.deepEqual(df.dtypes, [ + // 'int32', 'float32', + // 'float32', 'float32', + // ]); + // assert.deepEqual(df.shape, [82, 4]) + // }); +}); + + +describe("toExcel", function () { + it("toExcel works", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + const df: any = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + const filePath = path.join(process.cwd(), "test", "samples", "sampleOut.xlsx"); + toExcel(df, { filePath }) + + const dfNew: any = await readExcel(filePath, {}); + + assert.equal(fs.existsSync(filePath), true) + assert.deepEqual(dfNew.columns, [ + 'a', + 'b', + 'c', + 'd', + ]); + assert.deepEqual(dfNew.dtypes, [ + 'int32', 'int32', + 'int32', 'int32', + ]); + assert.deepEqual(dfNew.shape, [3, 4]) + }); + it("toExcel works for series", async function () { + const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + const df: any = new Series(data); + const filePath = path.join(process.cwd(), "test", "samples", "testSeries.xlsx"); + toExcel(df, { filePath }) + assert.equal(fs.existsSync(filePath), true) + }); + it("calling df.toExcel works", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + const df: any = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + const filePath = path.join(process.cwd(), "test", "samples", "sampleOut.xlsx"); + df.toExcel({ filePath }) + assert.equal(fs.existsSync(filePath), true) + }); + + it("handles null values correctly", async function () { + const data = [ + { 'name': 'Alice', 'age': 25 }, + { 'name': null, 'age': 30 }, + { 'name': 'Charlie', 'age': 35 } + ]; + const df: any = new DataFrame(data); + const filePath = path.join(process.cwd(), "test", "samples", "people.xlsx"); + + toExcel(df, { filePath, sheetName: 'Sheet1' }); + const df2: any = await readExcel(filePath); + + assert.deepEqual(df2.values, [ + ['Alice', 25], + [null, 30], + ['Charlie', 35] + ]); + assert.deepEqual(df2.columns, ['name', 'age']); + }); +}) diff --git a/src/danfojs-node/test/io/json.reader.test.ts b/src/danfojs-node/test/io/json.reader.test.ts new file mode 100644 index 00000000..3ad6aacb --- /dev/null +++ b/src/danfojs-node/test/io/json.reader.test.ts @@ -0,0 +1,154 @@ +import fs from "fs"; +import path from "path" +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, Series, readJSON, toJSON, streamJSON } from "../../dist/danfojs-node/src"; + +describe("readJSON", function () { + this.timeout(100000); + it("Read local json file works", async function () { + const filePath = path.join(process.cwd(), "test", "samples", "book.json"); + const df: any = await readJSON(filePath, {}); + assert.deepEqual(df.columns, [ + 'book_id', + 'title', + 'image_url', + 'authors', + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'string', + 'string', 'string', + ]); + }); + + it("Read local json file with config works", async function () { + const filePath = path.join(process.cwd(), "test", "samples", "book.json"); + const frameConfig = { + columns: ["A", "B", "C", "D"] + } + const df: any = await readJSON(filePath, { frameConfig }); + assert.deepEqual(df.columns, ["A", "B", "C", "D"]); + assert.deepEqual(df.dtypes, [ + 'int32', 'string', + 'string', 'string', + ]); + }); + // it("Read remote json file works", async function () { + // const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/book.json" + // const df: any = await readJSON(remoteFile, {}); + // assert.deepEqual(df.columns, [ + // 'book_id', + // 'title', + // 'image_url', + // 'authors', + // ]); + // assert.deepEqual(df.dtypes, [ + // 'int32', 'string', + // 'string', 'string', + // ]); + // }); +}); + + +describe("streamJSON", function () { + this.timeout(100000); + it("Streaming local csv file with callback works", async function () { + const filePath = path.join(process.cwd(), "test", "samples", "book_small.json"); + await streamJSON(filePath, (df: any) => { + if (df) { + df.print(); + assert.deepEqual(df.shape, [1, 4]) + assert.deepEqual(df.columns, [ + 'book_id', + 'title', + 'image_url', + 'authors', + ]); + assert.deepEqual(df.dtypes, [ + 'int32', 'string', + 'string', 'string', + ]); + } else { + assert.deepEqual(df, null); + } + }); + }); + + // it("Streaming remote json file with callback works", async function () { + // const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/book.json" + // await streamJSON(remoteFile, (df: any) => { + // if (df) { + // df.print(); + // assert.deepEqual(df.shape, [1, 4]) + // assert.deepEqual(df.columns, [ + // 'book_id', + // 'title', + // 'image_url', + // 'authors', + // ]); + // } else { + // assert.deepEqual(df, null); + // } + // }); + + // }); + +}) + + +describe("toJSON", function () { + it("toJSON works", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + const df: any = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + const expected: any = [ + { "a": 1, "b": 2, "c": 3, "d": 4 }, + { "a": 5, "b": 6, "c": 7, "d": 8 }, + { "a": 9, "b": 10, "c": 11, "d": 12 }, + ] + const json = toJSON(df, {}) + assert.deepEqual(json, expected); + }); + it("toJSON works for row format", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + const df: any = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + const expected: any = { + "a": [1, 5, 9], + "b": [2, 6, 10], + "c": [3, 7, 11], + "d": [4, 8, 12], + } + const json = toJSON(df, { format: "row" }) + assert.deepEqual(json, expected); + }); + it("toJSON writes file to local path", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + const df: any = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + + const colFilePath = path.join(process.cwd(), "test", "samples", "test_col_write.json"); + const rowFilePath = path.join(process.cwd(), "test", "samples", "test_row_write.json"); + + toJSON(df, { format: "row", filePath: rowFilePath }) + toJSON(df, { format: "column", filePath: colFilePath }) + + assert.equal(fs.existsSync(rowFilePath), true); + assert.equal(fs.existsSync(colFilePath), true); + }); + it("toJSON works for series", async function () { + const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + const df: any = new Series(data); + assert.deepEqual(toJSON(df, {}), { "0": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] }); + }); + it("df.toJSON works", async function () { + const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + const df: any = new DataFrame(data, { columns: ["a", "b", "c", "d"] }); + const expected: any = { + "a": [1, 5, 9], + "b": [2, 6, 10], + "c": [3, 7, 11], + "d": [4, 8, 12], + } + const json = df.toJSON({ format: "row" }) + assert.deepEqual(json, expected); + }); + +}) diff --git a/danfojs-node/tests/samples/book.json b/src/danfojs-node/test/samples/book.json similarity index 100% rename from danfojs-node/tests/samples/book.json rename to src/danfojs-node/test/samples/book.json diff --git a/src/danfojs-node/test/samples/book_small.json b/src/danfojs-node/test/samples/book_small.json new file mode 100644 index 00000000..e56276db --- /dev/null +++ b/src/danfojs-node/test/samples/book_small.json @@ -0,0 +1,80 @@ +[ + { + "book_id": 30555488, + "title": "The Underground Railroad", + "image_url": "https:\/\/images.gr-assets.com\/books\/1493178362m\/30555488.jpg", + "authors": "Colson Whitehead" + }, + { + "book_id": 30831912, + "title": "Norse Mythology", + "image_url": "https:\/\/images.gr-assets.com\/books\/1473864212m\/30831912.jpg", + "authors": "Neil Gaiman" + }, + { + "book_id": 30839185, + "title": "Vicious (Sinners of Saint, #1)", + "image_url": "https:\/\/images.gr-assets.com\/books\/1481945407m\/30839185.jpg", + "authors": "L.J. Shen" + }, + { + "book_id": 31140847, + "title": "Bossman", + "image_url": "https:\/\/s.gr-assets.com\/assets\/nophoto\/book\/111x148-bcc042a9c91a29c1d680899eff700a03.png", + "authors": "Vi Keeland" + }, + { + "book_id": 31176886, + "title": "The Chemist", + "image_url": "https:\/\/images.gr-assets.com\/books\/1468944057m\/31176886.jpg", + "authors": "Stephenie Meyer" + }, + { + "book_id": 31194270, + "title": "Evelyn, After", + "image_url": "https:\/\/s.gr-assets.com\/assets\/nophoto\/book\/111x148-bcc042a9c91a29c1d680899eff700a03.png", + "authors": "Victoria Helen Stone" + }, + { + "book_id": 31538614, + "title": "Short Stories from Hogwarts of Power, Politics and Pesky Poltergeists (Pottermore Presents, #2)", + "image_url": "https:\/\/images.gr-assets.com\/books\/1471436601m\/31538614.jpg", + "authors": "J.K. Rowling, MinaLima" + }, + { + "book_id": 31538635, + "title": "Short Stories from Hogwarts of Heroism, Hardship and Dangerous Hobbies (Pottermore Presents, #1)", + "image_url": "https:\/\/images.gr-assets.com\/books\/1471436733m\/31538635.jpg", + "authors": "J.K. Rowling, MinaLima" + }, + { + "book_id": 31538647, + "title": "Hogwarts: An Incomplete and Unreliable Guide (Pottermore Presents, #3)", + "image_url": "https:\/\/images.gr-assets.com\/books\/1502156557m\/31538647.jpg", + "authors": "J.K. Rowling" + }, + { + "book_id": 31845516, + "title": "Love Warrior", + "image_url": "https:\/\/images.gr-assets.com\/books\/1473164102m\/31845516.jpg", + "authors": "Glennon Doyle Melton" + }, + { + "book_id": 32075671, + "title": "The Hate U Give", + "image_url": "https:\/\/images.gr-assets.com\/books\/1476284759m\/32075671.jpg", + "authors": "Angie Thomas" + }, + { + "book_id": 32848471, + "title": "Egomaniac", + "image_url": "https:\/\/images.gr-assets.com\/books\/1479387807m\/32848471.jpg", + "authors": "Vi Keeland" + }, + { + "book_id": 33288638, + "title": "Wait for It", + "image_url": "https:\/\/s.gr-assets.com\/assets\/nophoto\/book\/111x148-bcc042a9c91a29c1d680899eff700a03.png", + "authors": "Mariana Zapata" + } +] \ No newline at end of file diff --git a/src/danfojs-node/test/samples/iris.csv b/src/danfojs-node/test/samples/iris.csv new file mode 100644 index 00000000..95c15f1b --- /dev/null +++ b/src/danfojs-node/test/samples/iris.csv @@ -0,0 +1,151 @@ +sepal length (cm),sepal width (cm),petal length (cm),petal width (cm),target +5.1,3.5,1.4,0.2,0.0 +4.9,3.0,1.4,0.2,0.0 +4.7,3.2,1.3,0.2,0.0 +4.6,3.1,1.5,0.2,0.0 +5.0,3.6,1.4,0.2,0.0 +5.4,3.9,1.7,0.4,0.0 +4.6,3.4,1.4,0.3,0.0 +5.0,3.4,1.5,0.2,0.0 +4.4,2.9,1.4,0.2,0.0 +4.9,3.1,1.5,0.1,0.0 +5.4,3.7,1.5,0.2,0.0 +4.8,3.4,1.6,0.2,0.0 +4.8,3.0,1.4,0.1,0.0 +4.3,3.0,1.1,0.1,0.0 +5.8,4.0,1.2,0.2,0.0 +5.7,4.4,1.5,0.4,0.0 +5.4,3.9,1.3,0.4,0.0 +5.1,3.5,1.4,0.3,0.0 +5.7,3.8,1.7,0.3,0.0 +5.1,3.8,1.5,0.3,0.0 +5.4,3.4,1.7,0.2,0.0 +5.1,3.7,1.5,0.4,0.0 +4.6,3.6,1.0,0.2,0.0 +5.1,3.3,1.7,0.5,0.0 +4.8,3.4,1.9,0.2,0.0 +5.0,3.0,1.6,0.2,0.0 +5.0,3.4,1.6,0.4,0.0 +5.2,3.5,1.5,0.2,0.0 +5.2,3.4,1.4,0.2,0.0 +4.7,3.2,1.6,0.2,0.0 +4.8,3.1,1.6,0.2,0.0 +5.4,3.4,1.5,0.4,0.0 +5.2,4.1,1.5,0.1,0.0 +5.5,4.2,1.4,0.2,0.0 +4.9,3.1,1.5,0.2,0.0 +5.0,3.2,1.2,0.2,0.0 +5.5,3.5,1.3,0.2,0.0 +4.9,3.6,1.4,0.1,0.0 +4.4,3.0,1.3,0.2,0.0 +5.1,3.4,1.5,0.2,0.0 +5.0,3.5,1.3,0.3,0.0 +4.5,2.3,1.3,0.3,0.0 +4.4,3.2,1.3,0.2,0.0 +5.0,3.5,1.6,0.6,0.0 +5.1,3.8,1.9,0.4,0.0 +4.8,3.0,1.4,0.3,0.0 +5.1,3.8,1.6,0.2,0.0 +4.6,3.2,1.4,0.2,0.0 +5.3,3.7,1.5,0.2,0.0 +5.0,3.3,1.4,0.2,0.0 +7.0,3.2,4.7,1.4,1.0 +6.4,3.2,4.5,1.5,1.0 +6.9,3.1,4.9,1.5,1.0 +5.5,2.3,4.0,1.3,1.0 +6.5,2.8,4.6,1.5,1.0 +5.7,2.8,4.5,1.3,1.0 +6.3,3.3,4.7,1.6,1.0 +4.9,2.4,3.3,1.0,1.0 +6.6,2.9,4.6,1.3,1.0 +5.2,2.7,3.9,1.4,1.0 +5.0,2.0,3.5,1.0,1.0 +5.9,3.0,4.2,1.5,1.0 +6.0,2.2,4.0,1.0,1.0 +6.1,2.9,4.7,1.4,1.0 +5.6,2.9,3.6,1.3,1.0 +6.7,3.1,4.4,1.4,1.0 +5.6,3.0,4.5,1.5,1.0 +5.8,2.7,4.1,1.0,1.0 +6.2,2.2,4.5,1.5,1.0 +5.6,2.5,3.9,1.1,1.0 +5.9,3.2,4.8,1.8,1.0 +6.1,2.8,4.0,1.3,1.0 +6.3,2.5,4.9,1.5,1.0 +6.1,2.8,4.7,1.2,1.0 +6.4,2.9,4.3,1.3,1.0 +6.6,3.0,4.4,1.4,1.0 +6.8,2.8,4.8,1.4,1.0 +6.7,3.0,5.0,1.7,1.0 +6.0,2.9,4.5,1.5,1.0 +5.7,2.6,3.5,1.0,1.0 +5.5,2.4,3.8,1.1,1.0 +5.5,2.4,3.7,1.0,1.0 +5.8,2.7,3.9,1.2,1.0 +6.0,2.7,5.1,1.6,1.0 +5.4,3.0,4.5,1.5,1.0 +6.0,3.4,4.5,1.6,1.0 +6.7,3.1,4.7,1.5,1.0 +6.3,2.3,4.4,1.3,1.0 +5.6,3.0,4.1,1.3,1.0 +5.5,2.5,4.0,1.3,1.0 +5.5,2.6,4.4,1.2,1.0 +6.1,3.0,4.6,1.4,1.0 +5.8,2.6,4.0,1.2,1.0 +5.0,2.3,3.3,1.0,1.0 +5.6,2.7,4.2,1.3,1.0 +5.7,3.0,4.2,1.2,1.0 +5.7,2.9,4.2,1.3,1.0 +6.2,2.9,4.3,1.3,1.0 +5.1,2.5,3.0,1.1,1.0 +5.7,2.8,4.1,1.3,1.0 +6.3,3.3,6.0,2.5,2.0 +5.8,2.7,5.1,1.9,2.0 +7.1,3.0,5.9,2.1,2.0 +6.3,2.9,5.6,1.8,2.0 +6.5,3.0,5.8,2.2,2.0 +7.6,3.0,6.6,2.1,2.0 +4.9,2.5,4.5,1.7,2.0 +7.3,2.9,6.3,1.8,2.0 +6.7,2.5,5.8,1.8,2.0 +7.2,3.6,6.1,2.5,2.0 +6.5,3.2,5.1,2.0,2.0 +6.4,2.7,5.3,1.9,2.0 +6.8,3.0,5.5,2.1,2.0 +5.7,2.5,5.0,2.0,2.0 +5.8,2.8,5.1,2.4,2.0 +6.4,3.2,5.3,2.3,2.0 +6.5,3.0,5.5,1.8,2.0 +7.7,3.8,6.7,2.2,2.0 +7.7,2.6,6.9,2.3,2.0 +6.0,2.2,5.0,1.5,2.0 +6.9,3.2,5.7,2.3,2.0 +5.6,2.8,4.9,2.0,2.0 +7.7,2.8,6.7,2.0,2.0 +6.3,2.7,4.9,1.8,2.0 +6.7,3.3,5.7,2.1,2.0 +7.2,3.2,6.0,1.8,2.0 +6.2,2.8,4.8,1.8,2.0 +6.1,3.0,4.9,1.8,2.0 +6.4,2.8,5.6,2.1,2.0 +7.2,3.0,5.8,1.6,2.0 +7.4,2.8,6.1,1.9,2.0 +7.9,3.8,6.4,2.0,2.0 +6.4,2.8,5.6,2.2,2.0 +6.3,2.8,5.1,1.5,2.0 +6.1,2.6,5.6,1.4,2.0 +7.7,3.0,6.1,2.3,2.0 +6.3,3.4,5.6,2.4,2.0 +6.4,3.1,5.5,1.8,2.0 +6.0,3.0,4.8,1.8,2.0 +6.9,3.1,5.4,2.1,2.0 +6.7,3.1,5.6,2.4,2.0 +6.9,3.1,5.1,2.3,2.0 +5.8,2.7,5.1,1.9,2.0 +6.8,3.2,5.9,2.3,2.0 +6.7,3.3,5.7,2.5,2.0 +6.7,3.0,5.2,2.3,2.0 +6.3,2.5,5.0,1.9,2.0 +6.5,3.0,5.2,2.0,2.0 +6.2,3.4,5.4,2.3,2.0 +5.9,3.0,5.1,1.8,2.0 diff --git a/src/danfojs-node/test/samples/sample.xlsx b/src/danfojs-node/test/samples/sample.xlsx new file mode 100644 index 00000000..d294b205 Binary files /dev/null and b/src/danfojs-node/test/samples/sample.xlsx differ diff --git a/src/danfojs-node/test/samples/sampleOut.xlsx b/src/danfojs-node/test/samples/sampleOut.xlsx new file mode 100644 index 00000000..92c01d48 Binary files /dev/null and b/src/danfojs-node/test/samples/sampleOut.xlsx differ diff --git a/src/danfojs-node/test/samples/test.xlsx b/src/danfojs-node/test/samples/test.xlsx new file mode 100644 index 00000000..c26493d9 Binary files /dev/null and b/src/danfojs-node/test/samples/test.xlsx differ diff --git a/src/danfojs-node/test/samples/testSeries.xlsx b/src/danfojs-node/test/samples/testSeries.xlsx new file mode 100644 index 00000000..35172ad2 Binary files /dev/null and b/src/danfojs-node/test/samples/testSeries.xlsx differ diff --git a/src/danfojs-node/test/samples/test_col_write.json b/src/danfojs-node/test/samples/test_col_write.json new file mode 100644 index 00000000..1e0a6dec --- /dev/null +++ b/src/danfojs-node/test/samples/test_col_write.json @@ -0,0 +1 @@ +[{"a":1,"b":2,"c":3,"d":4},{"a":5,"b":6,"c":7,"d":8},{"a":9,"b":10,"c":11,"d":12}] \ No newline at end of file diff --git a/src/danfojs-node/test/samples/test_row_write.json b/src/danfojs-node/test/samples/test_row_write.json new file mode 100644 index 00000000..d4df0231 --- /dev/null +++ b/src/danfojs-node/test/samples/test_row_write.json @@ -0,0 +1 @@ +{"a":[1,5,9],"b":[2,6,10],"c":[3,7,11],"d":[4,8,12]} \ No newline at end of file diff --git a/src/danfojs-node/test/samples/test_write.csv b/src/danfojs-node/test/samples/test_write.csv new file mode 100644 index 00000000..0932371e --- /dev/null +++ b/src/danfojs-node/test/samples/test_write.csv @@ -0,0 +1,4 @@ +a,b,c,d +1,2,3,4 +5,6,7,8 +9,10,11,12 diff --git a/danfojs-node/tests/samples/titanic.csv b/src/danfojs-node/test/samples/titanic.csv similarity index 100% rename from danfojs-node/tests/samples/titanic.csv rename to src/danfojs-node/test/samples/titanic.csv diff --git a/src/danfojs-node/test/samples/titanicOutLocal.csv b/src/danfojs-node/test/samples/titanicOutLocal.csv new file mode 100644 index 00000000..489234db --- /dev/null +++ b/src/danfojs-node/test/samples/titanicOutLocal.csv @@ -0,0 +1,888 @@ +Survived,Pclass,Name,Sex,Age,Siblings/Spouses Aboard,Parents/Children Aboard,Fare,titles +0,3, Owen Harris Braund,male,22,1,0,7.25,Mr +1,1, John Bradley (Florence Briggs Thayer) Cumings,female,38,1,0,71.2833,Mrs +1,3, Laina Heikkinen,female,26,0,0,7.925,Miss +1,1, Jacques Heath (Lily May Peel) Futrelle,female,35,1,0,53.1,Mrs +0,3, William Henry Allen,male,35,0,0,8.05,Mr +0,3, James Moran,male,27,0,0,8.4583,Mr +0,1, Timothy J McCarthy,male,54,0,0,51.8625,Mr +0,3, Gosta Leonard Palsson,male,2,3,1,21.075,Master +1,3, Oscar W (Elisabeth Vilhelmina Berg) Johnson,female,27,0,2,11.1333,Mrs +1,2, Nicholas (Adele Achem) Nasser,female,14,1,0,30.0708,Mrs +1,3, Marguerite Rut Sandstrom,female,4,1,1,16.7,Miss +1,1, Elizabeth Bonnell,female,58,0,0,26.55,Miss +0,3, William Henry Saundercock,male,20,0,0,8.05,Mr +0,3, Anders Johan Andersson,male,39,1,5,31.275,Mr +0,3, Hulda Amanda Adolfina Vestrom,female,14,0,0,7.8542,Miss +1,2, (Mary D Kingcome) Hewlett,female,55,0,0,16,Mrs +0,3, Eugene Rice,male,2,4,1,29.125,Master +1,2, Charles Eugene Williams,male,23,0,0,13,Mr +0,3, Julius (Emelia Maria Vandemoortele) Vander Planke,female,31,1,0,18,Mrs +1,3, Fatima Masselmani,female,22,0,0,7.225,Mrs +0,2, Joseph J Fynney,male,35,0,0,26,Mr +1,2, Lawrence Beesley,male,34,0,0,13,Mr +1,3, Anna McGowan,female,15,0,0,8.0292,Miss +1,1, William Thompson Sloper,male,28,0,0,35.5,Mr +0,3, Torborg Danira Palsson,female,8,3,1,21.075,Miss +1,3, Carl Oscar (Selma Augusta Emilia Johansson) Asplund,female,38,1,5,31.3875,Mrs +0,3, Farred Chehab Emir,male,26,0,0,7.225,Mr +0,1, Charles Alexander Fortune,male,19,3,2,263,Mr +1,3, Ellen O'Dwyer,female,24,0,0,7.8792,Miss +0,3, Lalio Todoroff,male,23,0,0,7.8958,Mr +0,1, Manuel E Uruchurtu,male,40,0,0,27.7208,Don +1,1, William Augustus (Marie Eugenie) Spencer,female,48,1,0,146.5208,Mrs +1,3, Mary Agatha Glynn,female,18,0,0,7.75,Miss +0,2, Edward H Wheadon,male,66,0,0,10.5,Mr +0,1, Edgar Joseph Meyer,male,28,1,0,82.1708,Mr +0,1, Alexander Oskar Holverson,male,42,1,0,52,Mr +1,3, Hanna Mamee,male,18,0,0,7.2292,Mr +0,3, Ernest Charles Cann,male,21,0,0,8.05,Mr +0,3, Augusta Maria Vander Planke,female,18,2,0,18,Miss +1,3, Jamila Nicola-Yarred,female,14,1,0,11.2417,Miss +0,3, Johan (Johanna Persdotter Larsson) Ahlin,female,40,1,0,9.475,Mrs +0,2, William John Robert (Dorothy Ann Wonnacott) Turpin,female,27,1,0,21,Mrs +1,2, Simonne Marie Anne Andree Laroche,female,3,1,2,41.5792,Miss +1,3, Margaret Delia Devaney,female,19,0,0,7.8792,Miss +0,3, William John Rogers,male,30,0,0,8.05,Mr +0,3, Denis Lennon,male,20,1,0,15.5,Mr +1,3, Bridget O'Driscoll,female,27,0,0,7.75,Miss +0,3, Youssef Samaan,male,16,2,0,21.6792,Mr +0,3, Josef (Josefine Franchi) Arnold-Franchi,female,18,1,0,17.8,Mrs +0,3, Juha Niilo Panula,male,7,4,1,39.6875,Master +0,3, Richard Cater Nosworthy,male,21,0,0,7.8,Mr +1,1, Henry Sleeper (Myna Haxtun) Harper,female,49,1,0,76.7292,Mrs +1,2, Lizzie (Elizabeth Anne Wilkinson) Faunthorpe,female,29,1,0,26,Mrs +0,1, Engelhart Cornelius Ostby,male,65,0,1,61.9792,Mr +1,1, Hugh Woolner,male,46,0,0,35.5,Mr +1,2, Emily Rugg,female,21,0,0,10.5,Miss +0,3, Mansouer Novel,male,28.5,0,0,7.2292,Mr +1,2, Constance Mirium West,female,5,1,2,27.75,Miss +0,3, William Frederick Goodwin,male,11,5,2,46.9,Master +0,3, Orsen Sirayanian,male,22,0,0,7.2292,Mr +1,1, Amelie Icard,female,38,0,0,80,Miss +0,1, Henry Birkhardt Harris,male,45,1,0,83.475,Mr +0,3, Harald Skoog,male,4,3,2,27.9,Master +0,1, Albert A Stewart,male,64,0,0,27.7208,Mr +1,3, Gerios Moubarek,male,7,1,1,15.2458,Master +1,2, (Elizabeth Ramell) Nye,female,29,0,0,10.5,Mrs +0,3, Ernest James Crease,male,19,0,0,8.1583,Mr +1,3, Erna Alexandra Andersson,female,17,4,2,7.925,Miss +0,3, Vincenz Kink,male,26,2,0,8.6625,Mr +0,2, Stephen Curnow Jenkin,male,32,0,0,10.5,Mr +0,3, Lillian Amy Goodwin,female,16,5,2,46.9,Miss +0,2, Ambrose Jr Hood,male,21,0,0,73.5,Mr +0,3, Apostolos Chronopoulos,male,26,1,0,14.4542,Mr +1,3, Lee Bing,male,32,0,0,56.4958,Mr +0,3, Sigurd Hansen Moen,male,25,0,0,7.65,Mr +0,3, Ivan Staneff,male,23,0,0,7.8958,Mr +0,3, Rahamin Haim Moutal,male,28,0,0,8.05,Mr +1,2, Alden Gates Caldwell,male,0.83,0,2,29,Master +1,3, Elizabeth Dowdell,female,30,0,0,12.475,Miss +0,3, Achille Waelens,male,22,0,0,9,Mr +1,3, Jan Baptist Sheerlinck,male,29,0,0,9.5,Mr +1,3, Brigdet Delia McDermott,female,31,0,0,7.7875,Miss +0,1, Francisco M Carrau,male,28,0,0,47.1,Mr +1,2, Bertha Ilett,female,17,0,0,10.5,Miss +1,3, Karl Alfred (Maria Mathilda Gustafsson) Backstrom,female,33,3,0,15.85,Mrs +0,3, William Neal Ford,male,16,1,3,34.375,Mr +0,3, Selman Francis Slocovski,male,20,0,0,8.05,Mr +1,1, Mabel Helen Fortune,female,23,3,2,263,Miss +0,3, Francesco Celotti,male,24,0,0,8.05,Mr +0,3, Emil Christmann,male,29,0,0,8.05,Mr +0,3, Paul Edvin Andreasson,male,20,0,0,7.8542,Mr +0,1, Herbert Fuller Chaffee,male,46,1,0,61.175,Mr +0,3, Bertram Frank Dean,male,26,1,2,20.575,Mr +0,3, Daniel Coxon,male,59,0,0,7.25,Mr +0,3, Charles Joseph Shorney,male,22,0,0,8.05,Mr +0,1, George B Goldschmidt,male,71,0,0,34.6542,Mr +1,1, William Bertram Greenfield,male,23,0,1,63.3583,Mr +1,2, John T (Ada Julia Bone) Doling,female,34,0,1,23,Mrs +0,2, Sinai Kantor,male,34,1,0,26,Mr +0,3, Matilda Petranec,female,28,0,0,7.8958,Miss +0,3, Pastcho Petroff,male,29,0,0,7.8958,Mr +0,1, Richard Frasar White,male,21,0,1,77.2875,Mr +0,3, Gustaf Joel Johansson,male,33,0,0,8.6542,Mr +0,3, Anders Vilhelm Gustafsson,male,37,2,0,7.925,Mr +0,3, Stoytcho Mionoff,male,28,0,0,7.8958,Mr +1,3, Anna Kristine Salkjelsvik,female,21,0,0,7.65,Miss +1,3, Albert Johan Moss,male,29,0,0,7.775,Mr +0,3, Tido Rekic,male,38,0,0,7.8958,Mr +1,3, Bertha Moran,female,28,1,0,24.15,Miss +0,1, Walter Chamberlain Porter,male,47,0,0,52,Mr +0,3, Hileni Zabour,female,14.5,1,0,14.4542,Miss +0,3, David John Barton,male,22,0,0,8.05,Mr +0,3, Katriina Jussila,female,20,1,0,9.825,Miss +0,3, Malake Attalah,female,17,0,0,14.4583,Miss +0,3, Edvard Pekoniemi,male,21,0,0,7.925,Mr +0,3, Patrick Connors,male,70.5,0,0,7.75,Mr +0,2, William John Robert Turpin,male,29,1,0,21,Mr +0,1, Quigg Edmond Baxter,male,24,0,1,247.5208,Mr +0,3, Ellis Anna Maria Andersson,female,2,4,2,31.275,Miss +0,2, Stanley George Hickman,male,21,2,0,73.5,Mr +0,3, Leonard Charles Moore,male,19,0,0,8.05,Mr +0,2, Nicholas Nasser,male,32.5,1,0,30.0708,Mr +1,2, Susan Webber,female,32.5,0,0,13,Miss +0,1, Percival Wayland White,male,54,0,1,77.2875,Mr +1,3, Elias Nicola-Yarred,male,12,1,0,11.2417,Master +0,3, Martin McMahon,male,19,0,0,7.75,Mr +1,3, Fridtjof Arne Madsen,male,24,0,0,7.1417,Mr +1,3, Anna Peter,female,2,1,1,22.3583,Miss +0,3, Johan Ekstrom,male,45,0,0,6.975,Mr +0,3, Jozef Drazenoic,male,33,0,0,7.8958,Mr +0,3, Domingos Fernandeo Coelho,male,20,0,0,7.05,Mr +0,3, Alexander A (Grace Charity Laury) Robins,female,47,1,0,14.5,Mrs +1,2, Leopold (Mathilde Francoise Pede) Weisz,female,29,1,0,26,Mrs +0,2, Samuel James Hayden Sobey,male,25,0,0,13,Mr +0,2, Emile Richard,male,23,0,0,15.0458,Mr +1,1, Helen Monypeny Newsom,female,19,0,2,26.2833,Miss +0,1, Jacques Heath Futrelle,male,37,1,0,53.1,Mr +0,3, Olaf Elon Osen,male,16,0,0,9.2167,Mr +0,1, Victor Giglio,male,24,0,0,79.2,Mr +0,3, Joseph (Sultana) Boulos,female,40,0,2,15.2458,Mrs +1,3, Anna Sofia Nysten,female,22,0,0,7.75,Miss +1,3, Pekka Pietari (Elin Matilda Dolck) Hakkarainen,female,24,1,0,15.85,Mrs +0,3, Jeremiah Burke,male,19,0,0,6.75,Mr +0,2, Edgardo Samuel Andrew,male,18,0,0,11.5,Mr +0,2, Joseph Charles Nicholls,male,19,1,1,36.75,Mr +1,3, August Edvard Andersson,male,27,0,0,7.7958,Mr +0,3, Robina Maggie Ford,female,9,2,2,34.375,Miss +0,2, Michel Navratil,male,36.5,0,2,26,Mr +0,2, Thomas Roussel Davids Byles,male,42,0,0,13,Rev +0,2, Robert James Bateman,male,51,0,0,12.525,Rev +1,1, Thomas (Edith Wearne) Pears,female,22,1,0,66.6,Mrs +0,3, Alfonzo Meo,male,55.5,0,0,8.05,Mr +0,3, Austin Blyler van Billiard,male,40.5,0,2,14.5,Mr +0,3, Ole Martin Olsen,male,27,0,0,7.3125,Mr +0,1, Charles Duane Williams,male,51,0,1,61.3792,Mr +1,3, Katherine Gilnagh,female,16,0,0,7.7333,Miss +0,3, Harry Corn,male,30,0,0,8.05,Mr +0,3, Mile Smiljanic,male,37,0,0,8.6625,Mr +0,3, Thomas Henry Sage,male,5,8,2,69.55,Master +0,3, John Hatfield Cribb,male,44,0,1,16.1,Mr +1,2, James (Elizabeth Inglis Milne) Watt,female,40,0,0,15.75,Mrs +0,3, John Viktor Bengtsson,male,26,0,0,7.775,Mr +0,3, Jovo Calic,male,17,0,0,8.6625,Mr +0,3, Eino Viljami Panula,male,1,4,1,39.6875,Master +1,3, Frank John William Goldsmith,male,9,0,2,20.525,Master +1,1, (Edith Martha Bowerman) Chibnall,female,48,0,1,55,Mrs +0,3, William (Anna Bernhardina Karlsson) Skoog,female,45,1,4,27.9,Mrs +0,1, John D Baumann,male,60,0,0,25.925,Mr +0,3, Lee Ling,male,28,0,0,56.4958,Mr +0,1, Wyckoff Van der hoef,male,61,0,0,33.5,Mr +0,3, Arthur Rice,male,4,4,1,29.125,Master +1,3, Eleanor Ileen Johnson,female,1,1,1,11.1333,Miss +0,3, Antti Wilhelm Sivola,male,21,0,0,7.925,Mr +0,1, James Clinch Smith,male,56,0,0,30.6958,Mr +0,3, Klas Albin Klasen,male,18,1,1,7.8542,Mr +0,3, Henry Forbes Lefebre,male,5,3,1,25.4667,Master +0,1, Ann Elizabeth Isham,female,50,0,0,28.7125,Miss +0,2, Reginald Hale,male,30,0,0,13,Mr +0,3, Lionel Leonard,male,36,0,0,0,Mr +0,3, Constance Gladys Sage,female,8,8,2,69.55,Miss +0,2, Rene Pernot,male,39,0,0,15.05,Mr +0,3, Clarence Gustaf Hugo Asplund,male,9,4,2,31.3875,Master +1,2, Richard F Becker,male,1,2,1,39,Master +1,3, Luise Gretchen Kink-Heilmann,female,4,0,2,22.025,Miss +0,1, Hugh Roscoe Rood,male,39,0,0,50,Mr +1,3, Thomas (Johanna Godfrey) O'Brien,female,26,1,0,15.5,Mrs +1,1, Charles Hallace Romaine,male,45,0,0,26.55,Mr +0,3, John Bourke,male,40,1,1,15.5,Mr +0,3, Stjepan Turcin,male,36,0,0,7.8958,Mr +1,2, (Rosa) Pinsky,female,32,0,0,13,Mrs +0,2, William Carbines,male,19,0,0,13,Mr +1,3, Carla Christine Nielsine Andersen-Jensen,female,19,1,0,7.8542,Miss +1,2, Michel M Navratil,male,3,1,1,26,Master +1,1, James Joseph (Margaret Tobin) Brown,female,44,0,0,27.7208,Mrs +1,1, Elise Lurette,female,58,0,0,146.5208,Miss +0,3, Robert Mernagh,male,28,0,0,7.75,Mr +0,3, Karl Siegwart Andreas Olsen,male,42,0,1,8.4042,Mr +1,3, Margaret Madigan,female,21,0,0,7.75,Miss +0,2, Henriette Yrois,female,24,0,0,13,Miss +0,3, Nestor Cyriel Vande Walle,male,28,0,0,9.5,Mr +0,3, Frederick Sage,male,17,8,2,69.55,Mr +0,3, Jakob Alfred Johanson,male,34,0,0,6.4958,Mr +0,3, Gerious Youseff,male,45.5,0,0,7.225,Mr +1,3, Gurshon Cohen,male,18,0,0,8.05,Mr +0,3, Telma Matilda Strom,female,2,0,1,10.4625,Miss +0,3, Karl Alfred Backstrom,male,32,1,0,15.85,Mr +1,3, Nassef Cassem Albimona,male,26,0,0,18.7875,Mr +1,3, Helen Carr,female,16,0,0,7.75,Miss +1,1, Henry Blank,male,40,0,0,31,Mr +0,3, Ahmed Ali,male,24,0,0,7.05,Mr +1,2, Clear Annie Cameron,female,35,0,0,21,Miss +0,3, John Henry Perkin,male,22,0,0,7.25,Mr +0,2, Hans Kristensen Givard,male,30,0,0,13,Mr +0,3, Philip Kiernan,male,22,1,0,7.75,Mr +1,1, Madeleine Newell,female,31,1,0,113.275,Miss +1,3, Eliina Honkanen,female,27,0,0,7.925,Miss +0,2, Sidney Samuel Jacobsohn,male,42,1,0,27,Mr +1,1, Albina Bazzani,female,32,0,0,76.2917,Miss +0,2, Walter Harris,male,30,0,0,10.5,Mr +1,3, Victor Francis Sunderland,male,16,0,0,8.05,Mr +0,2, James H Bracken,male,27,0,0,13,Mr +0,3, George Henry Green,male,51,0,0,8.05,Mr +0,3, Christo Nenkoff,male,22,0,0,7.8958,Mr +1,1, Frederick Maxfield Hoyt,male,38,1,0,90,Mr +0,3, Karl Ivar Sven Berglund,male,22,0,0,9.35,Mr +1,2, William John Mellors,male,19,0,0,10.5,Mr +0,3, John Hall Lovell,male,20.5,0,0,7.25,Mr +0,2, Arne Jonas Fahlstrom,male,18,0,0,13,Mr +0,3, Mathilde Lefebre,female,12,3,1,25.4667,Miss +1,1, Henry Birkhardt (Irene Wallach) Harris,female,35,1,0,83.475,Mrs +0,3, Bengt Edvin Larsson,male,29,0,0,7.775,Mr +0,2, Ernst Adolf Sjostedt,male,59,0,0,13.5,Mr +1,3, Lillian Gertrud Asplund,female,5,4,2,31.3875,Miss +0,2, Robert William Norman Leyson,male,24,0,0,10.5,Mr +0,3, Alice Phoebe Harknett,female,21,0,0,7.55,Miss +0,2, Stephen Hold,male,44,1,0,26,Mr +1,2, Marjorie Collyer,female,8,0,2,26.25,Miss +0,2, Frederick William Pengelly,male,19,0,0,10.5,Mr +0,2, George Henry Hunt,male,33,0,0,12.275,Mr +0,3, Thamine Zabour,female,19,1,0,14.4542,Miss +1,3, Katherine Murphy,female,18,1,0,15.5,Miss +0,2, Reginald Charles Coleridge,male,29,0,0,10.5,Mr +0,3, Matti Alexanteri Maenpaa,male,22,0,0,7.125,Mr +0,3, Sleiman Attalah,male,30,0,0,7.225,Mr +0,1, William Edward Minahan,male,44,2,0,90,Dr +0,3, Agda Thorilda Viktoria Lindahl,female,25,0,0,7.775,Miss +1,2, William (Anna) Hamalainen,female,24,0,2,14.5,Mrs +1,1, Richard Leonard Beckwith,male,37,1,1,52.5542,Mr +0,2, Ernest Courtenay Carter,male,54,1,0,26,Rev +0,3, James George Reed,male,18,0,0,7.25,Mr +0,3, Wilhelm (Elna Matilda Persson) Strom,female,29,1,1,10.4625,Mrs +0,1, William Thomas Stead,male,62,0,0,26.55,Mr +0,3, William Arthur Lobb,male,30,1,0,16.1,Mr +0,3, Viktor (Helena Wilhelmina) Rosblom,female,41,0,2,20.2125,Mrs +1,3, Darwis (Hanne Youssef Razi) Touma,female,29,0,2,15.2458,Mrs +1,1, Gertrude Maybelle Thorne,female,38,0,0,79.2,Mrs +1,1, Gladys Cherry,female,30,0,0,86.5,Miss +1,1, Anna Ward,female,35,0,0,512.3292,Miss +1,2, (Lutie Davis) Parrish,female,50,0,1,26,Mrs +1,3, Edvin Rojj Felix Asplund,male,3,4,2,31.3875,Master +0,1, Emil Taussig,male,52,1,1,79.65,Mr +0,1, William Harrison,male,40,0,0,0,Mr +0,3, Delia Henry,female,21,0,0,7.75,Miss +0,2, David Reeves,male,36,0,0,10.5,Mr +0,3, Ernesti Arvid Panula,male,16,4,1,39.6875,Mr +1,3, Ernst Ulrik Persson,male,25,1,0,7.775,Mr +1,1, William Thompson (Edith Junkins) Graham,female,58,0,1,153.4625,Mrs +1,1, Amelia Bissette,female,35,0,0,135.6333,Miss +0,1, Alexander Cairns,male,28,0,0,31,Mr +1,3, William Henry Tornquist,male,25,0,0,0,Mr +1,2, (Elizabeth Anne Maidment) Mellinger,female,41,0,1,19.5,Mrs +0,1, Charles H Natsch,male,37,0,1,29.7,Mr +1,3, Hanora Healy,female,33,0,0,7.75,Miss +1,1, Kornelia Theodosia Andrews,female,63,1,0,77.9583,Miss +0,3, Augusta Charlotta Lindblom,female,45,0,0,7.75,Miss +0,2, Francis Parkes,male,21,0,0,0,Mr +0,3, Eric Rice,male,7,4,1,29.125,Master +1,3, Stanton (Rosa Hunt) Abbott,female,35,1,1,20.25,Mrs +0,3, Frank Duane,male,65,0,0,7.75,Mr +0,3, Nils Johan Goransson Olsson,male,28,0,0,7.8542,Mr +0,3, Alfons de Pelsmaeker,male,16,0,0,9.5,Mr +1,3, Edward Arthur Dorking,male,19,0,0,8.05,Mr +0,1, Richard William Smith,male,57,0,0,26,Mr +0,3, Ivan Stankovic,male,33,0,0,8.6625,Mr +1,3, Theodore de Mulder,male,30,0,0,9.5,Mr +0,3, Penko Naidenoff,male,22,0,0,7.8958,Mr +1,2, Masabumi Hosono,male,42,0,0,13,Mr +1,3, Kate Connolly,female,22,0,0,7.75,Miss +1,1, Ellen Barber,female,26,0,0,78.85,Miss +1,1, Dickinson H (Helen Walton) Bishop,female,19,1,0,91.0792,Mrs +0,2, Rene Jacques Levy,male,36,0,0,12.875,Mr +0,3, Aloisia Haas,female,24,0,0,8.85,Miss +0,3, Ivan Mineff,male,24,0,0,7.8958,Mr +0,1, Ervin G Lewy,male,30,0,0,27.7208,Mr +0,3, Mansour Hanna,male,23.5,0,0,7.2292,Mr +0,1, Helen Loraine Allison,female,2,1,2,151.55,Miss +1,1, Adolphe Saalfeld,male,47,0,0,30.5,Mr +1,1, James (Helene DeLaudeniere Chaput) Baxter,female,50,0,1,247.5208,Mrs +1,3, Anna Katherine Kelly,female,20,0,0,7.75,Miss +1,3, Bernard McCoy,male,24,2,0,23.25,Mr +0,3, William Cahoone Jr Johnson,male,19,0,0,0,Mr +1,2, Nora A Keane,female,46,0,0,12.35,Miss +0,3, Howard Hugh Williams,male,28,0,0,8.05,Mr +1,1, Hudson Trevor Allison,male,0.92,1,2,151.55,Master +1,1, Margaret Fleming,female,42,0,0,110.8833,Miss +1,1, Victor de Satode (Maria Josefa Perez de Soto y Vallejo) Penasco y Castellana,female,17,1,0,108.9,Mrs +0,2, Samuel Abelson,male,30,1,0,24,Mr +1,1, Laura Mabel Francatelli,female,30,0,0,56.9292,Miss +1,1, Margaret Bechstein Hays,female,24,0,0,83.1583,Miss +1,1, Emily Borie Ryerson,female,18,2,2,262.375,Miss +0,2, William (Anna Sylfven) Lahtinen,female,26,1,1,26,Mrs +0,3, Ignjac Hendekovic,male,28,0,0,7.8958,Mr +0,2, Benjamin Hart,male,43,1,1,26.25,Mr +1,3, Helmina Josefina Nilsson,female,26,0,0,7.8542,Miss +1,2, Sinai (Miriam Sternin) Kantor,female,24,1,0,26,Mrs +0,2, Ernest Moraweck,male,54,0,0,14,Dr +1,1, Mary Natalie Wick,female,31,0,2,164.8667,Miss +1,1, Frederic Oakley (Margaretta Corning Stone) Spedden,female,40,1,1,134.5,Mrs +0,3, Samuel Dennis,male,22,0,0,7.25,Mr +0,3, Yoto Danoff,male,27,0,0,7.8958,Mr +1,2, Hilda Mary Slayter,female,30,0,0,12.35,Miss +1,2, Albert Francis (Sylvia Mae Harbaugh) Caldwell,female,22,1,1,29,Mrs +0,3, George John Jr Sage,male,20,8,2,69.55,Mr +1,1, Marie Grice Young,female,36,0,0,135.6333,Miss +0,3, Johan Hansen Nysveen,male,61,0,0,6.2375,Mr +1,2, (Ada E Hall) Ball,female,36,0,0,13,Mrs +1,3, Frank John (Emily Alice Brown) Goldsmith,female,31,1,1,20.525,Mrs +1,1, Jean Gertrude Hippach,female,16,0,1,57.9792,Miss +1,3, Agnes McCoy,female,28,2,0,23.25,Miss +0,1, Austen Partner,male,45.5,0,0,28.5,Mr +0,1, George Edward Graham,male,38,0,1,153.4625,Mr +0,3, Leo Edmondus Vander Planke,male,16,2,0,18,Mr +1,1, Henry William (Clara Heinsheimer) Frauenthal,female,42,1,0,133.65,Mrs +0,3, Mitto Denkoff,male,30,0,0,7.8958,Mr +0,1, Thomas Clinton Pears,male,29,1,0,66.6,Mr +1,1, Elizabeth Margaret Burns,female,41,0,0,134.5,Miss +1,3, Karl Edwart Dahl,male,45,0,0,8.05,Mr +0,1, Stephen Weart Blackwell,male,45,0,0,35.5,Mr +1,2, Edmond Roger Navratil,male,2,1,1,26,Master +1,1, Alice Elizabeth Fortune,female,24,3,2,263,Miss +0,2, Erik Gustaf Collander,male,28,0,0,13,Mr +0,2, Charles Frederick Waddington Sedgwick,male,25,0,0,13,Mr +0,2, Stanley Hubert Fox,male,36,0,0,13,Mr +1,2, Amelia Brown,female,24,0,0,13,Miss +1,2, Marion Elsie Smith,female,40,0,0,13,Miss +1,3, Thomas Henry (Mary E Finck) Davison,female,34,1,0,16.1,Mrs +1,3, William Loch Coutts,male,3,1,1,15.9,Master +0,3, Jovan Dimic,male,42,0,0,8.6625,Mr +0,3, Nils Martin Odahl,male,23,0,0,9.225,Mr +0,1, Fletcher Fellows Williams-Lambert,male,43,0,0,35,Mr +0,3, Tannous Elias,male,15,1,1,7.2292,Mr +0,3, Josef Arnold-Franchi,male,25,1,0,17.8,Mr +0,3, Wazli Yousif,male,23,0,0,7.225,Mr +0,3, Leo Peter Vanden Steen,male,28,0,0,9.5,Mr +1,1, Elsie Edith Bowerman,female,22,0,1,55,Miss +0,2, Annie Clemmer Funk,female,38,0,0,13,Miss +1,3, Mary McGovern,female,22,0,0,7.8792,Miss +1,3, Helen Mary Mockler,female,23,0,0,7.8792,Miss +0,3, Wilhelm Skoog,male,40,1,4,27.9,Mr +0,2, Sebastiano del Carlo,male,29,1,0,27.7208,Mr +0,3, (Catherine David) Barbara,female,45,0,1,14.4542,Mrs +0,3, Adola Asim,male,35,0,0,7.05,Mr +0,3, Thomas O'Brien,male,27,1,0,15.5,Mr +0,3, Mauritz Nils Martin Adahl,male,30,0,0,7.25,Mr +1,1, Frank Manley (Anna Sophia Atkinson) Warren,female,60,1,0,75.25,Mrs +1,3, (Mantoura Boulos) Moussa,female,35,0,0,7.2292,Mrs +1,3, Annie Jermyn,female,22,0,0,7.75,Miss +1,1, Leontine Pauline Aubart,female,24,0,0,69.3,Mme +1,1, George Achilles Harder,male,25,1,0,55.4417,Mr +0,3, Jakob Alfred Wiklund,male,18,1,0,6.4958,Mr +0,3, William Thomas Beavan,male,19,0,0,8.05,Mr +0,1, Sante Ringhini,male,22,0,0,135.6333,Mr +0,3, Stina Viola Palsson,female,3,3,1,21.075,Miss +1,1, Edgar Joseph (Leila Saks) Meyer,female,25,1,0,82.1708,Mrs +1,3, Aurora Adelia Landergren,female,22,0,0,7.25,Miss +0,1, Harry Elkins Widener,male,27,0,2,211.5,Mr +0,3, Tannous Betros,male,20,0,0,4.0125,Mr +0,3, Karl Gideon Gustafsson,male,19,0,0,7.775,Mr +1,1, Rosalie Bidois,female,42,0,0,227.525,Miss +1,3, Maria Nakid,female,1,0,2,15.7417,Miss +0,3, Juho Tikkanen,male,32,0,0,7.925,Mr +1,1, Alexander Oskar (Mary Aline Towner) Holverson,female,35,1,0,52,Mrs +0,3, Vasil Plotcharsky,male,27,0,0,7.8958,Mr +0,2, Charles Henry Davies,male,18,0,0,73.5,Mr +0,3, Sidney Leonard Goodwin,male,1,5,2,46.9,Master +1,2, Kate Buss,female,36,0,0,13,Miss +0,3, Matthew Sadlier,male,19,0,0,7.7292,Mr +1,2, Bertha Lehmann,female,17,0,0,12,Miss +1,1, William Ernest Carter,male,36,1,2,120,Mr +1,3, Carl Olof Jansson,male,21,0,0,7.7958,Mr +0,3, Johan Birger Gustafsson,male,28,2,0,7.925,Mr +1,1, Marjorie Newell,female,23,1,0,113.275,Miss +1,3, Hjalmar (Agnes Charlotta Bengtsson) Sandstrom,female,24,0,2,16.7,Mrs +0,3, Erik Johansson,male,22,0,0,7.7958,Mr +0,3, Elina Olsson,female,31,0,0,7.8542,Miss +0,2, Peter David McKane,male,46,0,0,26,Mr +0,2, Alfred Pain,male,23,0,0,10.5,Dr +1,2, William H (Jessie L) Trout,female,28,0,0,12.65,Mrs +1,3, Juha Niskanen,male,39,0,0,7.925,Mr +0,3, John Adams,male,26,0,0,8.05,Mr +0,3, Mari Aina Jussila,female,21,1,0,9.825,Miss +0,3, Pekka Pietari Hakkarainen,male,28,1,0,15.85,Mr +0,3, Marija Oreskovic,female,20,0,0,8.6625,Miss +0,2, Shadrach Gale,male,34,1,0,21,Mr +0,3, Carl/Charles Peter Widegren,male,51,0,0,7.75,Mr +1,2, William Rowe Richards,male,3,1,1,18.75,Master +0,3, Hans Martin Monsen Birkeland,male,21,0,0,7.775,Mr +0,3, Ida Lefebre,female,3,3,1,25.4667,Miss +0,3, Todor Sdycoff,male,42,0,0,7.8958,Mr +0,3, Henry Hart,male,27,0,0,6.8583,Mr +1,1, Daisy E Minahan,female,33,1,0,90,Miss +0,2, Alfred Fleming Cunningham,male,22,0,0,0,Mr +1,3, Johan Julian Sundman,male,44,0,0,7.925,Mr +0,3, Thomas (Annie Louise Rowley) Meek,female,32,0,0,8.05,Mrs +1,2, James Vivian (Lulu Thorne Christian) Drew,female,34,1,1,32.5,Mrs +1,2, Lyyli Karoliina Silven,female,18,0,2,13,Miss +0,2, William John Matthews,male,30,0,0,13,Mr +0,3, Catharina Van Impe,female,10,0,2,24.15,Miss +0,3, David Charters,male,21,0,0,7.7333,Mr +0,3, Leo Zimmerman,male,29,0,0,7.875,Mr +0,3, Ernst Gilbert (Anna Sigrid Maria Brogren) Danbom,female,28,1,1,14.4,Mrs +0,3, Viktor Richard Rosblom,male,18,1,1,20.2125,Mr +0,3, Phillippe Wiseman,male,54,0,0,7.25,Mr +1,2, Charles V (Ada Maria Winfield) Clarke,female,28,1,0,26,Mrs +1,2, Kate Florence Phillips,female,19,0,0,26,Miss +0,3, James Flynn,male,28,0,0,7.75,Mr +1,3, Berk (Berk Trembisky) Pickard,male,32,0,0,8.05,Mr +1,1, Mauritz Hakan Bjornstrom-Steffansson,male,28,0,0,26.55,Mr +1,3, Percival (Florence Kate White) Thorneycroft,female,33,1,0,16.1,Mrs +1,2, Charles Alexander (Alice Adelaide Slow) Louch,female,42,1,0,26,Mrs +0,3, Nikolai Erland Kallio,male,17,0,0,7.125,Mr +0,1, William Baird Silvey,male,50,1,0,55.9,Mr +1,1, Lucile Polk Carter,female,14,1,2,120,Miss +0,3, Doolina Margaret Ford,female,21,2,2,34.375,Miss +1,2, Sidney (Emily Hocking) Richards,female,24,2,3,18.75,Mrs +0,1, Mark Fortune,male,64,1,4,263,Mr +0,2, Johan Henrik Johannesson Kvillner,male,31,0,0,10.5,Mr +1,2, Benjamin (Esther Ada Bloomfield) Hart,female,45,1,1,26.25,Mrs +0,3, Leon Hampe,male,20,0,0,9.5,Mr +0,3, Johan Emil Petterson,male,25,1,0,7.775,Mr +1,2, Encarnacion Reynaldo,female,28,0,0,13,Ms +1,3, Bernt Johannesen-Bratthammer,male,29,0,0,8.1125,Mr +1,1, Washington Dodge,male,4,0,2,81.8583,Master +1,2, Madeleine Violet Mellinger,female,13,0,1,19.5,Miss +1,1, Frederic Kimber Seward,male,34,0,0,26.55,Mr +1,3, Marie Catherine Baclini,female,5,2,1,19.2583,Miss +1,1, Arthur Godfrey Peuchen,male,52,0,0,30.5,Major +0,2, Edwy Arthur West,male,36,1,2,27.75,Mr +0,3, Ingvald Olai Olsen Hagland,male,28,1,0,19.9667,Mr +0,1, Benjamin Laventall Foreman,male,30,0,0,27.75,Mr +1,1, Samuel L Goldenberg,male,49,1,0,89.1042,Mr +0,3, Joseph Peduzzi,male,24,0,0,8.05,Mr +1,3, Ivan Jalsevac,male,29,0,0,7.8958,Mr +0,1, Francis Davis Millet,male,65,0,0,26.55,Mr +1,1, Frederick R (Marion) Kenyon,female,41,1,0,51.8625,Mrs +1,2, Ellen Toomey,female,50,0,0,10.5,Miss +0,3, Maurice O'Connor,male,17,0,0,7.75,Mr +1,1, Harry Anderson,male,48,0,0,26.55,Mr +0,3, William Morley,male,34,0,0,8.05,Mr +0,1, Arthur H Gee,male,47,0,0,38.5,Mr +0,2, Jacob Christian Milling,male,48,0,0,13,Mr +0,3, Simon Maisner,male,34,0,0,8.05,Mr +0,3, Manuel Estanslas Goncalves,male,38,0,0,7.05,Mr +0,2, William Campbell,male,21,0,0,0,Mr +0,1, John Montgomery Smart,male,56,0,0,26.55,Mr +0,3, James Scanlan,male,22,0,0,7.725,Mr +1,3, Helene Barbara Baclini,female,0.75,2,1,19.2583,Miss +0,3, Arthur Keefe,male,39,0,0,7.25,Mr +0,3, Luka Cacic,male,38,0,0,8.6625,Mr +1,2, Edwy Arthur (Ada Mary Worth) West,female,33,1,2,27.75,Mrs +1,2, Amin S (Marie Marthe Thuillard) Jerwan,female,23,0,0,13.7917,Mrs +0,3, Ida Sofia Strandberg,female,22,0,0,9.8375,Miss +0,1, George Quincy Clifford,male,40,0,0,52,Mr +0,2, Peter Henry Renouf,male,34,1,0,21,Mr +0,3, Lewis Richard Braund,male,29,1,0,7.0458,Mr +0,3, Nils August Karlsson,male,22,0,0,7.5208,Mr +1,3, Hildur E Hirvonen,female,2,0,1,12.2875,Miss +0,3, Harold Victor Goodwin,male,9,5,2,46.9,Master +0,2, Anthony Wood Frost,male,37,0,0,0,Mr +0,3, Richard Henry Rouse,male,50,0,0,8.05,Mr +1,3, (Hedwig) Turkula,female,63,0,0,9.5875,Mrs +1,1, Dickinson H Bishop,male,25,1,0,91.0792,Mr +0,3, Jeannie Lefebre,female,8,3,1,25.4667,Miss +1,1, Frederick Maxfield (Jane Anne Forby) Hoyt,female,35,1,0,90,Mrs +0,1, Edward Austin Kent,male,58,0,0,29.7,Mr +0,3, Francis William Somerton,male,30,0,0,8.05,Mr +1,3, Eden Leslie Coutts,male,9,1,1,15.9,Master +0,3, Konrad Mathias Reiersen Hagland,male,19,1,0,19.9667,Mr +0,3, Einar Windelov,male,21,0,0,7.25,Mr +0,1, Harry Markland Molson,male,55,0,0,30.5,Mr +0,1, Ramon Artagaveytia,male,71,0,0,49.5042,Mr +0,3, Edward Roland Stanley,male,21,0,0,8.05,Mr +0,3, Gerious Yousseff,male,26,0,0,14.4583,Mr +1,1, Elizabeth Mussey Eustis,female,54,1,0,78.2667,Miss +0,3, Frederick William Shellard,male,55,0,0,15.1,Mr +0,1, Hudson J C (Bessie Waldo Daniels) Allison,female,25,1,2,151.55,Mrs +0,3, Olof Svensson,male,24,0,0,7.7958,Mr +0,3, Petar Calic,male,17,0,0,8.6625,Mr +0,3, Mary Canavan,female,21,0,0,7.75,Miss +0,3, Bridget Mary O'Sullivan,female,21,0,0,7.6292,Miss +0,3, Kristina Sofia Laitinen,female,37,0,0,9.5875,Miss +1,1, Roberta Maioni,female,16,0,0,86.5,Miss +0,1, Victor de Satode Penasco y Castellana,male,18,1,0,108.9,Mr +1,2, Frederick Charles (Jane Richards) Quick,female,33,0,2,26,Mrs +1,1, George Bradley,male,37,0,0,26.55,Mr +0,3, Henry Margido Olsen,male,28,0,0,22.525,Mr +1,3, Fang Lang,male,26,0,0,56.4958,Mr +1,3, Eugene Patrick Daly,male,29,0,0,7.75,Mr +0,3, James Webber,male,66,0,0,8.05,Mr +1,1, James Robert McGough,male,36,0,0,26.2875,Mr +1,1, Martin (Elizabeth L,female,54,1,0,59.4,Mrs +0,3, Satio Coleff,male,24,0,0,7.4958,Mr +0,1, William Anderson Walker,male,47,0,0,34.0208,Mr +1,2, (Amelia Milley) Lemore,female,34,0,0,10.5,Mrs +0,3, Patrick Ryan,male,30,0,0,24.15,Mr +1,2, William A (Florence Agnes Hughes) Angle,female,36,1,0,26,Mrs +0,3, Stefo Pavlovic,male,32,0,0,7.8958,Mr +1,1, Anne Perreault,female,30,0,0,93.5,Miss +0,3, Janko Vovk,male,22,0,0,7.8958,Mr +0,3, Sarkis Lahoud,male,35,0,0,7.225,Mr +1,1, Louis Albert (Ida Sophia Fischer) Hippach,female,44,0,1,57.9792,Mrs +0,3, Fared Kassem,male,18,0,0,7.2292,Mr +0,3, James Farrell,male,40.5,0,0,7.75,Mr +1,2, Lucy Ridsdale,female,50,0,0,10.5,Miss +0,1, John Farthing,male,49,0,0,221.7792,Mr +0,3, Johan Werner Salonen,male,39,0,0,7.925,Mr +0,2, Richard George Hocking,male,23,2,1,11.5,Mr +1,2, Phyllis May Quick,female,2,1,1,26,Miss +0,3, Nakli Toufik,male,17,0,0,7.2292,Mr +0,3, Joseph Jr Elias,male,17,1,1,7.2292,Mr +1,3, Catherine (Catherine Rizk) Peter,female,24,0,2,22.3583,Mrs +0,3, Marija Cacic,female,30,0,0,8.6625,Miss +1,2, Eva Miriam Hart,female,7,0,2,26.25,Miss +0,1, Archibald Willingham Butt,male,45,0,0,26.55,Major +1,1, Bertha LeRoy,female,30,0,0,106.425,Miss +0,3, Samuel Beard Risien,male,69,0,0,14.5,Mr +1,1, Hedwig Margaritha Frolicher,female,22,0,2,49.5,Miss +1,1, Harriet R Crosby,female,36,0,2,71,Miss +0,3, Ingeborg Constanzia Andersson,female,9,4,2,31.275,Miss +0,3, Sigrid Elisabeth Andersson,female,11,4,2,31.275,Miss +1,2, Edward Beane,male,32,1,0,26,Mr +0,1, Walter Donald Douglas,male,50,1,0,106.425,Mr +0,1, Arthur Ernest Nicholson,male,64,0,0,26,Mr +1,2, Edward (Ethel Clarke) Beane,female,19,1,0,26,Mrs +1,2, Julian Padro y Manent,male,27,0,0,13.8625,Mr +0,3, Frank John Goldsmith,male,33,1,1,20.525,Mr +1,2, John Morgan Jr Davies,male,8,1,1,36.75,Master +1,1, John Borland Jr Thayer,male,17,0,2,110.8833,Mr +0,2, Percival James R Sharp,male,27,0,0,26,Mr +0,3, Timothy O'Brien,male,21,0,0,7.8292,Mr +1,3, Fahim Leeni,male,22,0,0,7.225,Mr +1,3, Velin Ohman,female,22,0,0,7.775,Miss +0,1, George Wright,male,62,0,0,26.55,Mr +1,1, (Lucille Christiana Sutherland)Duff Gordon,female,48,1,0,39.6,Lady +0,1, Victor Robbins,male,45,0,0,227.525,Mr +1,1, Emil (Tillie Mandelbaum) Taussig,female,39,1,1,79.65,Mrs +1,3, Guillaume Joseph (Emma) de Messemaeker,female,36,1,0,17.4,Mrs +0,3, Thomas Rowan Morrow,male,30,0,0,7.75,Mr +0,3, Husein Sivic,male,40,0,0,7.8958,Mr +0,2, Robert Douglas Norman,male,28,0,0,13.5,Mr +0,3, John Simmons,male,40,0,0,8.05,Mr +0,3, (Marion Ogden) Meanwell,female,62,0,0,8.05,Miss +0,3, Alfred J Davies,male,24,2,0,24.15,Mr +0,3, Ilia Stoytcheff,male,19,0,0,7.8958,Mr +0,3, Nils (Alma Cornelia Berglund) Palsson,female,29,0,4,21.075,Mrs +0,3, Tannous Doharr,male,28,0,0,7.2292,Mr +1,3, Carl Jonsson,male,32,0,0,7.8542,Mr +1,2, George Harris,male,62,0,0,10.5,Mr +1,1, Edward Dale (Charlotte Lamson) Appleton,female,53,2,0,51.4792,Mrs +1,1, John Irwin Flynn,male,36,0,0,26.3875,Mr +1,3, Mary Kelly,female,22,0,0,7.75,Miss +0,3, Alfred George John Rush,male,16,0,0,8.05,Mr +0,3, George Patchett,male,19,0,0,14.5,Mr +1,2, Ethel Garside,female,34,0,0,13,Miss +1,1, William Baird (Alice Munger) Silvey,female,39,1,0,55.9,Mrs +0,3, Joseph (Maria Elias) Caram,female,18,1,0,14.4583,Mrs +1,3, Eiriik Jussila,male,32,0,0,7.925,Mr +1,2, Julie Rachel Christy,female,25,1,1,30,Miss +1,1, John Borland (Marian Longstreth Morris) Thayer,female,39,1,1,110.8833,Mrs +0,2, William James Downton,male,54,0,0,26,Mr +0,1, John Hugo Ross,male,36,0,0,40.125,Mr +0,3, Uscher Paulner,male,16,0,0,8.7125,Mr +1,1, Ruth Taussig,female,18,0,2,79.65,Miss +0,2, John Denzil Jarvis,male,47,0,0,15,Mr +1,1, Maxmillian Frolicher-Stehli,male,60,1,1,79.2,Mr +0,3, Eliezer Gilinski,male,22,0,0,8.05,Mr +0,3, Joseph Murdlin,male,22,0,0,8.05,Mr +0,3, Matti Rintamaki,male,35,0,0,7.125,Mr +1,1, Walter Bertram (Martha Eustis) Stephenson,female,52,1,0,78.2667,Mrs +0,3, William James Elsbury,male,47,0,0,7.25,Mr +0,3, Mary Bourke,female,40,0,2,7.75,Miss +0,2, John Henry Chapman,male,37,1,0,26,Mr +0,3, Jean Baptiste Van Impe,male,36,1,1,24.15,Mr +1,2, Jessie Wills Leitch,female,31,0,0,33,Miss +0,3, Alfred Johnson,male,49,0,0,0,Mr +0,3, Hanna Boulos,male,18,0,0,7.225,Mr +1,1, Cosmo Edmund Duff Gordon,male,49,1,0,56.9292,Sir +1,2, Sidney Samuel (Amy Frances Christy) Jacobsohn,female,24,2,1,27,Mrs +0,3, Petco Slabenoff,male,42,0,0,7.8958,Mr +0,1, Charles H Harrington,male,37,0,0,42.4,Mr +0,3, Ernst William Torber,male,44,0,0,8.05,Mr +1,1, Harry Homer,male,35,0,0,26.55,Mr +0,3, Edvard Bengtsson Lindell,male,36,1,0,15.55,Mr +0,3, Milan Karaic,male,30,0,0,7.8958,Mr +1,1, Robert Williams Daniel,male,27,0,0,30.5,Mr +1,2, Joseph (Juliette Marie Louise Lafargue) Laroche,female,22,1,2,41.5792,Mrs +1,1, Elizabeth W Shutes,female,40,0,0,153.4625,Miss +0,3, Anders Johan (Alfrida Konstantia Brogren) Andersson,female,39,1,5,31.275,Mrs +0,3, Jose Neto Jardin,male,21,0,0,7.05,Mr +1,3, Margaret Jane Murphy,female,18,1,0,15.5,Miss +0,3, John Horgan,male,22,0,0,7.75,Mr +0,3, William Alfred Brocklebank,male,35,0,0,8.05,Mr +1,2, Alice Herman,female,24,1,2,65,Miss +0,3, Ernst Gilbert Danbom,male,34,1,1,14.4,Mr +0,3, William Arthur (Cordelia K Stanlick) Lobb,female,26,1,0,16.1,Mrs +1,2, Marion Louise Becker,female,4,2,1,39,Miss +0,2, Lawrence Gavey,male,26,0,0,10.5,Mr +0,3, Antoni Yasbeck,male,27,1,0,14.4542,Mr +1,1, Edwin Nelson Jr Kimball,male,42,1,0,52.5542,Mr +1,3, Sahid Nakid,male,20,1,1,15.7417,Mr +0,3, Henry Damsgaard Hansen,male,21,0,0,7.8542,Mr +0,3, David John Bowen,male,21,0,0,16.1,Mr +0,1, Frederick Sutton,male,61,0,0,32.3208,Mr +0,2, Charles Leonard Kirkland,male,57,0,0,12.35,Rev +1,1, Gretchen Fiske Longley,female,21,0,0,77.9583,Miss +0,3, Guentcho Bostandyeff,male,26,0,0,7.8958,Mr +0,3, Patrick D O'Connell,male,18,0,0,7.7333,Mr +1,1, Algernon Henry Wilson Barkworth,male,80,0,0,30,Mr +0,3, Johan Svensson Lundahl,male,51,0,0,7.0542,Mr +1,1, Max Stahelin-Maeglin,male,32,0,0,30.5,Dr +0,1, William Henry Marsh Parr,male,30,0,0,0,Mr +0,3, Mabel Skoog,female,9,3,2,27.9,Miss +1,2, Mary Davis,female,28,0,0,13,Miss +0,3, Antti Gustaf Leinonen,male,32,0,0,7.925,Mr +0,2, Harvey Collyer,male,31,1,1,26.25,Mr +0,3, Juha (Maria Emilia Ojala) Panula,female,41,0,5,39.6875,Mrs +0,3, Percival Thorneycroft,male,37,1,0,16.1,Mr +0,3, Hans Peder Jensen,male,20,0,0,7.8542,Mr +1,1, Emma Sagesser,female,24,0,0,69.3,Mlle +0,3, Margit Elizabeth Skoog,female,2,3,2,27.9,Miss +1,3, Choong Foo,male,32,0,0,56.4958,Mr +1,3, Eugenie Baclini,female,0.75,2,1,19.2583,Miss +1,1, Henry Sleeper Harper,male,48,1,0,76.7292,Mr +0,3, Liudevit Cor,male,19,0,0,7.8958,Mr +1,1, Oberst Alfons Simonius-Blumer,male,56,0,0,35.5,Col +0,3, Edward Willey,male,21,0,0,7.55,Mr +1,3, Amy Zillah Elsie Stanley,female,23,0,0,7.55,Miss +0,3, Mito Mitkoff,male,23,0,0,7.8958,Mr +1,2, Elsie Doling,female,18,0,1,23,Miss +0,3, Johannes Halvorsen Kalvik,male,21,0,0,8.4333,Mr +1,3, Hanora O'Leary,female,16,0,0,7.8292,Miss +0,3, Hanora Hegarty,female,18,0,0,6.75,Miss +0,2, Leonard Mark Hickman,male,24,2,0,73.5,Mr +0,3, Alexander Radeff,male,27,0,0,7.8958,Mr +0,3, John (Catherine) Bourke,female,32,1,1,15.5,Mrs +0,2, George Floyd Eitemiller,male,23,0,0,13,Mr +0,1, Arthur Webster Newell,male,58,0,2,113.275,Mr +1,1, Henry William Frauenthal,male,50,2,0,133.65,Dr +0,3, Mohamed Badt,male,40,0,0,7.225,Mr +0,1, Edward Pomeroy Colley,male,47,0,0,25.5875,Mr +0,3, Peju Coleff,male,36,0,0,7.4958,Mr +1,3, Eino William Lindqvist,male,20,1,0,7.925,Mr +0,2, Lewis Hickman,male,32,2,0,73.5,Mr +0,2, Reginald Fenton Butler,male,25,0,0,13,Mr +0,3, Knud Paust Rommetvedt,male,49,0,0,7.775,Mr +0,3, Jacob Cook,male,43,0,0,8.05,Mr +1,1, Elmer Zebley (Juliet Cummins Wright) Taylor,female,48,1,0,52,Mrs +1,2, Thomas William Solomon (Elizabeth Catherine Ford) Brown,female,40,1,1,39,Mrs +0,1, Thornton Davidson,male,31,1,0,52,Mr +0,2, Henry Michael Mitchell,male,70,0,0,10.5,Mr +1,2, Charles Wilhelms,male,31,0,0,13,Mr +0,2, Ennis Hastings Watson,male,19,0,0,0,Mr +0,3, Gustaf Hjalmar Edvardsson,male,18,0,0,7.775,Mr +0,3, Frederick Charles Sawyer,male,24.5,0,0,8.05,Mr +1,3, Anna Sofia Turja,female,18,0,0,9.8417,Miss +0,3, Frederick (Augusta Tyler) Goodwin,female,43,1,6,46.9,Mrs +1,1, Thomas Drake Martinez Cardeza,male,36,0,1,512.3292,Mr +0,3, Katie Peters,female,28,0,0,8.1375,Miss +1,1, Hammad Hassab,male,27,0,0,76.7292,Mr +0,3, Thor Anderson Olsvigen,male,20,0,0,9.225,Mr +0,3, Charles Edward Goodwin,male,14,5,2,46.9,Mr +0,2, Thomas William Solomon Brown,male,60,1,1,39,Mr +0,2, Joseph Philippe Lemercier Laroche,male,25,1,2,41.5792,Mr +0,3, Jaako Arnold Panula,male,14,4,1,39.6875,Mr +0,3, Branko Dakic,male,19,0,0,10.1708,Mr +0,3, Eberhard Thelander Fischer,male,18,0,0,7.7958,Mr +1,1, Georgette Alexandra Madill,female,15,0,1,211.3375,Miss +1,1, Albert Adrian Dick,male,31,1,0,57,Mr +1,3, Manca Karun,female,4,0,1,13.4167,Miss +1,3, Ali Lam,male,37,0,0,56.4958,Mr +0,3, Khalil Saad,male,25,0,0,7.225,Mr +0,1, John Weir,male,60,0,0,26.55,Col +0,2, Charles Henry Chapman,male,52,0,0,13.5,Mr +0,3, James Kelly,male,44,0,0,8.05,Mr +1,3, Katherine Mullens,female,19,0,0,7.7333,Miss +0,1, John Borland Thayer,male,49,1,1,110.8833,Mr +0,3, Adolf Mathias Nicolai Olsen Humblen,male,42,0,0,7.65,Mr +1,1, John Jacob (Madeleine Talmadge Force) Astor,female,18,1,0,227.525,Mrs +1,1, Spencer Victor Silverthorne,male,35,0,0,26.2875,Mr +0,3, Saiide Barbara,female,18,0,1,14.4542,Miss +0,3, Martin Gallagher,male,25,0,0,7.7417,Mr +0,3, Henrik Juul Hansen,male,26,1,0,7.8542,Mr +0,2, Henry Samuel Morley,male,39,0,0,26,Mr +1,2, Florence Kelly,female,45,0,0,13.5,Mrs +1,1, Edward Pennington Calderhead,male,42,0,0,26.2875,Mr +1,1, Alice Cleaver,female,22,0,0,151.55,Miss +1,3, Halim Gonios Moubarek,male,4,1,1,15.2458,Master +1,1, Berthe Antonine Mayne,female,24,0,0,49.5042,Mlle +0,1, Herman Klaber,male,41,0,0,26.55,Mr +1,1, Elmer Zebley Taylor,male,48,1,0,52,Mr +0,3, August Viktor Larsson,male,29,0,0,9.4833,Mr +0,2, Samuel Greenberg,male,52,0,0,13,Mr +0,3, Peter Andreas Lauritz Andersen Soholt,male,19,0,0,7.65,Mr +1,1, Caroline Louise Endres,female,38,0,0,227.525,Miss +1,2, Edwina Celia Troutt,female,27,0,0,10.5,Miss +0,3, Malkolm Joackim Johnson,male,33,0,0,7.775,Mr +1,2, Annie Jessie Harper,female,6,0,1,33,Miss +0,3, Svend Lauritz Jensen,male,17,1,0,7.0542,Mr +0,2, William Henry Gillespie,male,34,0,0,13,Mr +0,2, Henry Price Hodges,male,50,0,0,13,Mr +1,1, Norman Campbell Chambers,male,27,1,0,53.1,Mr +0,3, Luka Oreskovic,male,20,0,0,8.6625,Mr +1,2, Peter Henry (Lillian Jefferys) Renouf,female,30,3,0,21,Mrs +1,3, Margareth Mannion,female,28,0,0,7.7375,Miss +0,2, Kurt Arnold Gottfrid Bryhl,male,25,1,0,26,Mr +0,3, Pieta Sofia Ilmakangas,female,25,1,0,7.925,Miss +1,1, Elisabeth Walton Allen,female,29,0,0,211.3375,Miss +0,3, Houssein G N Hassan,male,11,0,0,18.7875,Mr +0,2, Robert J Knight,male,41,0,0,0,Mr +0,2, William John Berriman,male,23,0,0,13,Mr +0,2, Moses Aaron Troupiansky,male,23,0,0,13,Mr +0,3, Leslie Williams,male,28.5,0,0,16.1,Mr +0,3, Edward (Margaret Ann Watson) Ford,female,48,1,3,34.375,Mrs +1,1, Gustave J Lesurer,male,35,0,0,512.3292,Mr +0,3, Kanio Ivanoff,male,20,0,0,7.8958,Mr +0,3, Minko Nankoff,male,32,0,0,7.8958,Mr +1,1, Walter James Hawksford,male,45,0,0,30,Mr +0,1, Tyrell William Cavendish,male,36,1,0,78.85,Mr +1,1, Susan Parker Ryerson,female,21,2,2,262.375,Miss +0,3, Neal McNamee,male,24,1,0,16.1,Mr +1,3, Juho Stranden,male,31,0,0,7.925,Mr +0,1, Edward Gifford Crosby,male,70,1,1,71,Capt +0,3, Rossmore Edward Abbott,male,16,1,1,20.25,Mr +1,2, Anna Sinkkonen,female,30,0,0,13,Miss +0,1, Daniel Warner Marvin,male,19,1,0,53.1,Mr +0,3, Michael Connaghton,male,31,0,0,7.75,Mr +1,2, Joan Wells,female,4,1,1,23,Miss +1,3, Meier Moor,male,6,0,1,12.475,Master +0,3, Johannes Joseph Vande Velde,male,33,0,0,9.5,Mr +0,3, Lalio Jonkoff,male,23,0,0,7.8958,Mr +1,2, Samuel (Jane Laver) Herman,female,48,1,2,65,Mrs +1,2, Viljo Hamalainen,male,0.67,1,1,14.5,Master +0,3, August Sigfrid Carlsson,male,28,0,0,7.7958,Mr +0,2, Percy Andrew Bailey,male,18,0,0,11.5,Mr +0,3, Thomas Leonard Theobald,male,34,0,0,8.05,Mr +1,1, of (Lucy Noel Martha Dyer-Edwards) Rothes,female,33,0,0,86.5,the Countess +0,3, John Garfirth,male,23,0,0,14.5,Mr +0,3, Iisakki Antino Aijo Nirva,male,41,0,0,7.125,Mr +1,3, Hanna Assi Barah,male,20,0,0,7.2292,Mr +1,1, William Ernest (Lucile Polk) Carter,female,36,1,2,120,Mrs +0,3, Hans Linus Eklund,male,16,0,0,7.775,Mr +1,1, John C (Anna Andrews) Hogeboom,female,51,1,0,77.9583,Mrs +0,1, Arthur Jackson Brewe,male,46,0,0,39.6,Dr +0,3, Mary Mangan,female,30.5,0,0,7.75,Miss +0,3, Daniel J Moran,male,28,1,0,24.15,Mr +0,3, Daniel Danielsen Gronnestad,male,32,0,0,8.3625,Mr +0,3, Rene Aime Lievens,male,24,0,0,9.5,Mr +0,3, Niels Peder Jensen,male,48,0,0,7.8542,Mr +0,2, (Mary) Mack,female,57,0,0,10.5,Mrs +0,3, Dibo Elias,male,29,0,0,7.225,Mr +1,2, Elizabeth (Eliza Needs) Hocking,female,54,1,3,23,Mrs +0,3, Pehr Fabian Oliver Malkolm Myhrman,male,18,0,0,7.75,Mr +0,3, Roger Tobin,male,20,0,0,7.75,Mr +1,3, Virginia Ethel Emanuel,female,5,0,0,12.475,Miss +0,3, Thomas J Kilgannon,male,22,0,0,7.7375,Mr +1,1, Edward Scott (Elisabeth Walton McMillan) Robert,female,43,0,1,211.3375,Mrs +1,3, Banoura Ayoub,female,13,0,0,7.2292,Miss +1,1, Albert Adrian (Vera Gillespie) Dick,female,17,1,0,57,Mrs +0,1, Milton Clyde Long,male,29,0,0,30,Mr +0,3, Andrew G Johnston,male,35,1,2,23.45,Mr +0,3, William Ali,male,25,0,0,7.05,Mr +0,3, Abraham (David Lishin) Harmer,male,25,0,0,7.25,Mr +1,3, Anna Sofia Sjoblom,female,18,0,0,7.4958,Miss +0,3, George Hugh Rice,male,8,4,1,29.125,Master +1,3, Bertram Vere Dean,male,1,1,2,20.575,Master +0,1, Benjamin Guggenheim,male,46,0,0,79.2,Mr +0,3, Andrew Keane,male,20,0,0,7.75,Mr +0,2, Alfred Gaskell,male,16,0,0,26,Mr +0,3, Stella Anna Sage,female,21,8,2,69.55,Miss +0,1, William Fisher Hoyt,male,43,0,0,30.6958,Mr +0,3, Ristiu Dantcheff,male,25,0,0,7.8958,Mr +0,2, Richard Otter,male,39,0,0,13,Mr +1,1, Alice (Farnham) Leader,female,49,0,0,25.9292,Dr +1,3, Mara Osman,female,31,0,0,8.6833,Mrs +0,3, Yousseff Ibrahim Shawah,male,30,0,0,7.2292,Mr +0,3, Jean Baptiste (Rosalie Paula Govaert) Van Impe,female,30,1,1,24.15,Mrs +0,2, Martin Ponesell,male,34,0,0,13,Mr +1,2, Harvey (Charlotte Annie Tate) Collyer,female,31,1,1,26.25,Mrs +1,1, William Thornton II Carter,male,11,1,2,120,Master +1,3, Assad Alexander Thomas,male,0.42,0,1,8.5167,Master +1,3, Oskar Arvid Hedman,male,27,0,0,6.975,Mr +0,3, Karl Johan Johansson,male,31,0,0,7.775,Mr +0,1, Thomas Jr Andrews,male,39,0,0,0,Mr +0,3, Ellen Natalia Pettersson,female,18,0,0,7.775,Miss +0,2, August Meyer,male,39,0,0,13,Mr +1,1, Norman Campbell (Bertha Griggs) Chambers,female,33,1,0,53.1,Mrs +0,3, William Alexander,male,26,0,0,7.8875,Mr +0,3, James Lester,male,39,0,0,24.15,Mr +0,2, Richard James Slemen,male,35,0,0,10.5,Mr +0,3, Ebba Iris Alfrida Andersson,female,6,4,2,31.275,Miss +0,3, Ernest Portage Tomlin,male,30.5,0,0,8.05,Mr +0,1, Richard Fry,male,39,0,0,0,Mr +0,3, Wendla Maria Heininen,female,23,0,0,7.925,Miss +0,2, Albert Mallet,male,31,1,1,37.0042,Mr +0,3, John Fredrik Alexander Holm,male,43,0,0,6.45,Mr +0,3, Karl Thorsten Skoog,male,10,3,2,27.9,Master +1,1, Charles Melville (Clara Jennings Gregg) Hays,female,52,1,1,93.5,Mrs +1,3, Nikola Lulic,male,27,0,0,8.6625,Mr +0,1, John George Reuchlin,male,38,0,0,0,Jonkheer +1,3, (Beila) Moor,female,27,0,1,12.475,Mrs +0,3, Urho Abraham Panula,male,2,4,1,39.6875,Master +0,3, John Flynn,male,36,0,0,6.95,Mr +0,3, Len Lam,male,23,0,0,56.4958,Mr +1,2, Andre Mallet,male,1,0,2,37.0042,Master +1,3, Thomas Joseph McCormack,male,19,0,0,7.75,Mr +1,1, George Nelson (Martha Evelyn) Stone,female,62,0,0,80,Mrs +1,3, Antoni (Selini Alexander) Yasbeck,female,15,1,0,14.4542,Mrs +1,2, George Sibley Richards,male,0.83,1,1,18.75,Master +0,3, Amin Saad,male,30,0,0,7.2292,Mr +0,3, Albert Augustsson,male,23,0,0,7.8542,Mr +0,3, Owen George Allum,male,18,0,0,8.3,Mr +1,1, Sara Rebecca Compton,female,39,1,1,83.1583,Miss +0,3, Jakob Pasic,male,21,0,0,8.6625,Mr +0,3, Maurice Sirota,male,20,0,0,8.05,Mr +1,3, Chang Chip,male,32,0,0,56.4958,Mr +1,1, Pierre Marechal,male,29,0,0,29.7,Mr +0,3, Ilmari Rudolf Alhomaki,male,20,0,0,7.925,Mr +0,2, Thomas Charles Mudd,male,16,0,0,10.5,Mr +1,1, Augusta Serepeca,female,30,0,0,31,Miss +0,3, Peter L Lemberopolous,male,34.5,0,0,6.4375,Mr +0,3, Jeso Culumovic,male,17,0,0,8.6625,Mr +0,3, Anthony Abbing,male,42,0,0,7.55,Mr +0,3, Douglas Bullen Sage,male,18,8,2,69.55,Mr +0,3, Marin Markoff,male,35,0,0,7.8958,Mr +0,2, John Harper,male,28,0,1,33,Rev +1,1, Samuel L (Edwiga Grabowska) Goldenberg,female,40,1,0,89.1042,Mrs +0,3, Sigvard Harald Elias Andersson,male,4,4,2,31.275,Master +0,3, Johan Svensson,male,74,0,0,7.775,Mr +0,3, Nourelain Boulos,female,9,1,1,15.2458,Miss +1,1, Mary Conover Lines,female,16,0,1,39.4,Miss +0,2, Ernest Courtenay (Lilian Hughes) Carter,female,44,1,0,26,Mrs +1,3, Sam (Leah Rosen) Aks,female,18,0,1,9.35,Mrs +1,1, George Dennick (Mary Hitchcock) Wick,female,45,1,1,164.8667,Mrs +1,1, Peter Denis Daly,male,51,0,0,26.55,Mr +1,3, Solomon (Latifa Qurban) Baclini,female,24,0,3,19.2583,Mrs +0,3, Raihed Razi,male,30,0,0,7.2292,Mr +0,3, Claus Peter Hansen,male,41,2,0,14.1083,Mr +0,2, Frederick Edward Giles,male,21,1,0,11.5,Mr +1,1, Frederick Joel (Margaret Welles Barron) Swift,female,48,0,0,25.9292,Mrs +0,3, Dorothy Edith Sage,female,14,8,2,69.55,Miss +0,2, John William Gill,male,24,0,0,13,Mr +1,2, (Karolina) Bystrom,female,42,0,0,13,Mrs +1,2, Asuncion Duran y More,female,27,1,0,13.8583,Miss +0,1, Washington Augustus II Roebling,male,31,0,0,50.4958,Mr +0,3, Philemon van Melkebeke,male,23,0,0,9.5,Mr +1,3, Harold Theodor Johnson,male,4,1,1,11.1333,Master +0,3, Cerin Balkic,male,26,0,0,7.8958,Mr +1,1, Richard Leonard (Sallie Monypeny) Beckwith,female,47,1,1,52.5542,Mrs +0,1, Frans Olof Carlsson,male,33,0,0,5,Mr +0,3, Victor Vander Cruyssen,male,47,0,0,9,Mr +1,2, Samuel (Hannah Wizosky) Abelson,female,28,1,0,24,Mrs +1,3, Adele Kiamie Najib,female,15,0,0,7.225,Miss +0,3, Alfred Ossian Gustafsson,male,20,0,0,9.8458,Mr +0,3, Nedelio Petroff,male,19,0,0,7.8958,Mr +0,3, Kristo Laleff,male,23,0,0,7.8958,Mr +1,1, Thomas Jr (Lily Alexenia Wilson) Potter,female,56,0,1,83.1583,Mrs +1,2, William (Imanita Parrish Hall) Shelley,female,25,0,1,26,Mrs +0,3, Johann Markun,male,33,0,0,7.8958,Mr +0,3, Gerda Ulrika Dahlberg,female,22,0,0,10.5167,Miss +0,2, Frederick James Banfield,male,28,0,0,10.5,Mr +0,3, Henry Jr Sutehall,male,25,0,0,7.05,Mr +0,3, William (Margaret Norton) Rice,female,39,0,5,29.125,Mrs +0,2, Juozas Montvila,male,27,0,0,13,Rev +1,1, Margaret Edith Graham,female,19,0,0,30,Miss +0,3, Catherine Helen Johnston,female,7,1,2,23.45,Miss +1,1, Karl Howell Behr,male,26,0,0,30,Mr +0,3, Patrick Dooley,male,32,0,0,7.75,Mr diff --git a/src/danfojs-node/test/samples/titanicOutRemote.csv b/src/danfojs-node/test/samples/titanicOutRemote.csv new file mode 100644 index 00000000..e69de29b diff --git a/danfojs-node/tests/core/concat.js b/src/danfojs-node/test/transformers/concat.test.ts similarity index 65% rename from danfojs-node/tests/core/concat.js rename to src/danfojs-node/test/transformers/concat.test.ts index 9558d034..0dd84947 100644 --- a/danfojs-node/tests/core/concat.js +++ b/src/danfojs-node/test/transformers/concat.test.ts @@ -1,8 +1,8 @@ import { assert } from "chai"; -import { Series, DataFrame, concat } from "../../dist"; - -describe("Concatenate", function () { +import { describe, it } from "mocha"; +import { DataFrame, concat , Series } from "../../dist/danfojs-node/src"; +describe("Concat", ()=>{ it("Check the axis 0 concatenation", function () { let data = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 20, 30, 40 ], [ 39, 89, 78 ] ]; let cols = [ "A", "B", "C" ]; @@ -16,7 +16,7 @@ describe("Concatenate", function () { let cols2 = [ "A", "B", "C", "D" ]; let df2 = new DataFrame(data2, { columns: cols2 }); - let new_df = concat({ "df_list": [ df, df1, df2 ], "axis": 0 }); + let new_df = concat({ dfList: [ df, df1, df2 ], axis: 0 }); let data_values = [ [ 1, 2, 3, NaN ], [ 4, 5, 6, NaN ], [ 20, 30, 40, NaN ], [ 39, 89, 78, NaN ], [ 1, 2, 3, NaN ], [ 4, 5, 6, NaN ], [ 20, 30, 40, NaN ], [ 39, 89, 78, NaN ], @@ -38,7 +38,7 @@ describe("Concatenate", function () { let cols2 = [ "A", "B", "C", "D" ]; let df2 = new DataFrame(data2, { columns: cols2 }); - let new_df = concat({ "df_list": [ df, df1, df2 ], "axis": 1 }); + let new_df = concat({ dfList: [ df, df1, df2 ], axis: 1 }); let data_values = [ [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 5 ], [ 4, 5, 6, 4, 5, 6, 4, 5, 6, 8 ], [ 20, 30, 40, 20, 30, 40, 20, 30, 40, 10 ], [ 39, 89, 78, 39, 89, 78, NaN, @@ -56,20 +56,18 @@ describe("Concatenate", function () { let df = new DataFrame(data, { columns: cols }); let s1 = new Series(data1); - let s2 = new Series(data2); let rslt = [ - [ 1, 2, 3, NaN ], - [ 4, 5, 6, NaN ], - [ 20, 30, 40, NaN ], - [ 39, 89, 78, NaN ], - [ NaN, NaN, NaN, 1 ], - [ NaN, NaN, NaN, 2 ], - [ NaN, NaN, NaN, 3 ], - [ NaN, NaN, NaN, 4 ] + [ NaN, 1, 2, 3 ], + [ NaN, 4, 5, 6 ], + [ NaN, 20, 30, 40], + [ NaN, 39, 89, 78 ], + [ 1, NaN, NaN, NaN ], + [ 2, NaN, NaN, NaN ], + [ 3, NaN, NaN, NaN], + [ 4, NaN, NaN, NaN ] ]; - - let con = concat({ "df_list": [ df, s1 ], "axis": 0 }); + let con = concat({ dfList: [ df, s1 ], axis: 0 }); assert.deepEqual(con.values, rslt); @@ -84,14 +82,14 @@ describe("Concatenate", function () { let data1 = [ 1, 2, 3, 4 ]; let s1 = new Series(data1); let rslt = [ - [ 1, 2, 3, 1 ], - [ 4, 5, 6, 2 ], - [ 20, 30, 40, 3 ], - [ 39, 89, 78, 4 ] + [ 1, 1, 2, 3 ], + [ 2, 4, 5, 6 ], + [ 3, 20, 30, 40 ], + [ 4, 39, 89, 78] ]; - let con = concat({ "df_list": [ df, s1 ], "axis": 1 }); + let con = concat({ dfList: [ df, s1 ], axis: 1 }); assert.deepEqual(con.values, rslt); @@ -106,7 +104,7 @@ describe("Concatenate", function () { let rslt = [ [ 1, 3 ], [ 2, 4 ], [ 3, 5 ], [ 4, 6 ] ]; - let con = concat({ "df_list": [ s1, s2 ], "axis": 1 }); + let con = concat({ dfList: [ s1, s2 ], axis: 1 }); assert.deepEqual(con.values, rslt); @@ -123,38 +121,10 @@ describe("Concatenate", function () { 3, 4, 5, 6 ]; - let con = concat({ "df_list": [ s1, s2 ], "axis": 0 }); + let con = concat({ dfList: [ s1, s2 ], axis: 0 }); assert.deepEqual(con.values, rslt); }); - it("test if df_list is an array", function(){ - - assert.throws(function () { concat({ "df_list":23, "axis":0 }); }, Error, 'df_list must be an Array of dataFrames/Series'); - - }); - it("assign default axis for concating", function(){ - let data1 = [ 1, 2, 3, 4 ]; - let data2 = [ 3, 4, 5, 6 ]; - - let s1 = new Series(data1); - let s2 = new Series(data2); - let rslt = [ [ 1, 3 ], [ 2, 4 ], [ 3, 5 ], [ 4, 6 ] ]; - - - let con = concat({ "df_list": [ s1, s2 ], "axis": 12 }); - - assert.deepEqual(con.values, rslt); - }); - it("ensure axis is a number", function(){ - let data1 = [ 1, 2, 3, 4 ]; - let data2 = [ 3, 4, 5, 6 ]; - - let s1 = new Series(data1); - let s2 = new Series(data2); - - assert.throws(function () { concat({ "df_list":[ s1, s2 ], "axis":"r" }); }, Error, 'axis must be a number'); - }); - -}); +}) \ No newline at end of file diff --git a/src/danfojs-node/test/transformers/csv.stream.transformer.test.ts b/src/danfojs-node/test/transformers/csv.stream.transformer.test.ts new file mode 100644 index 00000000..f4207a98 --- /dev/null +++ b/src/danfojs-node/test/transformers/csv.stream.transformer.test.ts @@ -0,0 +1,63 @@ +import { DataFrame, Series, streamCsvTransformer } from "../../dist/danfojs-node/src"; +import stream from "stream" +import path from "path" +import { describe, it } from "mocha"; + +describe("pipeCsvTransform", function () { + it("streamCsvTransformer works for local files", async function () { + const inputFilePath = path.join(process.cwd(), "test", "samples", "titanic.csv"); + const outputFilePath = path.join(process.cwd(), "test", "samples", "titanicOutLocal.csv"); + + const transformer = (df: DataFrame) => { + const titles = df["Name"].map((name: string) => name.split(".")[0]); + const names = df["Name"].map((name: string) => name.split(".")[1]); + df["Name"] = names + df.addColumn("titles", titles, { inplace: true }) + return df + } + streamCsvTransformer(inputFilePath, transformer, { outputFilePath, inputStreamOptions: { header: false } }) + }); + + // it("streamCsvTransformer works for remote files", async function () { + // const inputFilePath = "https://raw.githubusercontent.com/opensource9ja/danfojs/dev/danfojs-node/tests/samples/titanic.csv" + // const outputFilePath = path.join(process.cwd(), "test", "samples", "titanicOutRemote.csv"); + // const transformer = (df: DataFrame) => { + // const titles = df["Name"].map((name: string) => name.split(".")[0]); + // const names = df["Name"].map((name: string) => name.split(".")[1]); + // df["Name"] = names + // df.addColumn("titles", titles, { inplace: true }) + // return df + // } + // streamCsvTransformer(inputFilePath, transformer, { outputFilePath, inputStreamOptions: { header: true } }) + // }); + + // it("streamCsvTransformer works for custom writers", async function () { + // const inputFilePath = "https://raw.githubusercontent.com/opensource9ja/danfojs/dev/danfojs-node/tests/samples/titanic.csv" + // const transformer = (df: DataFrame) => { + // const titles = df["Name"].map((name: string) => name.split(".")[0]); + // const names = df["Name"].map((name: string) => name.split(".")[1]); + // df["Name"] = names + // df.addColumn("titles", titles, { inplace: true }) + // return df + // } + // let count = 0 + + // const customWriter = function () { + // const csvOutputStream = new stream.Writable({ objectMode: true }) + // csvOutputStream._write = (chunk: DataFrame | Series, encoding, callback) => { + // count += 1 + // callback() + + // } + // return csvOutputStream + // } + + // streamCsvTransformer( + // inputFilePath, + // transformer, + // { + // customCSVStreamWriter: customWriter, + // inputStreamOptions: { header: true } + // }) + // }); +}) diff --git a/src/danfojs-node/test/transformers/dummy.encoder.test.ts b/src/danfojs-node/test/transformers/dummy.encoder.test.ts new file mode 100644 index 00000000..3ed921a3 --- /dev/null +++ b/src/danfojs-node/test/transformers/dummy.encoder.test.ts @@ -0,0 +1,177 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, Series, getDummies } from "../../dist/danfojs-node/src"; + +describe("DummyEncoder", function () { + it("getDummies works on Series", function () { + + const data = ["dog", "male", "female", "male", "female", "male", "dog"]; + const series = new Series(data); + const df = getDummies(series, { prefix: "test", prefixSeparator: "/" }); + + const dfValues = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [0, 1, 0], + [0, 0, 1], + [0, 1, 0], + [1, 0, 0] + ]; + const dfColumns = ['test/dog', 'test/male', 'test/female']; + assert.deepEqual(df.values, dfValues); + assert.deepEqual(df.columns, dfColumns); + }); + it("getDummies works on Series with default prefix and prefixSeperator", function () { + + const data = ["dog", "male", "female", "male", "female", "male", "dog"]; + const series = new Series(data); + const df = getDummies(series); + + const dfValues = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [0, 1, 0], + [0, 0, 1], + [0, 1, 0], + [1, 0, 0] + ]; + const dfColumns = ['0_dog', '1_male', '2_female']; + assert.deepEqual(df.values, dfValues); + assert.deepEqual(df.columns, dfColumns); + }); + + it("getDummies works on DataFrame", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + const df1 = getDummies(df, { prefixSeparator: ["_", "#"], columns: ["A", "d"], prefix: "test" }); + const expectedColumns = ['B', 'C', 'test_1', 'test_3', 'test_4', 'test#fat', 'test#good', 'test#best'] + const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], + ['fog', 2.0, 0, 1, 0, 0, 1, 0], + ['gof', 3.0, 0, 0, 1, 0, 0, 1]] + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + it("Throw error if the prefix specified is not equal to the column specified", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + assert.throws(function () { getDummies(df, { prefix: ["fg"], prefixSeparator: "_", columns: ["A", "d"] }); }, Error, + `ParamError: prefix and data array must be of the same length. If you need to use the same prefix, then pass a string param instead. e.g {prefix: "fg"}`); + + }); + it("replace column sepecified with prefix", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + const df1 = getDummies(df, { prefix: ["F", "G"], prefixSeparator: "_", columns: ["A", "d"] }); + const expectedColumns = [ + 'B', 'C', + 'F_1', 'F_3', + 'F_4', 'G_fat', + 'G_good', 'G_best' + ]; + + const expected = [['dog', 1.0, 1, 0, 0, 1, 0, 0], + ['fog', 2.0, 0, 1, 0, 0, 1, 0], + ['gof', 3.0, 0, 0, 1, 0, 0, 1]] + + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("getDummies auto infers and encode columns with string dtype", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + + const df1 = getDummies(df, { prefixSeparator: "_" }); + const expectedColumns = [ + 'A', 'C', + 'B_dog', 'B_fog', + 'B_gof', 'd_fat', + 'd_good', 'd_best' + ]; + const expected = [ + [ + 1, 1, 1, 0, + 0, 1, 0, 0 + ], + [ + 3, 2, 0, 1, + 0, 0, 1, 0 + ], + [ + 4, 3, 0, 0, + 1, 0, 0, 1 + ] + ]; + assert.deepEqual(df1.values, expected); + assert.deepEqual(df1.columns, expectedColumns); + + }); + + it("should one hot encode all other columns", function () { + + const data = [[1, "dog", 1.0, "fat"], [3, "fog", 2.0, "good"], [4, "gof", 3.0, "best"]]; + const columns = ["A", "B", "C", "d"]; + const df = new DataFrame(data, { columns: columns }); + const rslt = [ + [1, 'dog', 1, 1, 0, 0], + [3, 'fog', 2, 0, 1, 0], + [4, 'gof', 3, 0, 0, 1] + ] + + assert.deepEqual(getDummies(df, { columns: ["d"] }).values, rslt) + + }); + + + it("Dummification works for object DF", function () { + + let data = { + fruits: ['pear', 'mango', "pawpaw", "mango", "bean"], + Count: [20, 30, 89, 12, 30], + Country: ["NG", "NG", "GH", "RU", "RU"] + }; + + let df = new DataFrame(data); + const expected = [ + [ + 20, 1, 0, 0, + 0, 1, 0, 0 + ], + [ + 30, 0, 1, 0, + 0, 1, 0, 0 + ], + [ + 89, 0, 0, 1, + 0, 0, 1, 0 + ], + [ + 12, 0, 1, 0, + 0, 0, 0, 1 + ], + [ + 30, 0, 0, 0, + 1, 0, 0, 1 + ] + ]; + + let dum_df = getDummies(df, { prefixSeparator: "_" }); + assert.deepEqual(dum_df.values, expected); + + }); +}); diff --git a/src/danfojs-node/test/transformers/label.encoder.test.ts b/src/danfojs-node/test/transformers/label.encoder.test.ts new file mode 100644 index 00000000..1eda8862 --- /dev/null +++ b/src/danfojs-node/test/transformers/label.encoder.test.ts @@ -0,0 +1,53 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, Series, LabelEncoder } from "../../dist/danfojs-node/src"; + +describe("LabelEncoder", function () { + + it("LabelEncoder works for Series", function () { + const sf = new Series([1, 2, 2, 6]) + const scaler = new LabelEncoder(); + scaler.fit(sf); + const expected = [0, 1, 1, 2]; + assert.deepEqual((scaler.transform(sf) as Series).values, expected); + }); + it("LabelEncoder works for values not found", function () { + const sf = new Series([1, 2, 2, 6]) + const scaler = new LabelEncoder(); + scaler.fit(sf); + + const expected = [0, 1, 1, 2, -1]; + assert.deepEqual((scaler.transform(new Series([1, 2, 2, 6, 7])) as Series).values, expected); + }); + it("LabelEncoder works for 1D array", function () { + const sf = [1, 2, 2, "boy", "git", "git"] + const scaler = new LabelEncoder(); + scaler.fit(sf); + const expected = [0, 1, 1, 2, 3, 3] + assert.deepEqual(scaler.transform(sf), expected); + }); + it("fitTransform works for 1D array", function () { + const sf = [1, 2, 2, "boy", "git", "git"] + const scaler = new LabelEncoder(); + const result = scaler.fitTransform(sf) + const expected = [0, 1, 1, 2, 3, 3] + assert.deepEqual(result, expected); + }); + it("inverseTransform works for 1D array", function () { + const sf = [1, 2, 2, "boy", "git", "git"] + const scaler = new LabelEncoder(); + scaler.fit(sf); + const result = scaler.inverseTransform([0, 1, 1, 2, 3, 3]) + assert.deepEqual(result, [1, 2, 2, "boy", "git", "git"]); + }); + it("Get properties from LabelEncoder", function () { + const sf = [1, 2, 2, "boy", "git", "git"] + const scaler = new LabelEncoder(); + scaler.fit(sf); + const classes = scaler.classes + const nClasses = scaler.nClasses + + assert.deepEqual(classes, { 1: 0, 2: 1, boy: 2, git: 3 }); + assert.equal(nClasses, 4) + }); +}); diff --git a/danfojs-node/tests/core/merge.js b/src/danfojs-node/test/transformers/merge.test.ts similarity index 87% rename from danfojs-node/tests/core/merge.js rename to src/danfojs-node/test/transformers/merge.test.ts index 494b3b32..809701e3 100644 --- a/danfojs-node/tests/core/merge.js +++ b/src/danfojs-node/test/transformers/merge.test.ts @@ -1,5 +1,7 @@ import { assert } from "chai"; -import { DataFrame, merge } from "../../dist"; +import { describe, it } from "mocha"; +import { DataFrame, merge } from "../../dist/danfojs-node/src"; + describe("Merge", function () { @@ -15,7 +17,7 @@ describe("Merge", function () { let df1 = new DataFrame(data, { columns: colum1 }); let df2 = new DataFrame(data2, { columns: colum2 }); - let merge_df = merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "outer" }); + let merge_df = merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "outer" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], @@ -26,7 +28,6 @@ describe("Merge", function () { [ 'K2', 'K0', NaN, NaN, 'C3', 'D3' ] ]; - assert.deepEqual(merge_df.values, output_data); }); @@ -42,7 +43,7 @@ describe("Merge", function () { let df1 = new DataFrame(data, { columns: colum1 }); let df2 = new DataFrame(data2, { columns: colum2 }); - let merge_df = merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "inner" }); + let merge_df = merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "inner" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], @@ -65,7 +66,7 @@ describe("Merge", function () { let df1 = new DataFrame(data, { columns: colum1 }); let df2 = new DataFrame(data2, { columns: colum2 }); - let merge_df = merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "left" }); + let merge_df = merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "left" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], @@ -90,7 +91,7 @@ describe("Merge", function () { let df1 = new DataFrame(data, { columns: colum1 }); let df2 = new DataFrame(data2, { columns: colum2 }); - let merge_df = merge({ "left": df1, "right": df2, "on": [ "Key1", "Key2" ], "how": "right" }); + let merge_df = merge({ left: df1, right: df2, on: [ "Key1", "Key2" ], how: "right" }); let output_data = [ [ 'K0', 'k0', 'A0', 'B0', 'C0', 'D0' ], @@ -101,4 +102,5 @@ describe("Merge", function () { assert.deepEqual(merge_df.values, output_data); }); -}); +}) + diff --git a/src/danfojs-node/test/transformers/min.max.scaler.test.ts b/src/danfojs-node/test/transformers/min.max.scaler.test.ts new file mode 100644 index 00000000..8c32340b --- /dev/null +++ b/src/danfojs-node/test/transformers/min.max.scaler.test.ts @@ -0,0 +1,56 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, Series, MinMaxScaler } from "../../dist/danfojs-node/src"; + +describe("MinMaxscaler", function () { + + it("Standardize values in a DataFrame using a MinMaxScaler", function () { + const data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]; + const scaler = new MinMaxScaler(); + + const expected = [[0, 0], [0.25, 0.25], [0.5, 0.5], [1, 1]]; + const transformedData = [[1.5, 0.]]; + + scaler.fit(new DataFrame(data)); + const resultDf = scaler.transform(new DataFrame(data)) as DataFrame; + assert.deepEqual(resultDf.values, expected); + assert.deepEqual(scaler.transform([[2, 2]]) as any, transformedData); + }); + it("fitTransform using a MinMaxScaler", function () { + const data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]; + const scaler = new MinMaxScaler(); + const resultDf = scaler.fitTransform(new DataFrame(data)) as DataFrame; + + const expected = [[0, 0], [0.25, 0.25], [0.5, 0.5], [1, 1]]; + assert.deepEqual(resultDf.values, expected); + }); + it("InverseTransform with MinMaxScaler", function () { + const scaler = new MinMaxScaler(); + scaler.fit([1, 2, 3, 4, 5]) + const resultTransform = scaler.transform([1, 2, 3, 4, 5]) + const resultInverse = scaler.inverseTransform([0, 0.25, 0.5, 0.75, 1]) + + assert.deepEqual(resultTransform, [0, 0.25, 0.5, 0.75, 1]); + assert.deepEqual([1, 2, 3, 4, 5], resultInverse); + }); + it("Index and columns are kept after transformation", function () { + const data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]; + const df = new DataFrame(data, { index: [1, 2, 3, 4], columns: ["a", "b"] }); + + const scaler = new MinMaxScaler(); + scaler.fit(df); + const resultDf = scaler.transform(df) as DataFrame + + assert.deepEqual(resultDf.index, [1, 2, 3, 4]); + assert.deepEqual(resultDf.columns, ["a", "b"]); + }); + it("Standardize values in a Series using a MinMaxScaler", function () { + const data = [-1, 2, -0.5, 60, 101, 18]; + const scaler = new MinMaxScaler(); + const result = [0, 0.029411764815449715, 0.0049019609577953815, 0.5980392098426819, 1, 0.18627451360225677]; + const transformedData = [0.029411764815449715, 0.029411764815449715]; + scaler.fit(new Series(data)) + assert.deepEqual((scaler.transform(new Series(data)) as Series).values, result); + assert.deepEqual(scaler.transform([2, 2]), transformedData); + }); +}); diff --git a/src/danfojs-node/test/transformers/one.hot.encoder.test.ts b/src/danfojs-node/test/transformers/one.hot.encoder.test.ts new file mode 100644 index 00000000..9885a89a --- /dev/null +++ b/src/danfojs-node/test/transformers/one.hot.encoder.test.ts @@ -0,0 +1,84 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { Series, OneHotEncoder, DataFrame } from "../../dist/danfojs-node/src"; + +describe("OneHotEncoder", function () { + it("OneHotEncoder works on array", function () { + const data = ["dog", "cat", "man", "dog", "cat", "man", "man", "cat"]; + const encode = new OneHotEncoder(); + encode.fit(data) + + const expected = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [0, 0, 1], + [0, 1, 0] + ]; + assert.deepEqual(encode.transform(data), expected); + assert.deepEqual(encode.transform(["man", "cat"]), [[0, 0, 1], [0, 1, 0]]); + }); + it("OneHotEncoder works on Series", function () { + const data = ["dog", "cat", "man", "dog", "cat", "man", "man", "cat"]; + const series = new Series(data); + const encoder = new OneHotEncoder(); + encoder.fit(series); + + const expected = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [0, 0, 1], + [0, 1, 0] + ]; + assert.deepEqual((encoder.transform(series) as DataFrame).values, expected); + }); + + it("fitTransform works on OneHotEncoder", function () { + const data = ["dog", "cat", "man", "dog", "cat", "man", "man", "cat"]; + const series = new Series(data); + const encoder = new OneHotEncoder(); + const result = encoder.fitTransform(series) as DataFrame + + const expected = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [0, 0, 1], + [0, 1, 0] + ]; + assert.deepEqual(result.values, expected); + }); + + it("Correct index is returned after transformation", function () { + const data = ["dog", "cat", "man", "dog", "cat", "man", "man", "cat"]; + const series = new Series(data, + { index: ["a", "b", "c", "d", "e", "f", "g", "h"], + }); + const encoder = new OneHotEncoder(); + const result = encoder.fitTransform(series) as DataFrame + + const expected = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [0, 0, 1], + [0, 1, 0] + ]; + assert.deepEqual(result.values, expected); + assert.deepEqual(result.index, ["a", "b", "c", "d", "e", "f", "g", "h"]); + assert.deepEqual(result.columns, ["0", "1", "2"]); + }); +}); diff --git a/src/danfojs-node/test/transformers/standard.scaler.test.ts b/src/danfojs-node/test/transformers/standard.scaler.test.ts new file mode 100644 index 00000000..ffe2d955 --- /dev/null +++ b/src/danfojs-node/test/transformers/standard.scaler.test.ts @@ -0,0 +1,58 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { DataFrame, Series, StandardScaler } from "../../dist/danfojs-node/src"; + + +describe("StandardScaler", function () { + + it("StandardScaler works for DataFrame", function () { + const data = [[0, 0], [0, 0], [1, 1], [1, 1]]; + + const scaler = new StandardScaler(); + scaler.fit(new DataFrame(data)) + + const expected = [[-1, -1], [-1, -1], [1, 1], [1, 1]]; + const resultDf = scaler.transform(new DataFrame(data)) as DataFrame + assert.deepEqual(resultDf.values, expected); + assert.deepEqual(scaler.transform([[2, 2]]) as any, [[3, 3]]); + }); + it("fitTransform works for StandardScaler", function () { + const data = [[0, 0], [0, 0], [1, 1], [1, 1]]; + + const scaler = new StandardScaler(); + const resultDf = scaler.fitTransform(new DataFrame(data)) as DataFrame; + + const expected = [[-1, -1], [-1, -1], [1, 1], [1, 1]]; + assert.deepEqual(resultDf.values, expected); + }); + it("inverseTransform works for StandardScaler", function () { + const data = [[0, 0], [0, 0], [1, 1], [1, 1]]; + + const scaler = new StandardScaler(); + scaler.fit(new DataFrame(data)) + const resultDf = scaler.inverseTransform([[-1, -1], [-1, -1], [1, 1], [1, 1]]) as any + + assert.deepEqual(resultDf, data); + }); + it("StandardScaler works for Array", function () { + const data = [[0, 0], [0, 0], [1, 1], [1, 1]]; + + const scaler = new StandardScaler(); + scaler.fit(data) + const expected = [[-1, -1], [-1, -1], [1, 1], [1, 1]]; + + assert.deepEqual(scaler.transform(data) as any, expected); + assert.deepEqual(scaler.transform([[2, 2]]) as any, [[3, 3]]); + }); + + it("StandardScaler works for Series", function () { + const data = [0, 0, 0, 0, 1, 1, 1, 1] + + const scaler = new StandardScaler(); + scaler.fit(new Series(data)) + const expected = [-1, -1, -1, -1, 1, 1, 1, 1] + + assert.deepEqual((scaler.transform(new Series(data)) as Series).values, expected); + assert.deepEqual(scaler.transform([2, 2]), [3, 3]); + }); +}); diff --git a/src/danfojs-node/test/utils.test.ts b/src/danfojs-node/test/utils.test.ts new file mode 100644 index 00000000..0a8da92d --- /dev/null +++ b/src/danfojs-node/test/utils.test.ts @@ -0,0 +1,281 @@ +import { assert } from "chai"; +import { describe, it } from "mocha"; +import { ArrayType1D } from "../dist/danfojs-base/shared/types"; +import { Utils, __version } from "../dist/danfojs-node/src"; +import packagejson from "../package.json"; + +const pversion = packagejson.version; + +const utils = new Utils(); + +describe("Utils", function () { + it("should have a version", function () { + assert.equal(__version, pversion); + }); + + it("removes an element from an array", function () { + let arr = [1, 2, 3, 4]; + assert.deepEqual(utils.removeElementFromArray(arr, 2), [1, 2, 4]); + }); + + it("Checks if variable is a string", function () { + let arr = ["1", "2"]; + assert.isTrue(utils.isString(arr[0])); + }); + + it("Checks if variable is a number", function () { + let arr = [1, 2, 3, 4]; + assert.isTrue(utils.isNumber(arr[0])); + }); + + it("Checks if value is null", function () { + let val = null; + let val2 = 1; + assert.isTrue(utils.isNull(val)); + assert.isFalse(utils.isNull(val2)); + }); + + it("Checks if value is undefined", function () { + let arr; + assert.isTrue(utils.isUndefined(arr)); + }); + + describe("isEmpty", function () { + it("should return true for null values", function () { + assert.isTrue(utils.isEmpty(null)); + }); + + it("should return true for undefined values", function () { + assert.isTrue(utils.isEmpty(undefined)); + }); + + it("should return true for NaN values", function () { + assert.isTrue(utils.isEmpty(NaN)); + }); + + it("should return false for strings (including empty strings)", function () { + assert.isFalse(utils.isEmpty("")); + assert.isFalse(utils.isEmpty(" ")); + assert.isFalse(utils.isEmpty("hello")); + }); + + it("should return false for numbers (except NaN)", function () { + assert.isFalse(utils.isEmpty(0)); + assert.isFalse(utils.isEmpty(-1)); + assert.isFalse(utils.isEmpty(42.5)); + }); + + it("should return false for BigInt values", function () { + assert.isFalse(utils.isEmpty(BigInt(9007199254740991))); + assert.isFalse(utils.isEmpty(BigInt(0))); + }); + + it("should return false for objects and arrays", function () { + assert.isFalse(utils.isEmpty({})); + assert.isFalse(utils.isEmpty([])); + assert.isFalse(utils.isEmpty({ key: "value" })); + assert.isFalse(utils.isEmpty([1, 2, 3])); + }); + + it("should return false for boolean values", function () { + assert.isFalse(utils.isEmpty(true)); + assert.isFalse(utils.isEmpty(false)); + }); + }); + + it("Checks if value is a valid Date object", function () { + let date1 = new Date(); + let date2 = "2021-01-01 00:00:00"; + let isoDate = "2021-01-01T00:00:00.000Z"; + + assert.isTrue(utils.isDate(date1)); + assert.isTrue(utils.isDate(date2)); + assert.isTrue(utils.isDate(isoDate)); + }); + + it("Generate numbers between two set of values [both inclusive]", function () { + let start = 0; + let end = 5; + let data = [0, 1, 2, 3, 4, 5]; + assert.deepEqual(utils.range(start, end), data); + }); + + it("transposes an array", function () { + let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40]]; + let result = [[1, 4, 20], [2, 5, 30], [3, 6, 40]]; + assert.deepEqual(utils.transposeArray(data), result); + }); + + describe("inferDtype", function () { + it("Returns string type present in an 1D array", function () { + let data = ['Alice', 'Boy', 'Girl', "39"]; + let result = ['string']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns float type present in an 1D array", function () { + let data = [1.1, 2.1, 3.2, 4.4]; + let result = ['float32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns int type present in an 1D array", function () { + let data = [1, 2, 3, 45]; + let result = ['int32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + it("Returns float when there's a mixture of int and float in a 1D array", function () { + let data = [1, 2.1, 3, 45]; + let result = ['float32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns float type when NaN is present in an 1D array", function () { + let data = [1, 2, 3, 45, NaN]; + let result = ['float32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns correct dtype if NaN present in data", function () { + let data = utils.transposeArray([ + [18.7, 17.4, 18, NaN, 19.3], + [20, NaN, 19, 18, 20]]) + let result = ['float32', 'float32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns the data type present in an 2D array", function () { + let data = utils.transposeArray([['Alice', 'Boy', 'Girl', "39"], [2, 5, 30, 89], [3.1, 6.1, 40.1, 78.2]]) + let result = ['string', 'int32', 'float32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns the string dtype when there's a mixture of dtypes in a 2D array", function () { + let data = utils.transposeArray([['Alice', 'Boy', 'Girl', 21], [2, 5, 30, "hey"], [3, 6, 40.1, 78.2]]) + let result = ['string', 'string', 'float32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns bool type in a 1D array", function () { + let data = [true, true, false, false, false, true]; + let result = ['boolean']; + assert.deepEqual(utils.inferDtype(data), result); + }); + it("Returns bool type in a 2D array", function () { + let data = utils.transposeArray([[true, false, true], ["boy", "girl", "man"], [20, 30, 24]]) + let result = ['boolean', 'string', 'int32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + it("Returns string type if values are all NaN", function () { + let data = utils.transposeArray([[true, false, true], ["boy", "girl", "boy"], [NaN, NaN, NaN]]) + let result = ['boolean', 'string', 'float32']; + assert.deepEqual(utils.inferDtype(data), result); + }); + + }); + + describe("mapIntegersToBooleans", function () { + it("map ints to bools in array of arrays", function () { + let data = [[1, 0, 1], [1, 1, 0]]; + assert.deepEqual(utils.mapIntegersToBooleans(data, 2), [[true, false, true], [true, true, false]]); + }); + + it("map ints to bools in array", function () { + let data = [1, 0, 0, 1, 1]; + assert.deepEqual(utils.mapIntegersToBooleans(data, 1), [true, false, false, true, true]); + }); + }); + + describe("round", function () { + it("round elements in array to 1 dp", function () { + let data = [10.01, 2.2, 3.11, 20.505, 20.22, 40.0909]; + assert.deepEqual(utils.round(data, 1, true), [10.0, 2.2, 3.1, 20.5, 20.2, 40.1]); + }); + + it("round elements in array to 2 dp", function () { + let data = [10.019, 2.2099, 3.1145, 20.506, 20.22, 40.0909]; + assert.deepEqual(utils.round(data, 2, true), [10.02, 2.21, 3.11, 20.51, 20.22, 40.09]); + }); + }); + + describe("replaceUndefinedWithNaN", function () { + it("replace undefined in Series with NaN", function () { + let data = [10.01, 2.2, undefined, 20.505, 20.22, undefined] as ArrayType1D; + assert.deepEqual(utils.replaceUndefinedWithNaN(data, true), [10.01, 2.2, NaN, 20.505, 20.22, NaN]); + }); + + it("replace undefined in DataFrame with NaN", function () { + let data = [[10.01, 2.2, undefined, 20.505, 20.22, undefined] as ArrayType1D, + [10.01, undefined, undefined, 20.505, 20, undefined] as ArrayType1D]; + + let result = [[10.01, 2.2, NaN, 20.505, 20.22, NaN], + [10.01, NaN, NaN, 20.505, 20, NaN]]; + assert.deepEqual(utils.replaceUndefinedWithNaN(data, false), result); + }); + + it("replace null in Series with NaN", function () { + let data = [10.01, 2.2, null, 20.505, 20.22, null] as ArrayType1D; + assert.deepEqual(utils.replaceUndefinedWithNaN(data, true), [10.01, 2.2, NaN, 20.505, 20.22, NaN]); + }); + + it("replace null in DataFrame with NaN", function () { + let data = [[10.01, 2.2, null, 20.505, 20.22, null] as ArrayType1D, + [10.01, null, null, 20.505, 20, null] as ArrayType1D]; + + let result = [[10.01, 2.2, NaN, 20.505, 20.22, NaN], + [10.01, NaN, NaN, 20.505, 20, NaN]]; + assert.deepEqual(utils.replaceUndefinedWithNaN(data, false), result); + }); + }); + + describe("convert2DArrayToSeriesArray", function () { + it("convert 2D array of array to 1D of string values", function () { + let data = [[10.01, 2.2, "a"], [20.505, 20.22, "boy"]]; + assert.deepEqual(utils.convert2DArrayToSeriesArray(data), ["10.01,2.2,a", "20.505,20.22,boy"]); + }); + + }); + + describe("throwErrorOnWrongParams", function () { + it("check if the right params are passed to a function", function () { + let paramsNeeded = ["replace", "with", "inplace"] + let kwargs = { "replae": 2, "with": 12, "inplace": true } + + assert.throws(() => { + utils.throwErrorOnWrongParams(kwargs, paramsNeeded) + }, Error, `Params Error: Required parameter not found. Your params must include the following [${paramsNeeded}]`); + }) + + it("check if the right params are passed to a function 2", function () { + let paramsNeeded = ["replace", "with", "inplace"] + let kwargs = { "replace": 2, "with": 12, "inplace": true } + utils.throwErrorOnWrongParams(kwargs, paramsNeeded) + }) + + }) + + describe("getRowAndColValues", function () { + it("retreive rows and labels from column object", function () { + let data = { "Alpha": ["A", "B", "C", "D"], count: [1, 2, 3, 4], sum: [20.3, 30.456, 40.90, 90.1] }; + let res = [["A", 1, 20.3], ["B", 2, 30.456], ["C", 3, 40.90], ["D", 4, 90.1]]; + assert.deepEqual(utils.getRowAndColValues(data)[0], res as any); + assert.deepEqual(utils.getRowAndColValues(data)[1], ["Alpha", "count", "sum"]); + }); + + }); + + + describe("getDuplicate", function () { + it("obtain duplicates and their index", function () { + let data = [1, 2, 3, 4, 5, 3, 4, 6, 4, 5]; + let res = { + '3': { count: 2, index: [2, 5] }, + '4': { count: 3, index: [3, 6, 8] }, + '5': { count: 2, index: [4, 9] } + }; + assert.deepEqual(utils.getDuplicate(data), res); + }); + }); + +}); diff --git a/src/danfojs-node/tsconfig.json b/src/danfojs-node/tsconfig.json new file mode 100644 index 00000000..3c52c2a7 --- /dev/null +++ b/src/danfojs-node/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "lib": ["es6", "DOM"], /* Specify library files to be included in the compilation. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + "outDir": "./dist", /* Redirect output structure to the directory. */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "resolveJsonModule": true, /* Include modules imported with '.json' extension */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ + "declaration": true, + "baseUrl": "./src", + }, + "include": [ + "./src/**/*" +], +"exclude": [ + "test.ts", + "**/*.spec.ts" +] +} diff --git a/src/danfojs-node/yarn-error.log b/src/danfojs-node/yarn-error.log new file mode 100644 index 00000000..eecc46ae --- /dev/null +++ b/src/danfojs-node/yarn-error.log @@ -0,0 +1,5663 @@ +Arguments: + /usr/local/bin/node /usr/local/Cellar/yarn/1.22.5/libexec/bin/yarn.js test + +PATH: + /Users/mac/.poetry/bin:/Users/mac/Downloads/google-cloud-sdk/bin:/Users/mac/opt/anaconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin + +Yarn version: + 1.22.5 + +Node version: + 14.17.0 + +Platform: + darwin x64 + +Trace: + SyntaxError: /Users/mac/Documents/Opensource/danfojs/src/danfojs-node/package.json: Unexpected token y in JSON at position 750 + at JSON.parse () + at /usr/local/Cellar/yarn/1.22.5/libexec/lib/cli.js:1625:59 + at Generator.next () + at step (/usr/local/Cellar/yarn/1.22.5/libexec/lib/cli.js:310:30) + at /usr/local/Cellar/yarn/1.22.5/libexec/lib/cli.js:321:13 + +npm manifest: + { + "name": "danfojs-node", + "version": "1.0.0", + "description": "JavaScript library providing high performance, intuitive, and easy to use data structures for manipulating and processing structured data.", + "main": "dist/danfojs-node/src/index.js", + "types": "dist/danfojs-node/src/index.d.ts", + "directories": { + "test": "test" + }, + "contributors": [ + { + "name": "Rising Odegua" + }, + { + "name": "Stephen Oni" + } + ], + "files": [ + "dist/" + ], + "dependencies": { + "@tensorflow/tfjs-node": "3.6.1", + "mathjs": "^9.4.4", + "node-fetch": "^2.6.1", + "papaparse": "^5.3.1", + "request": "^2.88.2", + "stream-json": "^1.7.3", + "table": "6.7.1", + "xlsx": "^0.17.2", + "seedrandom": "^2.4.3" + }, + yarn "scripts": { + "test": "nyc mocha --require ts-node/register test/**/*.test.ts", + "test:clean": "yarn build:clean && yarn test", + "dev": "nodemon", + "build": "tsc", + "build:clean": "rimraf ./build && node ./scripts/prebuild.js && tsc", + "lint": "eslint ./src", + "coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls", + "coverage": "nyc report --reporter=text-lcov | coveralls && nyc report --reporter=lcov", + "patch": "npm version patch" + }, + "publishConfig": { + "access": "public", + "branches": [ + "master" + ] + }, + "repository": { + "type": "git", + "url": "git+https://github.com/opensource9ja/danfojs.git" + }, + "keywords": [ + "pandas", + "data-analysis", + "data-manipulation", + "analysis" + ], + "author": "Rising Odegua ", + "license": "MIT", + "bugs": { + "url": "https://github.com/opensource9ja/danfojs/issues" + }, + "homepage": "https://github.com/opensource9ja/danfojs#readme", + "devDependencies": { + "@babel/cli": "^7.10.5", + "@babel/core": "^7.10.5", + "@babel/plugin-transform-runtime": "^7.12.10", + "@babel/preset-env": "^7.10.4", + "@babel/register": "^7.10.1", + "@types/chai": "^4.2.19", + "@types/mocha": "^8.2.2", + "@types/node": "^16.9.6", + "@types/papaparse": "^5.2.6", + "@types/request": "^2.48.7", + "@types/stream-json": "^1.7.1", + "@types/table": "^6.3.2", + "chai": "^4.2.0", + "coveralls": "^3.1.0", + "dotenv": "^10.0.0", + "dts-bundle-generator": "^5.9.0", + "eslint": "^7.1.0", + "mocha": "^7.2.0", + "nodemon": "^2.0.7", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-node": "^10.0.0", + "typescript": "^4.4.2", + "yarn": "^1.22.10" + }, + "nyc": { + "reporter": [ + "lcov", + "text" + ] + } + } + +yarn manifest: + No manifest + +Lockfile: + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # yarn lockfile v1 + + + "@babel/cli@^7.10.5": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.10.tgz#67a1015b1cd505bde1696196febf910c4c339a48" + integrity sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ== + dependencies: + commander "^4.0.1" + convert-source-map "^1.1.0" + fs-readdir-recursive "^1.1.0" + glob "^7.0.0" + lodash "^4.17.19" + make-dir "^2.1.0" + slash "^2.0.0" + source-map "^0.5.0" + optionalDependencies: + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents" + chokidar "^3.4.0" + + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + + "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== + + "@babel/core@^7.10.5", "@babel/core@^7.7.5": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^5.4.1" + source-map "^0.5.0" + + "@babel/generator@^7.12.10", "@babel/generator@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== + dependencies: + "@babel/types" "^7.12.11" + jsesc "^2.5.1" + source-map "^0.5.0" + + "@babel/helper-annotate-as-pure@^7.10.4": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== + dependencies: + "@babel/types" "^7.12.10" + + "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" + + "@babel/helper-compilation-targets@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== + dependencies: + "@babel/compat-data" "^7.12.5" + "@babel/helper-validator-option" "^7.12.1" + browserslist "^4.14.5" + semver "^5.5.0" + + "@babel/helper-create-class-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.1" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + + "@babel/helper-create-regexp-features-plugin@^7.12.1": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" + integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + regexpu-core "^4.7.1" + + "@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + + "@babel/helper-explode-assignable-expression@^7.10.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== + dependencies: + "@babel/types" "^7.12.1" + + "@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" + + "@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== + dependencies: + "@babel/types" "^7.12.10" + + "@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + + "@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== + dependencies: + "@babel/types" "^7.12.7" + + "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== + dependencies: + "@babel/types" "^7.12.5" + + "@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" + + "@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" + integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== + dependencies: + "@babel/types" "^7.12.10" + + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + + "@babel/helper-remap-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/types" "^7.12.1" + + "@babel/helper-replace-supers@^7.12.1": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.12.7" + "@babel/helper-optimise-call-expression" "^7.12.10" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.11" + + "@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== + dependencies: + "@babel/types" "^7.12.1" + + "@babel/helper-skip-transparent-expression-wrappers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== + dependencies: + "@babel/types" "^7.12.1" + + "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== + dependencies: + "@babel/types" "^7.12.11" + + "@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + + "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== + + "@babel/helper-wrap-function@^7.10.4": + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + + "@babel/helpers@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" + + "@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + + "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== + + "@babel/plugin-proposal-async-generator-functions@^7.12.1": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" + integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + + "@babel/plugin-proposal-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-proposal-dynamic-import@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + + "@babel/plugin-proposal-export-namespace-from@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + + "@babel/plugin-proposal-json-strings@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.0" + + "@babel/plugin-proposal-logical-assignment-operators@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + + "@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + + "@babel/plugin-proposal-numeric-separator@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + + "@babel/plugin-proposal-object-rest-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + + "@babel/plugin-proposal-optional-catch-binding@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + + "@babel/plugin-proposal-optional-chaining@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + + "@babel/plugin-proposal-private-methods@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + + "@babel/plugin-syntax-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + + "@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + + "@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + + "@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + + "@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + + "@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + + "@babel/plugin-syntax-top-level-await@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-arrow-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + + "@babel/plugin-transform-block-scoped-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-block-scoping@^7.12.11": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-classes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + globals "^11.1.0" + + "@babel/plugin-transform-computed-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-destructuring@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-duplicate-keys@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-exponentiation-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-for-of@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-function-name@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-member-expression-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-modules-amd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + + "@babel/plugin-transform-modules-commonjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.12.1" + babel-plugin-dynamic-import-node "^2.3.3" + + "@babel/plugin-transform-modules-systemjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== + dependencies: + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-identifier" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + + "@babel/plugin-transform-modules-umd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + + "@babel/plugin-transform-new-target@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-object-super@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + + "@babel/plugin-transform-parameters@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-property-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-regenerator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== + dependencies: + regenerator-transform "^0.14.2" + + "@babel/plugin-transform-reserved-words@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-runtime@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz#af0fded4e846c4b37078e8e5d06deac6cd848562" + integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA== + dependencies: + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + semver "^5.5.1" + + "@babel/plugin-transform-shorthand-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + + "@babel/plugin-transform-sticky-regex@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-template-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-typeof-symbol@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-unicode-escapes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/plugin-transform-unicode-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + + "@babel/preset-env@^7.10.4": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== + dependencies: + "@babel/compat-data" "^7.12.7" + "@babel/helper-compilation-targets" "^7.12.5" + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-option" "^7.12.11" + "@babel/plugin-proposal-async-generator-functions" "^7.12.1" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-dynamic-import" "^7.12.1" + "@babel/plugin-proposal-export-namespace-from" "^7.12.1" + "@babel/plugin-proposal-json-strings" "^7.12.1" + "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.7" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.12.1" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-async-to-generator" "^7.12.1" + "@babel/plugin-transform-block-scoped-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.11" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-computed-properties" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-dotall-regex" "^7.12.1" + "@babel/plugin-transform-duplicate-keys" "^7.12.1" + "@babel/plugin-transform-exponentiation-operator" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-function-name" "^7.12.1" + "@babel/plugin-transform-literals" "^7.12.1" + "@babel/plugin-transform-member-expression-literals" "^7.12.1" + "@babel/plugin-transform-modules-amd" "^7.12.1" + "@babel/plugin-transform-modules-commonjs" "^7.12.1" + "@babel/plugin-transform-modules-systemjs" "^7.12.1" + "@babel/plugin-transform-modules-umd" "^7.12.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" + "@babel/plugin-transform-new-target" "^7.12.1" + "@babel/plugin-transform-object-super" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-property-literals" "^7.12.1" + "@babel/plugin-transform-regenerator" "^7.12.1" + "@babel/plugin-transform-reserved-words" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.7" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.10" + "@babel/plugin-transform-unicode-escapes" "^7.12.1" + "@babel/plugin-transform-unicode-regex" "^7.12.1" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.12.11" + core-js-compat "^3.8.0" + semver "^5.5.0" + + "@babel/preset-modules@^0.1.3": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + + "@babel/register@^7.10.1": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.12.10.tgz#19b87143f17128af4dbe7af54c735663b3999f60" + integrity sha512-EvX/BvMMJRAA3jZgILWgbsrHwBQvllC5T8B29McyME8DvkdOxk4ujESfrMvME8IHSDvWXrmMXxPvA/lx2gqPLQ== + dependencies: + find-cache-dir "^2.0.0" + lodash "^4.17.19" + make-dir "^2.1.0" + pirates "^4.0.0" + source-map-support "^0.5.16" + + "@babel/runtime@^7.14.6": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b" + integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA== + dependencies: + regenerator-runtime "^0.13.4" + + "@babel/runtime@^7.8.4": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== + dependencies: + regenerator-runtime "^0.13.4" + + "@babel/template@^7.10.4", "@babel/template@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + + "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + + "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + + "@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.20" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + + "@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + + "@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + + "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": + version "2.1.8-no-fsevents" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b" + integrity sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + + "@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + + "@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + + "@tensorflow/tfjs-backend-cpu@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.6.0.tgz#4e64a7cf1c33b203f71f8f77cd7b0ac1ef25a871" + integrity sha512-ZpAs17hPdKXadbtNjAsymYUILe8V7+pY4fYo8j25nfDTW/HfBpyAwsHPbMcA/n5zyJ7ZJtGKFcCUv1sl24KL1Q== + dependencies: + "@types/seedrandom" "2.4.27" + seedrandom "2.4.3" + + "@tensorflow/tfjs-backend-webgl@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.6.0.tgz#1ea1a73abea8d6324fd81aedf7f187ab6eb73692" + integrity sha512-zp7l4TmD1khgeSux/Ujaaj8M/v+e8JVIKjOci6HCGaeMNrn74lTSH9oqGPWKUCmpZME17/V0LfRHK34ddmrPSA== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.6.0" + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "2.4.27" + "@types/webgl-ext" "0.0.30" + "@types/webgl2" "0.0.5" + seedrandom "2.4.3" + + "@tensorflow/tfjs-converter@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.6.0.tgz#32b3ff31b47e29630a82e30fbe01708facad7fd6" + integrity sha512-9MtatbTSvo3gpEulYI6+byTA3OeXSMT2lzyGAegXO9nMxsvjR01zBvlZ5SmsNyecNh6fMSzdL2+cCdQfQtsIBg== + + "@tensorflow/tfjs-core@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.6.0.tgz#6b4d8175790bdff78868eabe6adc6442eb4dc276" + integrity sha512-bb2c3zwK4SgXZRvkTiC7EhCpWbCGp0GMd+1/3Vo2/Z54jiLB/h3sXIgHQrTNiWwhKPtst/xxA+MsslFlvD0A5w== + dependencies: + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "2.4.27" + "@types/webgl-ext" "0.0.30" + node-fetch "~2.6.1" + seedrandom "2.4.3" + + "@tensorflow/tfjs-data@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-3.6.0.tgz#af2f03cffb75ad8e4c2f46e192e392d9b7f977ed" + integrity sha512-5KU7fnU7cj/opb4aCNDoW4qma64ggDwI0PCs5KEO41T3waVHDLk6bjlFlBVRdjfZqvM0K6EfWEyoiXzdvz/Ieg== + dependencies: + "@types/node-fetch" "^2.1.2" + node-fetch "~2.6.1" + + "@tensorflow/tfjs-layers@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-3.6.0.tgz#5358af559fc8baed304b3e567319fe93f1aa46a6" + integrity sha512-B7EHwAT6KFqhKzdf0e2Sr6haj9qpqpyEATV8OCPHdk+g8z2AGXOLlFfbgW6vCMjy1wb5jzYqCyZDoY3EWdgJAw== + + "@tensorflow/tfjs-node@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node/-/tfjs-node-3.6.1.tgz#a1452076fe6da48f5648ca33f85d1127e6881244" + integrity sha512-JA6GE7AYx+zoXiKQmEdMc848HDOurrI3vFyiLk/8bXJDEv7L7oW5y6Q1Ja+Bz5ul7UmOxNG89hyYhfGqJK8qKw== + dependencies: + "@tensorflow/tfjs" "3.6.0" + adm-zip "^0.4.11" + google-protobuf "^3.9.2" + https-proxy-agent "^2.2.1" + node-pre-gyp "0.14.0" + progress "^2.0.0" + rimraf "^2.6.2" + tar "^4.4.6" + + "@tensorflow/tfjs@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-3.6.0.tgz#e65956cd40c96523e3f5ec7a58a4bef9ef5e349c" + integrity sha512-uLDMDzyRkJa3fYBeR6etQTFD/t+nkQIH/DznL9hxmYoIYG8PigY2gcrc482TAvsdhiuvxCZ9rl5SyDtP93MvxQ== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.6.0" + "@tensorflow/tfjs-backend-webgl" "3.6.0" + "@tensorflow/tfjs-converter" "3.6.0" + "@tensorflow/tfjs-core" "3.6.0" + "@tensorflow/tfjs-data" "3.6.0" + "@tensorflow/tfjs-layers" "3.6.0" + argparse "^1.0.10" + chalk "^4.1.0" + core-js "3" + regenerator-runtime "^0.13.5" + yargs "^16.0.3" + + "@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + + "@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + + "@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + + "@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + + "@tsconfig/node16@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.1.tgz#a6ca6a9a0ff366af433f42f5f0e124794ff6b8f1" + integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA== + + "@types/caseless@*": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" + integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== + + "@types/chai@^4.2.19": + version "4.2.19" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.19.tgz#80f286b515897413c7a35bdda069cc80f2344233" + integrity sha512-jRJgpRBuY+7izT7/WNXP/LsMO9YonsstuL+xuvycDyESpoDoIAsMd7suwpB4h9oEWB+ZlPTqJJ8EHomzNhwTPQ== + + "@types/mocha@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0" + integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw== + + "@types/node-fetch@^2.1.2": + version "2.5.8" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" + integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + + "@types/node@*": + version "14.14.22" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" + integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw== + + "@types/node@^16.9.6": + version "16.9.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.6.tgz#040a64d7faf9e5d9e940357125f0963012e66f04" + integrity sha512-YHUZhBOMTM3mjFkXVcK+WwAcYmyhe1wL4lfqNtzI0b3qAy7yuSetnM7QJazgE5PFmgVTNGiLOgRFfJMqW7XpSQ== + + "@types/offscreencanvas@~2019.3.0": + version "2019.3.0" + resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553" + integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q== + + "@types/papaparse@^5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-5.2.6.tgz#0bba18de4d15eff65883bc7c0794e0134de9e7c7" + integrity sha512-xGKSd0UTn58N1h0+zf8mW863Rv8BvXcGibEgKFtBIXZlcDXAmX/T4RdDO2mwmrmOypUDt5vRgo2v32a78JdqUA== + dependencies: + "@types/node" "*" + + "@types/request@^2.48.7": + version "2.48.7" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.7.tgz#a962d11a26e0d71d9a9913d96bb806dc4d4c2f19" + integrity sha512-GWP9AZW7foLd4YQxyFZDBepl0lPsWLMEXDZUjQ/c1gqVPDPECrRZyEzuhJdnPWioFCq3Tv0qoGpMD6U+ygd4ZA== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + + "@types/seedrandom@2.4.27": + version "2.4.27" + resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41" + integrity sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE= + + "@types/stream-chain@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stream-chain/-/stream-chain-2.0.1.tgz#4d3cc47a32609878bc188de0bae420bcfd3bf1f5" + integrity sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg== + dependencies: + "@types/node" "*" + + "@types/stream-json@^1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@types/stream-json/-/stream-json-1.7.1.tgz#58b82a41161f2936c9bfc6c725a30e956bbd443b" + integrity sha512-BNIK/ix6iJvWvoXbDVVJhw5LNG1wie/rXcUo7jw4hBqY3FhIrg0e+RMXFN5UreKclBIStl9FDEHNSDLuuQ9/MQ== + dependencies: + "@types/node" "*" + "@types/stream-chain" "*" + + "@types/table@^6.3.2": + version "6.3.2" + resolved "https://registry.yarnpkg.com/@types/table/-/table-6.3.2.tgz#e18ad2594400d81c3da28c31b342eb5a0d87a8e7" + integrity sha512-GJ82z3vQbx2BhiUo12w2A3lyBpXPJrGHjQ7iS5aH925098w8ojqiWBhgOUy97JS2PKLmRCTLT0sI+gJI4futig== + dependencies: + table "*" + + "@types/tough-cookie@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.1.tgz#8f80dd965ad81f3e1bc26d6f5c727e132721ff40" + integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg== + + "@types/webgl-ext@0.0.30": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/webgl-ext/-/webgl-ext-0.0.30.tgz#0ce498c16a41a23d15289e0b844d945b25f0fb9d" + integrity sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg== + + "@types/webgl2@0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.5.tgz#dd925e20ab8ace80eb4b1e46fda5b109c508fb0d" + integrity sha512-oGaKsBbxQOY5+aJFV3KECDhGaXt+yZJt2y/OZsnQGLRkH6Fvr7rv4pCt3SRH1somIHfej/c4u7NSpCyd9x+1Ow== + + abab@^2.0.3, abab@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + + abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + + acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + + acorn-jsx@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + + acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + + acorn@^7.1.1, acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + + acorn@^8.2.4: + version "8.5.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" + integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== + + adler-32@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.2.0.tgz#6a3e6bf0a63900ba15652808cb15c6813d1a5f25" + integrity sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU= + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.1.0" + + adler-32@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.3.0.tgz#3cad1b71cdfa69f6c8a91f3e3615d31a4fdedc72" + integrity sha512-f5nltvjl+PRUh6YNfUstRaXwJxtfnKEWhAWWlmKvh+Y3J2+98a0KKVYDEhz6NdKGqswLhjNGznxfSsZGOvOd9g== + dependencies: + printj "~1.2.2" + + adm-zip@^0.4.11: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + + agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + + agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + + aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + + ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + + ajv@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.3.tgz#13ae747eff125cafb230ac504b2406cf371eece2" + integrity sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + + ajv@^8.0.1: + version "8.6.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.1.tgz#ae65764bf1edde8cd861281cda5057852364a295" + integrity sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + + ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + + ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + + ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + + ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + + ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + + ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + + ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + + ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + + ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + + anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + + anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + + anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + + append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + + aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + + archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + + are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + + arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + + argparse@^1.0.10, argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + + arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + + arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + + arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + + array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + + asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + + assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + + assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + + assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + + astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + + async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + + asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + + atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + + aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + + aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + + babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + + balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + + base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + + bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + + binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + + binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + + boxen@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" + + brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + + braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + + braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + + browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + + browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + + browserslist@^4.14.5, browserslist@^4.16.1: + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== + dependencies: + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" + + buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + + cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + + cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + + caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== + dependencies: + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" + + call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + + callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + + camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + + caniuse-lite@^1.0.30001219: + version "1.0.30001230" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" + integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ== + + caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + + cfb@^1.1.4, cfb@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/cfb/-/cfb-1.2.1.tgz#209429e4c68efd30641f6fc74b2d6028bd202402" + integrity sha512-wT2ScPAFGSVy7CY+aauMezZBnNrfnaLSrxHUHdea+Td/86vrk6ZquggV+ssBR88zNs0OnBkL2+lf9q0K+zVGzQ== + dependencies: + adler-32 "~1.3.0" + crc-32 "~1.2.0" + printj "~1.3.0" + + chai@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" + integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.0" + type-detect "^4.0.5" + + chalk@^2.0.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + + chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + + chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + + check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + + chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + + chokidar@^3.2.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + + chokidar@^3.4.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + + chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + + ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + + class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + + clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + + cli-boxes@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + + cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + + cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + + cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + + clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + + code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + + codepage@~1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab" + integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== + + collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + + color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + + color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + + color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + + color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + + colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + + combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + + commander@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + + commander@~2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== + + commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + + complex.js@^2.0.15: + version "2.0.15" + resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.15.tgz#7add6848b4c1d12aa9262f7df925ebe7a51a7406" + integrity sha512-gDBvQU8IG139ZBQTSo2qvDFP+lANMGluM779csXOr6ny1NUtA3wkUnCFjlDNH/moAVfXtvClYt6G0zarFbtz5w== + + component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + + concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + + configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + + console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + + convert-source-map@^1.1.0, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + + copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + + core-js-compat@^3.8.0: + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" + integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== + dependencies: + browserslist "^4.16.1" + semver "7.0.0" + + core-js@3: + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" + integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== + + core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + + coveralls@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" + integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== + dependencies: + js-yaml "^3.13.1" + lcov-parse "^1.0.0" + log-driver "^1.2.7" + minimist "^1.2.5" + request "^2.88.2" + + crc-32@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" + integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.1.0" + + create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + + cross-spawn@^7.0.0, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + + crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + + cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + + cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + + cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + + dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + + data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + + debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + + debug@4: + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + dependencies: + ms "2.1.2" + + debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + + debug@^3.1.0, debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + + debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + + decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + + decimal.js@^10.2.1, decimal.js@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + + decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + + decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + + deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + + deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + + deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + + deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + + default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== + dependencies: + strip-bom "^4.0.0" + + defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + + define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + + define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + + define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + + define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + + delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + + delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + + detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + + diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + + diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + + doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + + domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + + dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + + dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + + dts-bundle-generator@^5.9.0: + version "5.9.0" + resolved "https://registry.yarnpkg.com/dts-bundle-generator/-/dts-bundle-generator-5.9.0.tgz#454e8e62e9425bd5ff03afad66c1ea9cc02f7f99" + integrity sha512-wzxUa9nfGL09Sg+gD3jqA8kYIA9A/olenvP2MmZ6IGTlUxR8G1z4U+0+OfUEL6OH1mzn6xsD8EOVgpNnGDi8tQ== + dependencies: + typescript ">=3.0.1" + yargs "^15.3.1" + + duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + + ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + + electron-to-chromium@^1.3.723: + version "1.3.739" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz#f07756aa92cabd5a6eec6f491525a64fe62f98b9" + integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A== + + emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + + emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + + end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + + enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + + es-abstract@^1.18.0-next.1: + version "1.18.0-next.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" + integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.1" + is-regex "^1.1.1" + object-inspect "^1.9.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.3" + string.prototype.trimstart "^1.0.3" + + es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + + es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + + es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + + es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + + escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + + escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + + escape-latex@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1" + integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== + + escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + + escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + + eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + + eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + + eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + + eslint@^7.1.0: + version "7.18.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" + integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.3.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^6.0.0" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.20" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.4" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + + espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + + esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + + esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + dependencies: + estraverse "^5.1.0" + + esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + + estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + + estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + + esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + + exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + + expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + + extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + + extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + + extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + + extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + + extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + + extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + + fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + + fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + + fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + + fflate@^0.3.8: + version "0.3.11" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.3.11.tgz#2c440d7180fdeb819e64898d8858af327b042a5d" + integrity sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A== + + file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== + dependencies: + flat-cache "^3.0.4" + + fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + + fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + + find-cache-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + + find-cache-dir@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + + find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + + find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + + flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + + flat@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== + dependencies: + is-buffer "~2.0.3" + + flatted@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== + + for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + + foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + + forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + + form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + + form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + + form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + + frac@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b" + integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== + + fraction.js@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff" + integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg== + + fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + + fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== + + fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + + fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + + fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + + fsevents@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + + fsevents@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" + integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw== + + fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + + function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + + functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + + gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + + gensync@^1.0.0-beta.1: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + + get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + + get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + + get-intrinsic@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + + get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + + get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + + get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + + get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + + getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + + glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + + glob-parent@^5.0.0, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + + glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + + glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + + glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + + global-dirs@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d" + integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ== + dependencies: + ini "1.3.7" + + globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + + globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + + google-protobuf@^3.9.2: + version "3.14.0" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.14.0.tgz#20373d22046e63831a5110e11a84f713cc43651e" + integrity sha512-bwa8dBuMpOxg7COyqkW6muQuvNnWgVN8TX/epDRGW5m0jcrmq2QJyCyiV8ZE2/6LaIIqJtiv9bYokFhfpy/o6w== + + got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + + graceful-fs@^4.1.11, graceful-fs@^4.1.15: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + + graceful-fs@^4.1.2: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + + growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + + har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + + har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + + has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + + has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + + has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + + has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + + has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + + has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + + has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + + has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + + has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + + has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + + hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + + he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + + html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + + html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + + http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + + http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + + http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + + https-proxy-agent@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + + https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + + iconv-lite@0.4.24, iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + + ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + + ignore-walk@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + + ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + + import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + + import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + + imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + + indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + + inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + + inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + + ini@1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== + + ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + + is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + + is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + + is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + + is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + + is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + + is-buffer@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + + is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + + is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + + is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + + is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + + is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + + is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + + is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + + is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + + is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + + is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + + is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + + is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + + is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + + is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + + is-installed-globally@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + dependencies: + global-dirs "^2.0.1" + is-path-inside "^3.0.1" + + is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + + is-npm@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" + integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== + + is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + + is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + + is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + + is-path-inside@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + + is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + + is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + + is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + + is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + + is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + + is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + + is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + + is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + + isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + + isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + + isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + + isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + + isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + + istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + + istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + + istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + + istanbul-lib-processinfo@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" + integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== + dependencies: + archy "^1.0.0" + cross-spawn "^7.0.0" + istanbul-lib-coverage "^3.0.0-alpha.1" + make-dir "^3.0.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^3.3.3" + + istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + + istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + + istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + + javascript-natural-sort@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" + integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= + + js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + + js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + + js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + + jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + + jsdom@^16.2.2: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + + jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + + jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + + json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + + json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + + json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + + json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + + json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + + json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + + json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + + jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + + keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + + kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + + kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + + kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + + latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + + lcov-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= + + levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + + levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + + locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + + locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + + lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + + lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + + lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + + lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + + lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + + log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== + + log-symbols@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + + lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + + lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + + make-dir@^2.0.0, make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + + make-dir@^3.0.0, make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + + make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + + map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + + map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + + mathjs@^9.4.4: + version "9.4.4" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-9.4.4.tgz#29acd67563c1e720910213062824c3faf61bc858" + integrity sha512-5EEJXnWOzLDgMHSFyw623nH+MTBZxquWwXtrzTsingOouJJ6UZG2VNO1lwH31IMt9aMno1axO6TYleIP4YSDaQ== + dependencies: + "@babel/runtime" "^7.14.6" + complex.js "^2.0.15" + decimal.js "^10.3.1" + escape-latex "^1.2.0" + fraction.js "^4.1.1" + javascript-natural-sort "^0.7.1" + seedrandom "^3.0.5" + tiny-emitter "^2.1.0" + typed-function "^2.0.0" + + micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + + mime-db@1.45.0: + version "1.45.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== + + mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.28" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" + integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== + dependencies: + mime-db "1.45.0" + + mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + + minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + + minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + + minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + + minizlib@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + + mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + + mkdirp@0.5.5, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + + mocha@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" + integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + chokidar "3.3.0" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "3.0.0" + minimatch "3.0.4" + mkdirp "0.5.5" + ms "2.1.1" + node-environment-flags "1.0.6" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "1.6.0" + + ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + + ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + + ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + + ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + + nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + + natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + + needle@^2.2.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.6.0.tgz#24dbb55f2509e2324b4a99d61f413982013ccdbe" + integrity sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + + node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + + node-fetch@^2.6.1, node-fetch@~2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + + node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + + node-pre-gyp@0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" + integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4.4.2" + + node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + + node-releases@^1.1.71: + version "1.1.72" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" + integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== + + nodemon@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.7.tgz#6f030a0a0ebe3ea1ba2a38f71bf9bab4841ced32" + integrity sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA== + dependencies: + chokidar "^3.2.2" + debug "^3.2.6" + ignore-by-default "^1.0.1" + minimatch "^3.0.4" + pstree.remy "^1.1.7" + semver "^5.7.1" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.3" + update-notifier "^4.1.0" + + nopt@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + + nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + dependencies: + abbrev "1" + + normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + + normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + + normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + + npm-bundled@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" + + npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + + npm-packlist@^1.1.6: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + + npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + + number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + + nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + + nyc@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== + dependencies: + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" + + oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + + object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + + object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + + object-inspect@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + + object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + + object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + + object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + + object.assign@^4.1.0, object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + + object.getownpropertydescriptors@^2.0.3: + version "2.1.1" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544" + integrity sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + + object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + + once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + + optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + + optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + + os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + + os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + + osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + + p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + + p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + + p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + + p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + + p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + + p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + + package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + + package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + + papaparse@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.3.1.tgz#770b7a9124d821d4b2132132b7bd7dce7194b5b1" + integrity sha512-Dbt2yjLJrCwH2sRqKFFJaN5XgIASO9YOFeFP8rIBRG2Ain8mqk5r1M6DkfvqEVozVcz3r3HaUGw253hA1nLIcA== + + parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + + parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + + pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + + path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + + path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + + path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + + path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + + path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + + pathval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= + + performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + + picomatch@^2.0.4, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + + pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + + pirates@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== + dependencies: + node-modules-regexp "^1.0.0" + + pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + + pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + + posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + + prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + + prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + + prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + + printj@~1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" + integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + + printj@~1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.2.3.tgz#2cfb2b192a1e5385dbbe5b46658ac34aa828508a" + integrity sha512-sanczS6xOJOg7IKDvi4sGOUOe7c1tsEzjwlLFH/zgwx/uyImVM9/rgBkc8AfiQa/Vg54nRd8mkm9yI7WV/O+WA== + + printj@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.0.tgz#9018a918a790e43707f10625d6e10187a367cff6" + integrity sha512-017o8YIaz8gLhaNxRB9eBv2mWXI2CtzhPJALnQTP+OPpuUfP0RMWqr/mHCzqVeu1AQxfzSfAtAq66vKB8y7Lzg== + + process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + + process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + + progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + + psl@^1.1.28, psl@^1.1.33: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + + pstree.remy@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + + pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + + punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + + pupa@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" + + qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + + rc@^1.2.7, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + + readable-stream@^2.0.2, readable-stream@^2.0.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + + readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + + readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + + readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + + readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + + regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + + regenerate@^1.4.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + + regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + + regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== + dependencies: + "@babel/runtime" "^7.8.4" + + regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + + regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + + regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + + registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + + registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + + regjsgen@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== + + regjsparser@^0.6.4: + version "0.6.6" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.6.tgz#6d8c939d1a654f78859b08ddcc4aa777f3fa800a" + integrity sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ== + dependencies: + jsesc "~0.5.0" + + release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + dependencies: + es6-error "^4.0.1" + + remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + + repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + + repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + + request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + + require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + + require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + + require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + + resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + + resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + + resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + + responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + + ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + + rimraf@^2.6.1, rimraf@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + + rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + + safe-buffer@^5.0.1, safe-buffer@^5.1.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + + safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + + safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + + "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + + sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + + saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + + seedrandom@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.3.tgz#2438504dad33917314bff18ac4d794f16d6aaecc" + integrity sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw= + + seedrandom@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" + integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== + + semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + + semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + + semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + + semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + + semver@^7.2.1: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + + set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + + set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + + shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + + shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + + signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + + slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + + slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + + snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + + snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + + snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + + source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + + source-map-support@^0.5.16, source-map-support@^0.5.17: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + + source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + + source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + + source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + + spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== + dependencies: + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + which "^2.0.1" + + split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + + sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + + ssf@~0.11.2: + version "0.11.2" + resolved "https://registry.yarnpkg.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c" + integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== + dependencies: + frac "~1.1.2" + + sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + + static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + + stream-chain@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.4.tgz#2e5e9858e00d25ebaf7e4339e8328ddcab5facad" + integrity sha512-9lsl3YM53V5N/I1C2uJtc3Kavyi3kNYN83VkKb/bMWRk7D9imiFyUPYa0PoZbLohSVOX1mYE9YsmwObZUsth6Q== + + stream-json@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.7.3.tgz#8a2abe8b51a2e84ffbc8d09bca9d01dc70facae3" + integrity sha512-Y6dXn9KKWSwxOqnvHGcdZy1PK+J+7alBwHCeU3W9oRqm4ilLRA0XSPmd1tWwhg7tv9EIxJTMWh7KF15tYelKJg== + dependencies: + stream-chain "^2.2.4" + + string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + + "string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + + string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + + string-width@^4.0.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + + string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + + string.prototype.trimend@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + + string.prototype.trimstart@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + + string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + + strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + + strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + + strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + + strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + + strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + + strip-json-comments@2.0.1, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + + supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + + supports-color@^5.3.0, supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + + supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + + symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + + table@*, table@6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" + integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== + dependencies: + ajv "^8.0.1" + lodash.clonedeep "^4.5.0" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + + table@^6.0.4: + version "6.0.7" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" + integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== + dependencies: + ajv "^7.0.2" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" + + tar@^4.4.2, tar@^4.4.6: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + + term-size@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" + integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== + + test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + + text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + + tiny-emitter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + + to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + + to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + + to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + + to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + + to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + + to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + + touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" + + tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + + tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + + tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + + ts-node@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.0.0.tgz#05f10b9a716b0b624129ad44f0ea05dac84ba3be" + integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg== + dependencies: + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + + tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + + tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + + type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + + type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + + type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + + type-fest@^0.8.0, type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + + typed-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-2.0.0.tgz#15ab3825845138a8b1113bd89e60cd6a435739e8" + integrity sha512-Hhy1Iwo/e4AtLZNK10ewVVcP2UEs408DS35ubP825w/YgSBK1KVLwALvvIG4yX75QJrxjCpcWkzkVRB0BwwYlA== + + typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + + typescript@>=3.0.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324" + integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA== + + typescript@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== + + undefsafe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae" + integrity sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== + dependencies: + debug "^2.2.0" + + unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + + unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + + unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + + unicode-property-aliases-ecmascript@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== + + union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + + unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + + universalify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + + unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + + upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + + update-notifier@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" + integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== + dependencies: + boxen "^4.2.0" + chalk "^3.0.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.3.1" + is-npm "^4.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + pupa "^2.0.1" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + + uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + + urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + + url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + + use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + + util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + + uuid@^3.3.2, uuid@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + + v8-compile-cache@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + + verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + + w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + + w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + + webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + + webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + + whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + + whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + + whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + + which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + + which@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + + which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + + wide-align@1.1.3, wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + + widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + + wmf@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da" + integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== + + word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + + word@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/word/-/word-0.4.0.tgz#691272aaecb9da96388fc873d2ecb48a17cbee54" + integrity sha512-Aq84KjS7Z9HSU14qf4l/NEouaqfJAZtE9zEz7TIvw9V/3oJeUbjQwhz7ggqbL7I7REt4Bz+9HuCWsBO5N7xChw== + dependencies: + cfb "^1.2.0" + jsdom "^16.2.2" + + wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + + wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + + wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + + wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + + write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + + ws@^7.4.6: + version "7.5.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" + integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + + xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + + xlsx@^0.17.2: + version "0.17.2" + resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.17.2.tgz#032bcca02ca01b5ebf7da93dcb035891f2c092af" + integrity sha512-RIhN6/oc/ZqYZqY4jz4AX92yNfULhtNrcZP1lknIcsyR+Ra8Zu/9F1lAZWncYbDex95iYQX/XNNNzNFXZjlNOQ== + dependencies: + adler-32 "~1.2.0" + cfb "^1.1.4" + codepage "~1.15.0" + commander "~2.17.1" + crc-32 "~1.2.0" + exit-on-epipe "~1.0.1" + fflate "^0.3.8" + ssf "~0.11.2" + wmf "~1.0.1" + word "~0.4.0" + + xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + + xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + + y18n@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== + + y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + + yallist@^3.0.0, yallist@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + + yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + + yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + + yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + + yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + + yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + + yargs@13.3.2, yargs@^13.3.0: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + + yargs@^15.0.2, yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + + yargs@^16.0.3: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + + yarn@^1.22.10: + version "1.22.10" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" + integrity sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA== + + yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/danfojs-node/yarn.lock b/src/danfojs-node/yarn.lock similarity index 56% rename from danfojs-node/yarn.lock rename to src/danfojs-node/yarn.lock index 8b8f7098..8f78d12c 100644 --- a/danfojs-node/yarn.lock +++ b/src/danfojs-node/yarn.lock @@ -4,7 +4,7 @@ "@babel/cli@^7.10.5": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.10.tgz#67a1015b1cd505bde1696196febf910c4c339a48" + resolved "https://registry.npmjs.org/@babel/cli/-/cli-7.12.10.tgz" integrity sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ== dependencies: commander "^4.0.1" @@ -21,19 +21,19 @@ "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== "@babel/core@^7.10.5", "@babel/core@^7.7.5": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz" integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== dependencies: "@babel/code-frame" "^7.10.4" @@ -54,7 +54,7 @@ "@babel/generator@^7.12.10", "@babel/generator@^7.12.11": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz" integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== dependencies: "@babel/types" "^7.12.11" @@ -63,14 +63,14 @@ "@babel/helper-annotate-as-pure@^7.10.4": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz" integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== dependencies: "@babel/types" "^7.12.10" "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz" integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: "@babel/helper-explode-assignable-expression" "^7.10.4" @@ -78,7 +78,7 @@ "@babel/helper-compilation-targets@^7.12.5": version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz" integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== dependencies: "@babel/compat-data" "^7.12.5" @@ -88,7 +88,7 @@ "@babel/helper-create-class-features-plugin@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz" integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -99,7 +99,7 @@ "@babel/helper-create-regexp-features-plugin@^7.12.1": version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz" integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -107,7 +107,7 @@ "@babel/helper-define-map@^7.10.4": version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + resolved "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz" integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -116,14 +116,14 @@ "@babel/helper-explode-assignable-expression@^7.10.4": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz" integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz" integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== dependencies: "@babel/helper-get-function-arity" "^7.12.10" @@ -132,35 +132,35 @@ "@babel/helper-get-function-arity@^7.12.10": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz" integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== dependencies: "@babel/types" "^7.12.10" "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz" integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== dependencies: "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz" integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== dependencies: "@babel/types" "^7.12.7" "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz" integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== dependencies: "@babel/types" "^7.12.5" "@babel/helper-module-transforms@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz" integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== dependencies: "@babel/helper-module-imports" "^7.12.1" @@ -175,19 +175,19 @@ "@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz" integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== dependencies: "@babel/types" "^7.12.10" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz" integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -196,7 +196,7 @@ "@babel/helper-replace-supers@^7.12.1": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz" integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== dependencies: "@babel/helper-member-expression-to-functions" "^7.12.7" @@ -206,38 +206,38 @@ "@babel/helper-simple-access@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz" integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-skip-transparent-expression-wrappers@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz" integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz" integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== dependencies: "@babel/types" "^7.12.11" "@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz" integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== "@babel/helper-wrap-function@^7.10.4": version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz" integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -247,7 +247,7 @@ "@babel/helpers@^7.12.5": version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz" integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== dependencies: "@babel/template" "^7.10.4" @@ -256,7 +256,7 @@ "@babel/highlight@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz" integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" @@ -265,12 +265,12 @@ "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz" integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz" integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -279,7 +279,7 @@ "@babel/plugin-proposal-class-properties@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz" integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== dependencies: "@babel/helper-create-class-features-plugin" "^7.12.1" @@ -287,7 +287,7 @@ "@babel/plugin-proposal-dynamic-import@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz" integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -295,7 +295,7 @@ "@babel/plugin-proposal-export-namespace-from@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz" integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -303,7 +303,7 @@ "@babel/plugin-proposal-json-strings@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz" integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -311,7 +311,7 @@ "@babel/plugin-proposal-logical-assignment-operators@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz" integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -319,7 +319,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz" integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -327,7 +327,7 @@ "@babel/plugin-proposal-numeric-separator@^7.12.7": version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz" integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -335,7 +335,7 @@ "@babel/plugin-proposal-object-rest-spread@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -344,7 +344,7 @@ "@babel/plugin-proposal-optional-catch-binding@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz" integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -352,7 +352,7 @@ "@babel/plugin-proposal-optional-chaining@^7.12.7": version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz" integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -361,7 +361,7 @@ "@babel/plugin-proposal-private-methods@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz" integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== dependencies: "@babel/helper-create-class-features-plugin" "^7.12.1" @@ -369,7 +369,7 @@ "@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz" integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -377,98 +377,98 @@ "@babel/plugin-syntax-async-generators@^7.8.0": version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz" integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings@^7.8.0": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.0": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.0": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.0": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-top-level-await@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz" integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-arrow-functions@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz" integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-async-to-generator@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz" integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== dependencies: "@babel/helper-module-imports" "^7.12.1" @@ -477,21 +477,21 @@ "@babel/plugin-transform-block-scoped-functions@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz" integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-block-scoping@^7.12.11": version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz" integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-classes@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz" integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -505,21 +505,21 @@ "@babel/plugin-transform-computed-properties@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz" integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-destructuring@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz" integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz" integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -527,14 +527,14 @@ "@babel/plugin-transform-duplicate-keys@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz" integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-exponentiation-operator@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz" integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" @@ -542,14 +542,14 @@ "@babel/plugin-transform-for-of@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz" integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-function-name@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz" integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -557,21 +557,21 @@ "@babel/plugin-transform-literals@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz" integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-member-expression-literals@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz" integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-modules-amd@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz" integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -580,7 +580,7 @@ "@babel/plugin-transform-modules-commonjs@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz" integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -590,7 +590,7 @@ "@babel/plugin-transform-modules-systemjs@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz" integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== dependencies: "@babel/helper-hoist-variables" "^7.10.4" @@ -601,7 +601,7 @@ "@babel/plugin-transform-modules-umd@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz" integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -609,21 +609,21 @@ "@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz" integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/plugin-transform-new-target@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz" integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-object-super@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz" integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -631,35 +631,35 @@ "@babel/plugin-transform-parameters@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz" integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-property-literals@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz" integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-regenerator@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz" integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== dependencies: regenerator-transform "^0.14.2" "@babel/plugin-transform-reserved-words@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz" integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-runtime@^7.12.10": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz#af0fded4e846c4b37078e8e5d06deac6cd848562" + resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz" integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA== dependencies: "@babel/helper-module-imports" "^7.12.5" @@ -668,14 +668,14 @@ "@babel/plugin-transform-shorthand-properties@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz" integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-spread@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz" integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -683,35 +683,35 @@ "@babel/plugin-transform-sticky-regex@^7.12.7": version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz" integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-template-literals@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz" integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typeof-symbol@^7.12.10": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz" integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-unicode-escapes@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz" integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-unicode-regex@^7.12.1": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz" integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -719,7 +719,7 @@ "@babel/preset-env@^7.10.4": version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz" integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== dependencies: "@babel/compat-data" "^7.12.7" @@ -791,7 +791,7 @@ "@babel/preset-modules@^0.1.3": version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz" integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -802,7 +802,7 @@ "@babel/register@^7.10.1": version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.12.10.tgz#19b87143f17128af4dbe7af54c735663b3999f60" + resolved "https://registry.npmjs.org/@babel/register/-/register-7.12.10.tgz" integrity sha512-EvX/BvMMJRAA3jZgILWgbsrHwBQvllC5T8B29McyME8DvkdOxk4ujESfrMvME8IHSDvWXrmMXxPvA/lx2gqPLQ== dependencies: find-cache-dir "^2.0.0" @@ -811,23 +811,23 @@ pirates "^4.0.0" source-map-support "^0.5.16" -"@babel/runtime@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" - integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== +"@babel/runtime@^7.14.6": + version "7.15.3" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz" + integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA== dependencies: regenerator-runtime "^0.13.4" "@babel/runtime@^7.8.4": version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" "@babel/template@^7.10.4", "@babel/template@^7.12.7": version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz" integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== dependencies: "@babel/code-frame" "^7.10.4" @@ -836,7 +836,7 @@ "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5": version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz" integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== dependencies: "@babel/code-frame" "^7.12.11" @@ -851,7 +851,7 @@ "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4": version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz" integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== dependencies: "@babel/helper-validator-identifier" "^7.12.11" @@ -860,7 +860,7 @@ "@eslint/eslintrc@^0.3.0": version "0.3.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz" integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== dependencies: ajv "^6.12.4" @@ -876,7 +876,7 @@ "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" @@ -887,12 +887,12 @@ "@istanbuljs/schema@^0.1.2": version "0.1.2" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== "@mapbox/node-pre-gyp@1.0.4": version "1.0.4" - resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.4.tgz#6c76e7a40138eac39e1a4dc869a083e43e236c00" + resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.4.tgz" integrity sha512-M669Qo4nRT7iDmQEjQYC7RU8Z6dpz9UmSbkJ1OFEja3uevCdLKh7IZZki7L1TZj02kRyl82snXFY8QqkyfowrQ== dependencies: detect-libc "^1.0.3" @@ -907,7 +907,7 @@ "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": version "2.1.8-no-fsevents" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b" + resolved "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz" integrity sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w== dependencies: anymatch "^2.0.0" @@ -922,35 +922,47 @@ readdirp "^2.2.1" upath "^1.1.1" -"@tensorflow/tfjs-backend-cpu@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.11.0.tgz#01d5d68b91faf12bee4854adae56bc956b794f1a" - integrity sha512-ShLkrZ4/rmhZwzGKenMFDfQnaEbyZgWA5F8JRa52Iob/vptlZeuOzjq87CZKmZMUmDswR9A2kjzovT/H1bJdWQ== +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@tensorflow/tfjs-backend-cpu@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.13.0.tgz" + integrity sha512-POmzUoAP8HooYYTZ72O1ZYkpVZB0f+8PeAkbTxIG0oahcJccj6a0Vovp1A6xWKfljUoPlJb3jWVC++S603ZL8w== dependencies: "@types/seedrandom" "2.4.27" seedrandom "2.4.3" -"@tensorflow/tfjs-backend-webgl@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.11.0.tgz#fbd7f24c164d17c11d964206b4b075b073b1a3bc" - integrity sha512-rNnc/dZ7LIl9O/Pn9W24I1h8kgpJ+XvG8NrdNSfIoWPCW4fvPSlU7B3yMeZXvRneny+z+T3xRs96nWyU2mZBJw== +"@tensorflow/tfjs-backend-webgl@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.13.0.tgz" + integrity sha512-ZuJS11tCoZx2F1Eq7wqiqu8euJpPW/JV0qOKBehlRpV2qQrR+wHMpBT1hhDl4qU4LdgFTtSggKIRg/L8b0ScUQ== dependencies: - "@tensorflow/tfjs-backend-cpu" "3.11.0" + "@tensorflow/tfjs-backend-cpu" "3.13.0" "@types/offscreencanvas" "~2019.3.0" "@types/seedrandom" "2.4.27" "@types/webgl-ext" "0.0.30" "@types/webgl2" "0.0.6" seedrandom "2.4.3" -"@tensorflow/tfjs-converter@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.11.0.tgz#0842269a83599b52fd167a8a05372018a9a1ca6a" - integrity sha512-rTRIKvBoqL0qdPYpm8UXauZycOiaBHZB2E2v3OoXoHnjvle/Xn/09uZJdrixgGhR+Kahs3Vz27BEEFz6RI5j2w== +"@tensorflow/tfjs-converter@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-3.13.0.tgz" + integrity sha512-H2VpDTv9Ve0HBt7ttzz46DmnsPaiT0B+yJjVH3NebGZbgY9C8boBgJIsdyqfiqEWBS3WxF8h4rh58Hv5XXMgaQ== -"@tensorflow/tfjs-core@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.11.0.tgz#1e3986533faaed922bbfc2fe86da506d0e9e5c79" - integrity sha512-JOp+1+LCd0Xg3hu7fu6iQPWZnN8Hc6ssfP7B+625XH5GYY1/OhVASa7Ahe2mJr9gZovY2lw8FUejLh1jMmBb1Q== +"@tensorflow/tfjs-core@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-3.13.0.tgz" + integrity sha512-18qBEVIB/4u2OUK9nA5P1XT3e3LyarElD1UKNSNDpnMLxhLTUVZaCR71eHJcpl9wP2Q0cciaTJCTpJdPv1tNDQ== dependencies: "@types/long" "^4.0.1" "@types/offscreencanvas" "~2019.3.0" @@ -960,26 +972,26 @@ node-fetch "~2.6.1" seedrandom "2.4.3" -"@tensorflow/tfjs-data@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-3.11.0.tgz#90dd23a7181f0a744f2882a12c3442b27047383d" - integrity sha512-+cUHUHzjM/zs0JVOwHQm9wP15Y+BZdRcUpMoYWia8r3kaGSyvoz6WqzacEP1PeXgJVnr2gtU3D+bF32th8fZfQ== +"@tensorflow/tfjs-data@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-3.13.0.tgz" + integrity sha512-n50+lxPK0CU72nlFt4dzMCCNV44CQsQU3sSP9zdR2bYHeoFqjjy1ISp+UV5N5DNLj7bsEMs73kGS1EuJ7YcdqQ== dependencies: "@types/node-fetch" "^2.1.2" node-fetch "~2.6.1" -"@tensorflow/tfjs-layers@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-3.11.0.tgz#456d8dc3fe93937ced329d5d06310da294d3758c" - integrity sha512-BtLgLucJZHv5te1K3yjT3iZdHXgMJArrLuOb/oRPOtTp4R2ad5N0V2m5RtuZJ3sI5/ah0h72xtmTWNyTv3/5dw== +"@tensorflow/tfjs-layers@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-3.13.0.tgz" + integrity sha512-kTWJ/+9fbNCMDA9iQjDMYHmWivsiWz8CKNSOZdeCW7tiBwF1EiREBVQXMk1JI11ngQa8f+rYSLs7rkhp3SYl5Q== -"@tensorflow/tfjs-node@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node/-/tfjs-node-3.11.0.tgz#6c6f0dc0e2f0eb03658337b53ce3009e97526f8d" - integrity sha512-EFBAkwJDoP4WuiWqjT9ER80dUvilvVFXULlU3WpmVGDluIL/Yq18xEKHvPaYHW5jLq/mvMljLtUBlHqigfvAhw== +"@tensorflow/tfjs-node@^3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs-node/-/tfjs-node-3.13.0.tgz" + integrity sha512-LYM3ck/TyipxMFD23moX9qC3F23UBC3zbiw85HTxZ9FPlE1QNLP1UNlfFGeUTnPvY6CUcvPyQsrG9fBTvtwB1A== dependencies: "@mapbox/node-pre-gyp" "1.0.4" - "@tensorflow/tfjs" "3.11.0" + "@tensorflow/tfjs" "3.13.0" adm-zip "^0.5.2" google-protobuf "^3.9.2" https-proxy-agent "^2.2.1" @@ -987,141 +999,194 @@ rimraf "^2.6.2" tar "^4.4.6" -"@tensorflow/tfjs@3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-3.11.0.tgz#63d5231f41d57ca11b910664632a8e349eba3967" - integrity sha512-TTYrKdkoh1sHnt4vn6MboLbpi1Es4U1Aw+L3PqwadRvXW4+7ySUtc00McrQ+ooK0q3Qhl3N7cvgchgM7nED3Mg== - dependencies: - "@tensorflow/tfjs-backend-cpu" "3.11.0" - "@tensorflow/tfjs-backend-webgl" "3.11.0" - "@tensorflow/tfjs-converter" "3.11.0" - "@tensorflow/tfjs-core" "3.11.0" - "@tensorflow/tfjs-data" "3.11.0" - "@tensorflow/tfjs-layers" "3.11.0" +"@tensorflow/tfjs@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-3.13.0.tgz" + integrity sha512-B5HvNH+6hHhQQkn+AG+u4j5sxZBMYdsq4IWXlBZzioJcVygtZhBWXkxp01boSwngjqUBgi8S2DopBE7McAUKqQ== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.13.0" + "@tensorflow/tfjs-backend-webgl" "3.13.0" + "@tensorflow/tfjs-converter" "3.13.0" + "@tensorflow/tfjs-core" "3.13.0" + "@tensorflow/tfjs-data" "3.13.0" + "@tensorflow/tfjs-layers" "3.13.0" argparse "^1.0.10" chalk "^4.1.0" core-js "3" regenerator-runtime "^0.13.5" yargs "^16.0.3" -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz" + integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA== + +"@types/caseless@*": + version "0.12.2" + resolved "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz" + integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== + +"@types/chai-as-promised@^7.1.5": + version "7.1.5" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + dependencies: + "@types/chai" "*" + +"@types/chai@*": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.3.tgz#3c90752792660c4b562ad73b3fbd68bf3bc7ae07" + integrity sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g== + +"@types/chai@^4.2.19": + version "4.2.19" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.2.19.tgz" + integrity sha512-jRJgpRBuY+7izT7/WNXP/LsMO9YonsstuL+xuvycDyESpoDoIAsMd7suwpB4h9oEWB+ZlPTqJJ8EHomzNhwTPQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/long@^4.0.1": version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" + resolved "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== +"@types/mocha@^9.0.0": + version "9.0.0" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz" + integrity sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA== + "@types/node-fetch@^2.1.2": version "2.5.8" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" + resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz" integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== dependencies: "@types/node" "*" form-data "^3.0.0" -"@types/node@*": - version "14.14.22" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" - integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw== +"@types/node@*", "@types/node@^16.9.6": + version "16.11.59" + resolved "https://registry.npmjs.org/@types/node/-/node-16.11.59.tgz" + integrity sha512-6u+36Dj3aDzhfBVUf/mfmc92OEdzQ2kx2jcXGdigfl70E/neV21ZHE6UCz4MDzTRcVqGAM27fk+DLXvyDsn3Jw== "@types/offscreencanvas@~2019.3.0": version "2019.3.0" - resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553" + resolved "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz" integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q== +"@types/papaparse@^5.2.6": + version "5.2.6" + resolved "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.2.6.tgz" + integrity sha512-xGKSd0UTn58N1h0+zf8mW863Rv8BvXcGibEgKFtBIXZlcDXAmX/T4RdDO2mwmrmOypUDt5vRgo2v32a78JdqUA== + dependencies: + "@types/node" "*" + +"@types/request@^2.48.7": + version "2.48.7" + resolved "https://registry.npmjs.org/@types/request/-/request-2.48.7.tgz" + integrity sha512-GWP9AZW7foLd4YQxyFZDBepl0lPsWLMEXDZUjQ/c1gqVPDPECrRZyEzuhJdnPWioFCq3Tv0qoGpMD6U+ygd4ZA== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + "@types/seedrandom@2.4.27": version "2.4.27" - resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41" + resolved "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.27.tgz" integrity sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE= +"@types/stream-chain@*": + version "2.0.1" + resolved "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz" + integrity sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg== + dependencies: + "@types/node" "*" + +"@types/stream-json@^1.7.1": + version "1.7.1" + resolved "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.1.tgz" + integrity sha512-BNIK/ix6iJvWvoXbDVVJhw5LNG1wie/rXcUo7jw4hBqY3FhIrg0e+RMXFN5UreKclBIStl9FDEHNSDLuuQ9/MQ== + dependencies: + "@types/node" "*" + "@types/stream-chain" "*" + +"@types/table@^6.3.2": + version "6.3.2" + resolved "https://registry.npmjs.org/@types/table/-/table-6.3.2.tgz" + integrity sha512-GJ82z3vQbx2BhiUo12w2A3lyBpXPJrGHjQ7iS5aH925098w8ojqiWBhgOUy97JS2PKLmRCTLT0sI+gJI4futig== + dependencies: + table "*" + +"@types/tough-cookie@*": + version "4.0.1" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz" + integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg== + "@types/webgl-ext@0.0.30": version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/webgl-ext/-/webgl-ext-0.0.30.tgz#0ce498c16a41a23d15289e0b844d945b25f0fb9d" + resolved "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz" integrity sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg== "@types/webgl2@0.0.6": version "0.0.6" - resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.6.tgz#1ea2db791362bd8521548d664dbd3c5311cdf4b6" + resolved "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.6.tgz" integrity sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ== -abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== - abbrev@1: version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" - integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - acorn-jsx@^5.3.1: version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== -acorn-walk@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" - integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== - -acorn@^7.1.1, acorn@^7.4.0: +acorn@^7.4.0: version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4: - version "8.5.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" - integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== - -adler-32@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.2.0.tgz#6a3e6bf0a63900ba15652808cb15c6813d1a5f25" - integrity sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU= - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -adler-32@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.3.0.tgz#3cad1b71cdfa69f6c8a91f3e3615d31a4fdedc72" - integrity sha512-f5nltvjl+PRUh6YNfUstRaXwJxtfnKEWhAWWlmKvh+Y3J2+98a0KKVYDEhz6NdKGqswLhjNGznxfSsZGOvOd9g== - dependencies: - printj "~1.2.2" - adm-zip@^0.5.2: version "0.5.9" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.9.tgz#b33691028333821c0cf95c31374c5462f2905a83" + resolved "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz" integrity sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg== agent-base@6: version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" agent-base@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz" integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== dependencies: es6-promisify "^5.0.0" aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" @@ -1129,7 +1194,7 @@ aggregate-error@^3.0.0: ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -1139,7 +1204,7 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: ajv@^7.0.2: version "7.0.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.3.tgz#13ae747eff125cafb230ac504b2406cf371eece2" + resolved "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz" integrity sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ== dependencies: fast-deep-equal "^3.1.1" @@ -1148,62 +1213,69 @@ ajv@^7.0.2: uri-js "^4.2.2" ajv@^8.0.1: - version "8.6.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" - integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw== + version "8.6.1" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz" + integrity sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" uri-js "^4.2.2" +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + ansi-colors@3.2.3: version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== ansi-colors@^4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-regex@^2.0.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-regex@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== ansi-regex@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" anymatch@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz" integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" @@ -1211,136 +1283,149 @@ anymatch@^2.0.0: anymatch@~3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz" integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + append-transform@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + resolved "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz" integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== dependencies: default-require-extensions "^3.0.0" aproba@^1.0.3: version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== archy@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= are-we-there-yet@~1.1.2: version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz" integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" arr-diff@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-unique@^0.3.2: version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + asn1@~0.2.3: version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz" integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assertion-error@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== assign-symbols@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= astral-regex@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async-each@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sign2@~0.7.0: version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -babel-plugin-add-module-exports@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz#6caa4ddbe1f578c6a5264d4d3e6c8a2720a7ca2b" - integrity sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg== - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" balanced-match@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base@^0.11.1: version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz" integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" @@ -1353,24 +1438,38 @@ base@^0.11.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" binary-extensions@^1.0.0: version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +boxen@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" + brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -1378,7 +1477,7 @@ brace-expansion@^1.1.7: braces@^2.3.1, braces@^2.3.2: version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" @@ -1394,24 +1493,19 @@ braces@^2.3.1, braces@^2.3.2: braces@~3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== - browser-stdout@1.3.1: version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserslist@^4.14.5, browserslist@^4.16.1: version "4.16.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz" integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== dependencies: caniuse-lite "^1.0.30001219" @@ -1422,12 +1516,17 @@ browserslist@^4.14.5, browserslist@^4.16.1: buffer-from@^1.0.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer-from@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + cache-base@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" @@ -1440,9 +1539,22 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + caching-transform@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + resolved "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz" integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== dependencies: hasha "^5.0.0" @@ -1452,7 +1564,7 @@ caching-transform@^4.0.0: call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" @@ -1460,45 +1572,34 @@ call-bind@^1.0.0, call-bind@^1.0.2: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30001219: version "1.0.30001230" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz" integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ== caseless@~0.12.0: version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -cfb@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/cfb/-/cfb-1.2.0.tgz#6a4d0872b525ed60349e1ef51fb4b0bf73eca9a8" - integrity sha512-sXMvHsKCICVR3Naq+J556K+ExBo9n50iKl6LGarlnvuA2035uMlGA/qVrc0wQtow5P1vJEw9UyrKLCbtIKz+TQ== +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== dependencies: - adler-32 "~1.2.0" - crc-32 "~1.2.0" - printj "~1.1.2" - -cfb@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/cfb/-/cfb-1.2.1.tgz#209429e4c68efd30641f6fc74b2d6028bd202402" - integrity sha512-wT2ScPAFGSVy7CY+aauMezZBnNrfnaLSrxHUHdea+Td/86vrk6ZquggV+ssBR88zNs0OnBkL2+lf9q0K+zVGzQ== - dependencies: - adler-32 "~1.3.0" - crc-32 "~1.2.0" - printj "~1.3.0" + check-error "^1.0.2" chai@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" + resolved "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz" integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== dependencies: assertion-error "^1.1.0" @@ -1510,16 +1611,24 @@ chai@^4.2.0: chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: ansi-styles "^4.1.0" @@ -1527,12 +1636,12 @@ chalk@^4.0.0, chalk@^4.1.0: check-error@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= chokidar@3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz" integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== dependencies: anymatch "~3.1.1" @@ -1545,9 +1654,24 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" +chokidar@^3.2.2: + version "3.5.2" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chokidar@^3.4.0: version "3.5.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== dependencies: anymatch "~3.1.1" @@ -1560,19 +1684,24 @@ chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.1" -chownr@^1.1.4: +chownr@^1.1.1: version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chownr@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + class-utils@^0.3.5: version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" @@ -1582,12 +1711,17 @@ class-utils@^0.3.5: clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.0: + version "2.2.1" + resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cliui@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + resolved "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz" integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: string-width "^3.1.0" @@ -1596,7 +1730,7 @@ cliui@^5.0.0: cliui@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: string-width "^4.2.0" @@ -1605,26 +1739,28 @@ cliui@^6.0.0: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + code-point-at@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codepage@~1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab" - integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== - collection-visit@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" @@ -1632,90 +1768,97 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== colorette@^1.2.2: version "1.2.2" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz" integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" commander@^4.0.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@~2.17.1: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - commondir@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= complex.js@^2.0.15: version "2.0.15" - resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.15.tgz#7add6848b4c1d12aa9262f7df925ebe7a51a7406" + resolved "https://registry.npmjs.org/complex.js/-/complex.js-2.0.15.tgz" integrity sha512-gDBvQU8IG139ZBQTSo2qvDFP+lANMGluM779csXOr6ny1NUtA3wkUnCFjlDNH/moAVfXtvClYt6G0zarFbtz5w== component-emitter@^1.2.1: version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= convert-source-map@^1.1.0, convert-source-map@^1.7.0: version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" copy-descriptor@^0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js-compat@^3.8.0: version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz" integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== dependencies: browserslist "^4.16.1" @@ -1723,17 +1866,17 @@ core-js-compat@^3.8.0: core-js@3: version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz" integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= coveralls@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" + resolved "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz" integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== dependencies: js-yaml "^3.13.1" @@ -1742,159 +1885,142 @@ coveralls@^3.1.0: minimist "^1.2.5" request "^2.88.2" -crc-32@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" - integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" -cssom@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" - integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== - dependencies: - cssom "~0.3.6" +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== dashdash@^1.12.0: version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz" integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" -data-urls@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" - integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== - dependencies: - abab "^2.0.3" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.0.0" - debug@3.2.6: version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" debug@4: version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== dependencies: ms "2.1.2" debug@^2.2.0, debug@^2.3.3: version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@^3.1.0: +debug@^3.1.0, debug@^3.2.6: version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decimal.js@^10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" - integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== - decimal.js@^10.3.1: version "10.3.1" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz" integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== decode-uri-component@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + deep-eql@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== dependencies: type-detect "^4.0.0" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3: version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deep-is@~0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - default-require-extensions@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + resolved "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz" integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== dependencies: strip-bom "^4.0.0" +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" @@ -1902,41 +2028,64 @@ define-property@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= detect-libc@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -diff@3.5.0: +diff@3.5.0, diff@^3.1.0: version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + resolved "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" -domexception@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" - integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: - webidl-conversions "^5.0.0" + is-obj "^2.0.0" + +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + +dts-bundle-generator@^5.9.0: + version "5.9.0" + resolved "https://registry.npmjs.org/dts-bundle-generator/-/dts-bundle-generator-5.9.0.tgz" + integrity sha512-wzxUa9nfGL09Sg+gD3jqA8kYIA9A/olenvP2MmZ6IGTlUxR8G1z4U+0+OfUEL6OH1mzn6xsD8EOVgpNnGDi8tQ== + dependencies: + typescript ">=3.0.1" + yargs "^15.3.1" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= ecc-jsbn@~0.1.1: version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" @@ -1944,29 +2093,36 @@ ecc-jsbn@~0.1.1: electron-to-chromium@^1.3.723: version "1.3.739" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz#f07756aa92cabd5a6eec6f491525a64fe62f98b9" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz" integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A== emoji-regex@^7.0.1: version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + enquirer@^2.3.5: version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== dependencies: ansi-colors "^4.1.1" es-abstract@^1.18.0-next.1: version "1.18.0-next.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz" integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== dependencies: call-bind "^1.0.2" @@ -1986,7 +2142,7 @@ es-abstract@^1.18.0-next.1: es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" @@ -1995,51 +2151,44 @@ es-to-primitive@^1.2.1: es6-error@^4.0.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== es6-promise@^4.0.3: version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + resolved "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== es6-promisify@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + resolved "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz" integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= dependencies: es6-promise "^4.0.3" escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + escape-latex@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1" + resolved "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz" integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -2047,24 +2196,24 @@ eslint-scope@^5.1.1: eslint-utils@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint-visitor-keys@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== eslint@^7.1.0: version "7.18.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" + resolved "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz" integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== dependencies: "@babel/code-frame" "^7.0.0" @@ -2107,55 +2256,50 @@ eslint@^7.1.0: espree@^7.3.0, espree@^7.3.1: version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: acorn "^7.4.0" acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.2.0: version "1.3.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz" integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" - integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== - expand-brackets@^2.1.4: version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" @@ -2168,14 +2312,14 @@ expand-brackets@^2.1.4: extend-shallow@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" @@ -2183,12 +2327,12 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== extglob@^2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" @@ -2202,44 +2346,39 @@ extglob@^2.0.4: extsprintf@1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= fast-deep-equal@^3.1.1: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fflate@^0.3.8: - version "0.3.11" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.3.11.tgz#2c440d7180fdeb819e64898d8858af327b042a5d" - integrity sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A== - file-entry-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz" integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== dependencies: flat-cache "^3.0.4" fill-range@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" @@ -2249,14 +2388,14 @@ fill-range@^4.0.0: fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" find-cache-dir@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" @@ -2265,7 +2404,7 @@ find-cache-dir@^2.0.0: find-cache-dir@^3.2.0: version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" @@ -2274,14 +2413,14 @@ find-cache-dir@^3.2.0: find-up@3.0.0, find-up@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -2289,7 +2428,7 @@ find-up@^4.0.0, find-up@^4.1.0: flat-cache@^3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: flatted "^3.1.0" @@ -2297,24 +2436,24 @@ flat-cache@^3.0.4: flat@^4.1.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + resolved "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz" integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== dependencies: is-buffer "~2.0.3" flatted@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== for-in@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= foreground-child@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz" integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== dependencies: cross-spawn "^7.0.0" @@ -2322,12 +2461,21 @@ foreground-child@^2.0.0: forever-agent@~0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + form-data@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz" integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== dependencies: asynckit "^0.4.0" @@ -2336,82 +2484,82 @@ form-data@^3.0.0: form-data@~2.3.2: version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" mime-types "^2.1.12" -frac@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b" - integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== - fraction.js@^4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff" + resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz" integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg== fragment-cache@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz" integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fromentries@^1.2.0: version "1.3.2" - resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + resolved "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz" integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== -fs-minipass@^1.2.7: +fs-minipass@^1.2.5: version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz" integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== dependencies: minipass "^2.6.0" fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" fs-readdir-recursive@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + resolved "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz" integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@~2.1.1: version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== fsevents@~2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz" integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw== +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= gauge@~2.7.3: version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz" integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" @@ -2425,22 +2573,22 @@ gauge@~2.7.3: gensync@^1.0.0-beta.1: version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-func-name@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= get-intrinsic@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz" integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== dependencies: function-bind "^1.1.1" @@ -2449,24 +2597,38 @@ get-intrinsic@^1.0.2: get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-parent@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz" integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" @@ -2474,14 +2636,21 @@ glob-parent@^3.1.0: glob-parent@^5.0.0, glob-parent@~5.1.0: version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: is-glob "^4.0.1" +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob@7.1.3: version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" @@ -2493,7 +2662,7 @@ glob@7.1.3: glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" @@ -2503,41 +2672,70 @@ glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +global-dirs@^2.0.1: + version "2.1.0" + resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz" + integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ== + dependencies: + ini "1.3.7" + globals@^11.1.0: version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^12.1.0: version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + resolved "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz" integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== dependencies: type-fest "^0.8.1" google-protobuf@^3.9.2: version "3.14.0" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.14.0.tgz#20373d22046e63831a5110e11a84f713cc43651e" + resolved "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.14.0.tgz" integrity sha512-bwa8dBuMpOxg7COyqkW6muQuvNnWgVN8TX/epDRGW5m0jcrmq2QJyCyiV8ZE2/6LaIIqJtiv9bYokFhfpy/o6w== +got@^9.6.0: + version "9.6.0" + resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + graceful-fs@^4.1.11, graceful-fs@^4.1.15: version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graceful-fs@^4.1.2: + version "4.2.6" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + growl@1.10.5: version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== har-schema@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: ajv "^6.12.3" @@ -2545,27 +2743,27 @@ har-validator@~5.1.3: has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-unicode@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" @@ -2574,7 +2772,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" @@ -2583,27 +2781,32 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + has@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hasha@^5.0.0: version "5.2.2" - resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + resolved "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz" integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== dependencies: is-stream "^2.0.0" @@ -2611,33 +2814,22 @@ hasha@^5.0.0: he@1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -html-encoding-sniffer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" - integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== - dependencies: - whatwg-encoding "^1.0.5" - html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== http-signature@~1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" @@ -2646,7 +2838,7 @@ http-signature@~1.2.0: https-proxy-agent@^2.2.1: version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz" integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== dependencies: agent-base "^4.3.0" @@ -2654,45 +2846,48 @@ https-proxy-agent@^2.2.1: https-proxy-agent@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz" integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== dependencies: agent-base "6" debug "4" -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= ignore@^4.0.6: version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" @@ -2700,74 +2895,91 @@ inflight@^1.0.4: inherits@2, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@1.3.7: + version "1.3.7" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + is-accessor-descriptor@^0.1.6: version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-binary-path@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz" integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-buffer@^1.1.5: version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@~2.0.3: version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== is-callable@^1.1.4, is-callable@^1.2.2: version "1.2.2" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz" integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-descriptor@^0.1.0: version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" @@ -2776,7 +2988,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" @@ -2785,152 +2997,175 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" +is-installed-globally@^0.3.1: + version "0.3.2" + resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + dependencies: + global-dirs "^2.0.1" + is-path-inside "^3.0.1" + is-negative-zero@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz" integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-npm@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz" + integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== + is-number@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-path-inside@^3.0.1: + version "3.0.3" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" -is-potential-custom-element-name@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" - integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== - is-regex@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz" integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== dependencies: has-symbols "^1.0.1" is-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== is-symbol@^1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz" integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== dependencies: has-symbols "^1.0.1" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isstream@~0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== istanbul-lib-hook@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + resolved "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz" integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== dependencies: append-transform "^2.0.0" istanbul-lib-instrument@^4.0.0: version "4.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz" integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== dependencies: "@babel/core" "^7.7.5" @@ -2940,7 +3175,7 @@ istanbul-lib-instrument@^4.0.0: istanbul-lib-processinfo@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" + resolved "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz" integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== dependencies: archy "^1.0.0" @@ -2953,7 +3188,7 @@ istanbul-lib-processinfo@^2.0.2: istanbul-lib-report@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: istanbul-lib-coverage "^3.0.0" @@ -2962,7 +3197,7 @@ istanbul-lib-report@^3.0.0: istanbul-lib-source-maps@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz" integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== dependencies: debug "^4.1.1" @@ -2971,7 +3206,7 @@ istanbul-lib-source-maps@^4.0.0: istanbul-reports@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz" integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== dependencies: html-escaper "^2.0.0" @@ -2979,17 +3214,17 @@ istanbul-reports@^3.0.2: javascript-natural-sort@^0.7.1: version "0.7.1" - resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" + resolved "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz" integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@3.13.1: version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== dependencies: argparse "^1.0.7" @@ -2997,7 +3232,7 @@ js-yaml@3.13.1: js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" @@ -3005,87 +3240,66 @@ js-yaml@^3.13.1: jsbn@~0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^16.2.2: - version "16.7.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" - integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== - dependencies: - abab "^2.0.5" - acorn "^8.2.4" - acorn-globals "^6.0.0" - cssom "^0.4.4" - cssstyle "^2.3.0" - data-urls "^2.0.0" - decimal.js "^10.2.1" - domexception "^2.0.1" - escodegen "^2.0.0" - form-data "^3.0.0" - html-encoding-sniffer "^2.0.1" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" - symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.1.0" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.5.0" - ws "^7.4.6" - xml-name-validator "^3.0.0" - jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-schema@0.2.3: version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stringify-safe@~5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + json5@^2.1.2: version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + resolved "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz" integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== dependencies: minimist "^1.2.5" jsprim@^1.2.2: version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz" integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" @@ -3093,54 +3307,60 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + lcov-parse@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + resolved "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz" integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= levn@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - locate-path@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" @@ -3148,63 +3368,68 @@ locate-path@^3.0.0: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" lodash.clonedeep@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= lodash.flattendeep@^4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= lodash.truncate@^4.4.2: version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.7.0: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - log-driver@^1.2.7: version "1.2.7" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + resolved "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== log-symbols@3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz" integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== dependencies: chalk "^2.4.2" long@4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== dependencies: pify "^4.0.1" @@ -3212,29 +3437,34 @@ make-dir@^2.0.0, make-dir@^2.1.0: make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + map-cache@^0.2.2: version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" mathjs@^9.4.4: - version "9.5.0" - resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-9.5.0.tgz#5e8ed06a8b539dadb0bcfbcb5d55fe88179daf86" - integrity sha512-a6QFEoLFLEI1cKr0B7lwAM1TTNAfNTxppimyqS5WhxGKXbV59DK4OX606z05PpuKpTiq7gTtPiSV0OAwFfxSvw== + version "9.4.4" + resolved "https://registry.npmjs.org/mathjs/-/mathjs-9.4.4.tgz" + integrity sha512-5EEJXnWOzLDgMHSFyw623nH+MTBZxquWwXtrzTsingOouJJ6UZG2VNO1lwH31IMt9aMno1axO6TYleIP4YSDaQ== dependencies: - "@babel/runtime" "^7.15.4" + "@babel/runtime" "^7.14.6" complex.js "^2.0.15" decimal.js "^10.3.1" escape-latex "^1.2.0" @@ -3246,7 +3476,7 @@ mathjs@^9.4.4: micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" @@ -3265,53 +3495,58 @@ micromatch@^3.1.10, micromatch@^3.1.4: mime-db@1.45.0: version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== mime-types@^2.1.12, mime-types@~2.1.19: version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz" integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== dependencies: mime-db "1.45.0" +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== -minipass@^2.6.0, minipass@^2.9.0: +minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + resolved "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" minipass@^3.0.0: - version "3.1.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732" - integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw== + version "3.1.6" + resolved "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== dependencies: yallist "^4.0.0" -minizlib@^1.3.3: +minizlib@^1.2.1: version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz" integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== dependencies: minipass "^2.9.0" minizlib@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" @@ -3319,27 +3554,34 @@ minizlib@^2.1.1: mixin-deep@^1.2.0: version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.5, mkdirp@^0.5.5: +mkdirp@0.5.5, mkdirp@^0.5.0: version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + mkdirp@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== mocha@^7.2.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" + resolved "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz" integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== dependencies: ansi-colors "3.2.3" @@ -3369,27 +3611,27 @@ mocha@^7.2.0: ms@2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@^2.1.1: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== nanomatch@^1.2.9: version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" @@ -3406,61 +3648,91 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= node-environment-flags@1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + resolved "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz" integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== dependencies: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" node-fetch@^2.6.1, node-fetch@~2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + version "2.6.7" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-modules-regexp@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + resolved "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= node-preload@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + resolved "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz" integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== dependencies: process-on-spawn "^1.0.0" node-releases@^1.1.71: version "1.1.72" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz" integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== +nodemon@^2.0.7: + version "2.0.7" + resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz" + integrity sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA== + dependencies: + chokidar "^3.2.2" + debug "^3.2.6" + ignore-by-default "^1.0.1" + minimatch "^3.0.4" + pstree.remy "^1.1.7" + semver "^5.7.1" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.3" + update-notifier "^4.1.0" + nopt@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + dependencies: + abbrev "1" + normalize-path@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + npmlog@^4.1.2: version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" @@ -3470,17 +3742,12 @@ npmlog@^4.1.2: number-is-nan@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== - nyc@^15.1.0: version "15.1.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + resolved "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz" integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== dependencies: "@istanbuljs/load-nyc-config" "^1.0.0" @@ -3513,17 +3780,17 @@ nyc@^15.1.0: oauth-sign@~0.9.0: version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4.1.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" @@ -3532,24 +3799,24 @@ object-copy@^0.1.0: object-inspect@^1.9.0: version "1.9.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz" integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-visit@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.assign@4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== dependencies: define-properties "^1.1.2" @@ -3559,7 +3826,7 @@ object.assign@4.1.0: object.assign@^4.1.0, object.assign@^4.1.2: version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: call-bind "^1.0.0" @@ -3569,7 +3836,7 @@ object.assign@^4.1.0, object.assign@^4.1.2: object.getownpropertydescriptors@^2.0.3: version "2.1.1" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544" + resolved "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz" integrity sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng== dependencies: call-bind "^1.0.0" @@ -3578,33 +3845,21 @@ object.getownpropertydescriptors@^2.0.3: object.pick@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - optionator@^0.9.1: version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: deep-is "^0.1.3" @@ -3614,42 +3869,47 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-locate@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-map@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + resolved "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz" integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== dependencies: aggregate-error "^3.0.0" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== package-hash@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + resolved "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz" integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== dependencies: graceful-fs "^4.1.15" @@ -3657,159 +3917,179 @@ package-hash@^4.0.0: lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + papaparse@^5.3.1: version "5.3.1" - resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.3.1.tgz#770b7a9124d821d4b2132132b7bd7dce7194b5b1" + resolved "https://registry.npmjs.org/papaparse/-/papaparse-5.3.1.tgz" integrity sha512-Dbt2yjLJrCwH2sRqKFFJaN5XgIASO9YOFeFP8rIBRG2Ain8mqk5r1M6DkfvqEVozVcz3r3HaUGw253hA1nLIcA== parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" -parse5@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - pascalcase@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-dirname@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= + version "1.1.1" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== performance-now@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= picomatch@^2.0.4, picomatch@^2.2.1: version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pirates@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz" integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== dependencies: node-modules-regexp "^1.0.0" pkg-dir@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: find-up "^3.0.0" pkg-dir@^4.1.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" posix-character-classes@^0.1.0: version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -printj@~1.1.0, printj@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" - integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== - -printj@~1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.2.3.tgz#2cfb2b192a1e5385dbbe5b46658ac34aa828508a" - integrity sha512-sanczS6xOJOg7IKDvi4sGOUOe7c1tsEzjwlLFH/zgwx/uyImVM9/rgBkc8AfiQa/Vg54nRd8mkm9yI7WV/O+WA== - -printj@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.0.tgz#9018a918a790e43707f10625d6e10187a367cff6" - integrity sha512-017o8YIaz8gLhaNxRB9eBv2mWXI2CtzhPJALnQTP+OPpuUfP0RMWqr/mHCzqVeu1AQxfzSfAtAq66vKB8y7Lzg== +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process-on-spawn@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + resolved "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz" integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== dependencies: fromentries "^1.2.0" progress@^2.0.0: version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -psl@^1.1.28, psl@^1.1.33: +psl@^1.1.28: version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +pstree.remy@^1.1.7: + version "1.1.8" + resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pupa@^2.0.1: + version "2.1.1" + resolved "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" + qs@~6.5.2: version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + readable-stream@^2.0.2, readable-stream@^2.0.6: version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" @@ -3822,7 +4102,7 @@ readable-stream@^2.0.2, readable-stream@^2.0.6: readdirp@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" @@ -3831,45 +4111,52 @@ readdirp@^2.2.1: readdirp@~3.2.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz" integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== dependencies: picomatch "^2.0.4" readdirp@~3.5.0: version "3.5.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz" integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== dependencies: picomatch "^2.2.1" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + regenerate-unicode-properties@^8.2.0: version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz" integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== dependencies: regenerate "^1.4.0" regenerate@^1.4.0: version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5: version "0.13.7" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" @@ -3877,12 +4164,12 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpp@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== regexpu-core@^4.7.1: version "4.7.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz" integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" @@ -3892,43 +4179,57 @@ regexpu-core@^4.7.1: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.2.0" +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + regjsgen@^0.5.1: version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== regjsparser@^0.6.4: version "0.6.6" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.6.tgz#6d8c939d1a654f78859b08ddcc4aa777f3fa800a" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz" integrity sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ== dependencies: jsesc "~0.5.0" release-zalgo@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + resolved "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz" integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= dependencies: es6-error "^4.0.1" remove-trailing-separator@^1.0.1: version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.6.1: version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= request@^2.88.2: version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== dependencies: aws-sign2 "~0.7.0" @@ -3954,129 +4255,136 @@ request@^2.88.2: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve-url@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + ret@~0.1.10: version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== rimraf@^2.6.2: version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.2: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-regex@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== - dependencies: - xmlchars "^2.2.0" - seedrandom@2.4.3: version "2.4.3" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.3.tgz#2438504dad33917314bff18ac4d794f16d6aaecc" + resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz" integrity sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw= seedrandom@^3.0.5: version "3.0.5" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" + resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + semver@7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: +semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.2.1: version "7.3.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz" integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== dependencies: lru-cache "^6.0.0" semver@^7.3.4: version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== dependencies: lru-cache "^6.0.0" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" @@ -4086,29 +4394,29 @@ set-value@^2.0.0, set-value@^2.0.1: shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== slash@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== slice-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: ansi-styles "^4.0.0" @@ -4117,7 +4425,7 @@ slice-ansi@^4.0.0: snapdragon-node@^2.0.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" @@ -4126,14 +4434,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" @@ -4147,7 +4455,7 @@ snapdragon@^0.8.1: source-map-resolve@^0.5.0: version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: atob "^2.1.2" @@ -4156,32 +4464,40 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16: +source-map-support@^0.5.16, source-map-support@^0.5.17: version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== spawn-wrap@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + resolved "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz" integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== dependencies: foreground-child "^2.0.0" @@ -4193,26 +4509,19 @@ spawn-wrap@^2.0.0: split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -ssf@~0.11.2: - version "0.11.2" - resolved "https://registry.yarnpkg.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c" - integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== - dependencies: - frac "~1.1.2" - sshpk@^1.7.0: version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz" integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" @@ -4227,7 +4536,7 @@ sshpk@^1.7.0: static-extend@^0.1.1: version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" @@ -4235,19 +4544,19 @@ static-extend@^0.1.1: stream-chain@^2.2.4: version "2.2.4" - resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.4.tgz#2e5e9858e00d25ebaf7e4339e8328ddcab5facad" + resolved "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.4.tgz" integrity sha512-9lsl3YM53V5N/I1C2uJtc3Kavyi3kNYN83VkKb/bMWRk7D9imiFyUPYa0PoZbLohSVOX1mYE9YsmwObZUsth6Q== stream-json@^1.7.3: version "1.7.3" - resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.7.3.tgz#8a2abe8b51a2e84ffbc8d09bca9d01dc70facae3" + resolved "https://registry.npmjs.org/stream-json/-/stream-json-1.7.3.tgz" integrity sha512-Y6dXn9KKWSwxOqnvHGcdZy1PK+J+7alBwHCeU3W9oRqm4ilLRA0XSPmd1tWwhg7tv9EIxJTMWh7KF15tYelKJg== dependencies: stream-chain "^2.2.4" string-width@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" @@ -4256,7 +4565,7 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2": version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" @@ -4264,16 +4573,25 @@ string-width@^1.0.1: string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.0.0: + version "4.2.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== dependencies: emoji-regex "^8.0.0" @@ -4282,7 +4600,7 @@ string-width@^4.1.0, string-width@^4.2.0: string.prototype.trimend@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz" integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== dependencies: call-bind "^1.0.0" @@ -4290,7 +4608,7 @@ string.prototype.trimend@^1.0.3: string.prototype.trimstart@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz" integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== dependencies: call-bind "^1.0.0" @@ -4298,83 +4616,83 @@ string.prototype.trimstart@^1.0.3: string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" strip-ansi@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz" integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== dependencies: ansi-regex "^5.0.0" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-json-comments@2.0.1: +strip-json-comments@2.0.1, strip-json-comments@~2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== supports-color@6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz" integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" -supports-color@^5.3.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" -symbol-tree@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== - -table@6.7.1: +table@*, table@6.7.1: version "6.7.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" + resolved "https://registry.npmjs.org/table/-/table-6.7.1.tgz" integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== dependencies: ajv "^8.0.1" @@ -4386,7 +4704,7 @@ table@6.7.1: table@^6.0.4: version "6.0.7" - resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" + resolved "https://registry.npmjs.org/table/-/table-6.0.7.tgz" integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== dependencies: ajv "^7.0.2" @@ -4395,21 +4713,21 @@ table@^6.0.4: string-width "^4.2.0" tar@^4.4.6: - version "4.4.19" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" - integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== - dependencies: - chownr "^1.1.4" - fs-minipass "^1.2.7" - minipass "^2.9.0" - minizlib "^1.3.3" - mkdirp "^0.5.5" - safe-buffer "^5.2.1" - yallist "^3.1.1" + version "4.4.13" + resolved "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" tar@^6.1.0: version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + resolved "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== dependencies: chownr "^2.0.0" @@ -4419,9 +4737,14 @@ tar@^6.1.0: mkdirp "^1.0.3" yallist "^4.0.0" +term-size@^2.1.0: + version "2.2.1" + resolved "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz" + integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== + test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" @@ -4430,29 +4753,34 @@ test-exclude@^6.0.0: text-table@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= tiny-emitter@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + resolved "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-object-path@^0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^2.1.0: version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" @@ -4460,14 +4788,14 @@ to-regex-range@^2.1.0: to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" @@ -4475,86 +4803,141 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" + nopt "~1.0.10" tough-cookie@~2.5.0: version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: psl "^1.1.28" punycode "^2.1.1" -tr46@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" - integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +ts-mocha@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" + integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw== dependencies: - punycode "^2.1.1" + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + +ts-node@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz" + integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg== + dependencies: + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + +tsconfig-paths@^3.5.0: + version "3.14.1" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" + integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.6" + strip-bom "^3.0.0" tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== typed-function@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-2.0.0.tgz#15ab3825845138a8b1113bd89e60cd6a435739e8" + resolved "https://registry.npmjs.org/typed-function/-/typed-function-2.0.0.tgz" integrity sha512-Hhy1Iwo/e4AtLZNK10ewVVcP2UEs408DS35ubP825w/YgSBK1KVLwALvvIG4yX75QJrxjCpcWkzkVRB0BwwYlA== typedarray-to-buffer@^3.1.5: version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" +typescript@>=3.0.1: + version "4.4.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz" + integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA== + +typescript@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== + +undefsafe@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz" + integrity sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== + dependencies: + debug "^2.2.0" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz" integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== unicode-match-property-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz" integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== dependencies: unicode-canonical-property-names-ecmascript "^1.0.4" @@ -4562,17 +4945,17 @@ unicode-match-property-ecmascript@^1.0.4: unicode-match-property-value-ecmascript@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz" integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== unicode-property-aliases-ecmascript@^1.0.4: version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz" integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== union-value@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" @@ -4580,14 +4963,16 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" unset-value@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" @@ -4595,142 +4980,130 @@ unset-value@^1.0.0: upath@^1.1.1: version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +update-notifier@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz" + integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== + dependencies: + boxen "^4.2.0" + chalk "^3.0.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.3.1" + is-npm "^4.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + pupa "^2.0.1" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + use@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= uuid@^3.3.2, uuid@^3.3.3: version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== v8-compile-cache@^2.0.3: version "2.2.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz" integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== verror@1.10.0: version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" - integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" - integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== - dependencies: - xml-name-validator "^3.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= -webidl-conversions@^5.0.0: +whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" - integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== - -webidl-conversions@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" - integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== - -whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= dependencies: - iconv-lite "0.4.24" - -whatwg-mimetype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" - integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== - -whatwg-url@^8.0.0, whatwg-url@^8.5.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" - integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== - dependencies: - lodash "^4.7.0" - tr46 "^2.1.0" - webidl-conversions "^6.1.0" + tr46 "~0.0.3" + webidl-conversions "^3.0.0" which-module@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@1.3.1: version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" -wmf@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da" - integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -word@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/word/-/word-0.4.0.tgz#691272aaecb9da96388fc873d2ecb48a17cbee54" - integrity sha512-Aq84KjS7Z9HSU14qf4l/NEouaqfJAZtE9zEz7TIvw9V/3oJeUbjQwhz7ggqbL7I7REt4Bz+9HuCWsBO5N7xChw== +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== dependencies: - cfb "^1.2.0" - jsdom "^16.2.2" + string-width "^4.0.0" + +word-wrap@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f" + integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA== wrap-ansi@^5.1.0: version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz" integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: ansi-styles "^3.2.0" @@ -4739,7 +5112,7 @@ wrap-ansi@^5.1.0: wrap-ansi@^6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: ansi-styles "^4.0.0" @@ -4748,7 +5121,7 @@ wrap-ansi@^6.2.0: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -4757,12 +5130,12 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write-file-atomic@^3.0.0: version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== dependencies: imurmurhash "^0.1.4" @@ -4770,60 +5143,38 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -ws@^7.4.6: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== - -xlsx@^0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.17.2.tgz#032bcca02ca01b5ebf7da93dcb035891f2c092af" - integrity sha512-RIhN6/oc/ZqYZqY4jz4AX92yNfULhtNrcZP1lknIcsyR+Ra8Zu/9F1lAZWncYbDex95iYQX/XNNNzNFXZjlNOQ== - dependencies: - adler-32 "~1.2.0" - cfb "^1.1.4" - codepage "~1.15.0" - commander "~2.17.1" - crc-32 "~1.2.0" - exit-on-epipe "~1.0.1" - fflate "^0.3.8" - ssf "~0.11.2" - wmf "~1.0.1" - word "~0.4.0" - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== -xmlchars@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +"xlsx@https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz": + version "0.19.3" + resolved "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz#f804c1850e2da5260165db0a059dc2a6099d55f3" y18n@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz" integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== y18n@^5.0.5: version "5.0.5" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz" integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== -yallist@^3.0.0, yallist@^3.1.1: +yallist@^3.0.0, yallist@^3.0.3: version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz" integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" @@ -4831,7 +5182,7 @@ yargs-parser@13.1.2, yargs-parser@^13.1.2: yargs-parser@^18.1.2: version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" @@ -4839,12 +5190,12 @@ yargs-parser@^18.1.2: yargs-parser@^20.2.2: version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== yargs-unparser@1.6.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz" integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== dependencies: flat "^4.1.0" @@ -4853,7 +5204,7 @@ yargs-unparser@1.6.0: yargs@13.3.2, yargs@^13.3.0: version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + resolved "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" @@ -4867,9 +5218,9 @@ yargs@13.3.2, yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^15.0.2: +yargs@^15.0.2, yargs@^15.3.1: version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" @@ -4886,7 +5237,7 @@ yargs@^15.0.2: yargs@^16.0.3: version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -4899,5 +5250,15 @@ yargs@^16.0.3: yarn@^1.22.10: version "1.22.10" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" + resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.10.tgz" integrity sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..fb57ccd1 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +