UNPKG

als-statistics

Version:

A powerful and lightweight JavaScript library for descriptive statistics, regression, clustering, outlier detection, and noise analysis using a flexible table/column architecture.

222 lines (186 loc) 8.38 kB
const { describe, it, before } = require('node:test'); const assert = require('node:assert'); const Table = require('../../lib/table/index'); const RatioColumn = require('../../lib/ratio-column/index'); const Column = require('../../lib/column/index'); describe('Table class', () => { it('should create a table', () => { const table = new Table(); assert.deepStrictEqual(table.columns, {}); assert.strictEqual(table.n, 0); }); it('should add columns', () => { const table = new Table(); const ratio = table.addColumn('Numbers', [10, 20, 30]); const strCol = table.addColumn('Category', ['A', 'B', 'C']); assert(ratio instanceof RatioColumn); assert(strCol instanceof Column); }); it('should filter and clear filters', () => { const table = new Table(); table.addColumn('Numbers', [10, 20, 30, 40, 50]); table.filterRows([2, 3]); assert.deepStrictEqual(table.filtered, { 2: true, 3: true }); table.clearAllRowsFilters(); assert.deepStrictEqual(table.filtered, {}); }); it('should compare two ratio columns', () => { const table = new Table(); table.addColumn('A', [1, 2, 3, 4, 5]); table.addColumn('B', [2, 3, 4, 5, 6]); const comparison = table.compare('A', 'B'); assert.strictEqual(comparison.covariancePopulation.toFixed(2), '2.00'); }); it('should compute a new column based on existing columns', () => { const table = new Table(); table.addColumn('A', [1, 2, 3]); table.addColumn('B', [4, 5, 6]); const newColumn = table.compute(({ A, B }) => A + B, 'Sum'); assert.deepStrictEqual(newColumn.values, [5, 7, 9]); assert(table.columns['Sum'] instanceof RatioColumn); }); it('should transpose the table', () => { const table = new Table(); table.addColumn('A', [1, 2, 3]); table.addColumn('B', [4, 5, 6]); const transposed = table.transpose(); assert.strictEqual(transposed.n, 2); assert.strictEqual(Object.keys(transposed.columns).length, 3); }); it('should calculate descriptive statistics', () => { const table = new Table(); table.addColumn('Numbers', [10, 20, 30, 40, 50]); const desc = table.descriptive('mean'); assert.strictEqual(desc.values[0], 30); }); it('should delete a column', () => { const table = new Table(); table.addColumn('A', [1, 2, 3]); table.addColumn('B', [4, 5, 6]); table.deleteColumn('A'); assert.strictEqual(Object.keys(table.columns).length, 1); assert.strictEqual(table.columns['A'], undefined); assert.strictEqual(table.n, 3); // n не уменьшается, что может быть нежелательно }); it('should clone table with filtered values', () => { const table = new Table(); table.addColumn('A', [1, 2, 3, 4, 5]); table.filterRows([1, 2, 3]); const cloned = table.clone(true); assert.deepStrictEqual(cloned.columns['A'].values, [1, 5]); assert.strictEqual(cloned.n, 2); }); it('should clone table with original values', () => { const table = new Table(); table.addColumn('A', [1, 2, 3, 4, 5]); table.filterRows([1, 2, 3]); const cloned = table.clone(false); assert.deepStrictEqual(cloned.columns['A'].values, [1, 2, 3, 4, 5]); assert.strictEqual(cloned.n, 5); }); it('should transpose with filtered rows', () => { const table = new Table(); table.addColumn('A', [1, 2, 3]); table.filterRows([1]); const transposed = table.transpose(); assert.strictEqual(Object.keys(transposed.columns).length, 2); // 0 и 2 }); }); describe('Cloning with filter columns', () => { let table before(() => { table = new Table(); table.addColumn("A", [1, 2, 3]); table.addColumn("B", [4, 5, 6]); table.addColumn("C", [7, 8, 9]); }) it('should clone table with explicit include', () => { const cloned = table.clone(true, ["A", "C"]); assert.deepStrictEqual(cloned.columns["A"].values, [1, 2, 3]); assert.deepStrictEqual(cloned.columns["C"].values, [7, 8, 9]); assert.strictEqual(cloned.columns["B"], undefined); }); it('should clone table with exclude only', () => { const cloned = table.clone(true, ["-B"]); assert.deepStrictEqual(cloned.columns["A"].values, [1, 2, 3]); assert.deepStrictEqual(cloned.columns["C"].values, [7, 8, 9]); assert.strictEqual(cloned.columns["B"], undefined); }); it('should clone table with regex and exclude', () => { table.addColumn("A1", [10, 11, 12]); const cloned = table.clone(true, [/^A/, "-A1"]); assert.deepStrictEqual(cloned.columns["A"].values, [1, 2, 3]); assert.strictEqual(cloned.columns["A1"], undefined); assert.strictEqual(cloned.columns["B"], undefined); }); it('should ignore exclude with include', () => { const cloned = table.clone(true, ["A", "-B"]); assert.deepStrictEqual(cloned.columns["A"].values, [1, 2, 3]); assert.strictEqual(cloned.columns["B"], undefined); assert.strictEqual(cloned.columns["C"], undefined); }); }) describe('Table class - New Features', () => { it('should create table with initial data using constructor', () => { const data = { Numbers: [10, 20, 30], Letters: ['A', 'B', 'C'] }; const table = new Table(data); assert.strictEqual(table.n, 3); assert.strictEqual(table.columnsN, 2); assert.ok(table.columns['Numbers'] instanceof RatioColumn); assert.ok(table.columns['Letters'] instanceof Column); assert.deepStrictEqual(table.columns['Numbers'].values, [10, 20, 30]); assert.deepStrictEqual(table.columns['Letters'].values, ['A', 'B', 'C']); }); it('should add row at the end when index is null', () => { const table = new Table(); table.addColumn('Numbers', [1, 2]); table.addColumn('Letters', ['A', 'B']); const result = table.addRow({ Numbers: 3, Letters: 'C' }); assert.strictEqual(result, true); assert.strictEqual(table.n, 3); assert.deepStrictEqual(table.columns['Numbers'].values, [1, 2, 3]); assert.deepStrictEqual(table.columns['Letters'].values, ['A', 'B', 'C']); }); it('should add row at specific index', () => { const table = new Table(); table.addColumn('Numbers', [1, 3]); table.addColumn('Letters', ['A', 'C']); const result = table.addRow({ Numbers: 2, Letters: 'B' }, 1); assert.strictEqual(result, true); assert.strictEqual(table.n, 3); assert.deepStrictEqual(table.columns['Numbers'].values, [1, 2, 3]); assert.deepStrictEqual(table.columns['Letters'].values, ['A', 'B', 'C']); }); it('should return false for invalid row data', () => { const table = new Table(); table.addColumn('Numbers', [1, 2]); table.addColumn('Letters', ['A', 'B']); // Неправильный тип let result = table.addRow({ Numbers: '3', Letters: 'C' }); assert.strictEqual(result, false); // Отсутствует ключ result = table.addRow({ Numbers: 3 }); assert.strictEqual(result, false); // Лишний ключ result = table.addRow({ Numbers: 3, Letters: 'C', Extra: 1 }); assert.strictEqual(result, false); }); it('should filter indexes with where method', () => { const table = new Table(); table.addColumn('Numbers', [10, 20, 30, 40]); table.addColumn('Letters', ['A', 'B', 'C', 'D']); const result = table.where((row) => row.Numbers < 25); assert.deepStrictEqual(result, [0, 1]); }); it('should respect existing filters in where method', () => { const table = new Table(); table.addColumn('Numbers', [10, 20, 30, 40]); table.addColumn('Letters', ['A', 'B', 'C', 'D']); table.filterRows([1]); // Фильтруем строку с 20 const result = table.where((row) => row.Numbers > 15); assert.deepStrictEqual(result, [2, 3]); }); });