ml-matrix 6.8.2 → 6.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -19
- package/matrix.d.ts +56 -37
- package/matrix.js +118 -67
- package/matrix.umd.js +1 -1
- package/package.json +13 -15
- package/src/correlation.js +3 -1
- package/src/covariance.js +3 -1
- package/src/dc/nipals.js +3 -1
- package/src/matrix.js +96 -27
- package/src/util.js +14 -30
- package/src/views/columnSelection.js +1 -1
- package/src/views/rowSelection.js +1 -1
- package/src/views/selection.js +6 -5
- package/src/wrap/wrap.js +4 -2
package/src/matrix.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isAnyArray } from 'is-any-array';
|
|
1
2
|
import rescale from 'ml-array-rescale';
|
|
2
3
|
|
|
3
4
|
import { inspectMatrix, inspectMatrixWithOptions } from './inspect';
|
|
@@ -28,8 +29,9 @@ import {
|
|
|
28
29
|
checkColumnIndex,
|
|
29
30
|
checkColumnVector,
|
|
30
31
|
checkRange,
|
|
31
|
-
checkIndices,
|
|
32
32
|
checkNonEmpty,
|
|
33
|
+
checkRowIndices,
|
|
34
|
+
checkColumnIndices,
|
|
33
35
|
} from './util';
|
|
34
36
|
|
|
35
37
|
export class AbstractMatrix {
|
|
@@ -560,19 +562,47 @@ export class AbstractMatrix {
|
|
|
560
562
|
return this;
|
|
561
563
|
}
|
|
562
564
|
|
|
563
|
-
max() {
|
|
565
|
+
max(by) {
|
|
564
566
|
if (this.isEmpty()) {
|
|
565
567
|
return NaN;
|
|
566
568
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
569
|
+
switch (by) {
|
|
570
|
+
case 'row': {
|
|
571
|
+
const max = new Array(this.rows).fill(Number.NEGATIVE_INFINITY);
|
|
572
|
+
for (let row = 0; row < this.rows; row++) {
|
|
573
|
+
for (let column = 0; column < this.columns; column++) {
|
|
574
|
+
if (this.get(row, column) > max[row]) {
|
|
575
|
+
max[row] = this.get(row, column);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
572
578
|
}
|
|
579
|
+
return max;
|
|
573
580
|
}
|
|
581
|
+
case 'column': {
|
|
582
|
+
const max = new Array(this.columns).fill(Number.NEGATIVE_INFINITY);
|
|
583
|
+
for (let row = 0; row < this.rows; row++) {
|
|
584
|
+
for (let column = 0; column < this.columns; column++) {
|
|
585
|
+
if (this.get(row, column) > max[column]) {
|
|
586
|
+
max[column] = this.get(row, column);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return max;
|
|
591
|
+
}
|
|
592
|
+
case undefined: {
|
|
593
|
+
let max = this.get(0, 0);
|
|
594
|
+
for (let row = 0; row < this.rows; row++) {
|
|
595
|
+
for (let column = 0; column < this.columns; column++) {
|
|
596
|
+
if (this.get(row, column) > max) {
|
|
597
|
+
max = this.get(row, column);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return max;
|
|
602
|
+
}
|
|
603
|
+
default:
|
|
604
|
+
throw new Error(`invalid option: ${by}`);
|
|
574
605
|
}
|
|
575
|
-
return v;
|
|
576
606
|
}
|
|
577
607
|
|
|
578
608
|
maxIndex() {
|
|
@@ -591,19 +621,48 @@ export class AbstractMatrix {
|
|
|
591
621
|
return idx;
|
|
592
622
|
}
|
|
593
623
|
|
|
594
|
-
min() {
|
|
624
|
+
min(by) {
|
|
595
625
|
if (this.isEmpty()) {
|
|
596
626
|
return NaN;
|
|
597
627
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
628
|
+
|
|
629
|
+
switch (by) {
|
|
630
|
+
case 'row': {
|
|
631
|
+
const min = new Array(this.rows).fill(Number.POSITIVE_INFINITY);
|
|
632
|
+
for (let row = 0; row < this.rows; row++) {
|
|
633
|
+
for (let column = 0; column < this.columns; column++) {
|
|
634
|
+
if (this.get(row, column) < min[row]) {
|
|
635
|
+
min[row] = this.get(row, column);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
return min;
|
|
640
|
+
}
|
|
641
|
+
case 'column': {
|
|
642
|
+
const min = new Array(this.columns).fill(Number.POSITIVE_INFINITY);
|
|
643
|
+
for (let row = 0; row < this.rows; row++) {
|
|
644
|
+
for (let column = 0; column < this.columns; column++) {
|
|
645
|
+
if (this.get(row, column) < min[column]) {
|
|
646
|
+
min[column] = this.get(row, column);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
603
649
|
}
|
|
650
|
+
return min;
|
|
604
651
|
}
|
|
652
|
+
case undefined: {
|
|
653
|
+
let min = this.get(0, 0);
|
|
654
|
+
for (let row = 0; row < this.rows; row++) {
|
|
655
|
+
for (let column = 0; column < this.columns; column++) {
|
|
656
|
+
if (this.get(row, column) < min) {
|
|
657
|
+
min = this.get(row, column);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return min;
|
|
662
|
+
}
|
|
663
|
+
default:
|
|
664
|
+
throw new Error(`invalid option: ${by}`);
|
|
605
665
|
}
|
|
606
|
-
return v;
|
|
607
666
|
}
|
|
608
667
|
|
|
609
668
|
minIndex() {
|
|
@@ -1237,12 +1296,13 @@ export class AbstractMatrix {
|
|
|
1237
1296
|
}
|
|
1238
1297
|
|
|
1239
1298
|
selection(rowIndices, columnIndices) {
|
|
1240
|
-
|
|
1299
|
+
checkRowIndices(this, rowIndices);
|
|
1300
|
+
checkColumnIndices(this, columnIndices);
|
|
1241
1301
|
let newMatrix = new Matrix(rowIndices.length, columnIndices.length);
|
|
1242
|
-
for (let i = 0; i <
|
|
1243
|
-
let rowIndex =
|
|
1244
|
-
for (let j = 0; j <
|
|
1245
|
-
let columnIndex =
|
|
1302
|
+
for (let i = 0; i < rowIndices.length; i++) {
|
|
1303
|
+
let rowIndex = rowIndices[i];
|
|
1304
|
+
for (let j = 0; j < columnIndices.length; j++) {
|
|
1305
|
+
let columnIndex = columnIndices[j];
|
|
1246
1306
|
newMatrix.set(i, j, this.get(rowIndex, columnIndex));
|
|
1247
1307
|
}
|
|
1248
1308
|
}
|
|
@@ -1330,13 +1390,13 @@ export class AbstractMatrix {
|
|
|
1330
1390
|
}
|
|
1331
1391
|
switch (by) {
|
|
1332
1392
|
case 'row': {
|
|
1333
|
-
if (!
|
|
1393
|
+
if (!isAnyArray(mean)) {
|
|
1334
1394
|
throw new TypeError('mean must be an array');
|
|
1335
1395
|
}
|
|
1336
1396
|
return varianceByRow(this, unbiased, mean);
|
|
1337
1397
|
}
|
|
1338
1398
|
case 'column': {
|
|
1339
|
-
if (!
|
|
1399
|
+
if (!isAnyArray(mean)) {
|
|
1340
1400
|
throw new TypeError('mean must be an array');
|
|
1341
1401
|
}
|
|
1342
1402
|
return varianceByColumn(this, unbiased, mean);
|
|
@@ -1379,14 +1439,14 @@ export class AbstractMatrix {
|
|
|
1379
1439
|
const { center = this.mean(by) } = options;
|
|
1380
1440
|
switch (by) {
|
|
1381
1441
|
case 'row': {
|
|
1382
|
-
if (!
|
|
1442
|
+
if (!isAnyArray(center)) {
|
|
1383
1443
|
throw new TypeError('center must be an array');
|
|
1384
1444
|
}
|
|
1385
1445
|
centerByRow(this, center);
|
|
1386
1446
|
return this;
|
|
1387
1447
|
}
|
|
1388
1448
|
case 'column': {
|
|
1389
|
-
if (!
|
|
1449
|
+
if (!isAnyArray(center)) {
|
|
1390
1450
|
throw new TypeError('center must be an array');
|
|
1391
1451
|
}
|
|
1392
1452
|
centerByColumn(this, center);
|
|
@@ -1417,7 +1477,7 @@ export class AbstractMatrix {
|
|
|
1417
1477
|
case 'row': {
|
|
1418
1478
|
if (scale === undefined) {
|
|
1419
1479
|
scale = getScaleByRow(this);
|
|
1420
|
-
} else if (!
|
|
1480
|
+
} else if (!isAnyArray(scale)) {
|
|
1421
1481
|
throw new TypeError('scale must be an array');
|
|
1422
1482
|
}
|
|
1423
1483
|
scaleByRow(this, scale);
|
|
@@ -1426,7 +1486,7 @@ export class AbstractMatrix {
|
|
|
1426
1486
|
case 'column': {
|
|
1427
1487
|
if (scale === undefined) {
|
|
1428
1488
|
scale = getScaleByColumn(this);
|
|
1429
|
-
} else if (!
|
|
1489
|
+
} else if (!isAnyArray(scale)) {
|
|
1430
1490
|
throw new TypeError('scale must be an array');
|
|
1431
1491
|
}
|
|
1432
1492
|
scaleByColumn(this, scale);
|
|
@@ -1461,6 +1521,12 @@ function compareNumbers(a, b) {
|
|
|
1461
1521
|
return a - b;
|
|
1462
1522
|
}
|
|
1463
1523
|
|
|
1524
|
+
function isArrayOfNumbers(array) {
|
|
1525
|
+
return array.every((element) => {
|
|
1526
|
+
return typeof element === 'number';
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1464
1530
|
// Synonyms
|
|
1465
1531
|
AbstractMatrix.random = AbstractMatrix.rand;
|
|
1466
1532
|
AbstractMatrix.randomInt = AbstractMatrix.randInt;
|
|
@@ -1487,7 +1553,7 @@ export default class Matrix extends AbstractMatrix {
|
|
|
1487
1553
|
} else {
|
|
1488
1554
|
throw new TypeError('nColumns must be a positive integer');
|
|
1489
1555
|
}
|
|
1490
|
-
} else if (
|
|
1556
|
+
} else if (isAnyArray(nRows)) {
|
|
1491
1557
|
// Copy the values from the 2D array
|
|
1492
1558
|
const arrayData = nRows;
|
|
1493
1559
|
nRows = arrayData.length;
|
|
@@ -1502,6 +1568,9 @@ export default class Matrix extends AbstractMatrix {
|
|
|
1502
1568
|
if (arrayData[i].length !== nColumns) {
|
|
1503
1569
|
throw new RangeError('Inconsistent array dimensions');
|
|
1504
1570
|
}
|
|
1571
|
+
if (!isArrayOfNumbers(arrayData[i])) {
|
|
1572
|
+
throw new TypeError('Input data contains non-numeric values');
|
|
1573
|
+
}
|
|
1505
1574
|
this.data.push(Float64Array.from(arrayData[i]));
|
|
1506
1575
|
}
|
|
1507
1576
|
} else {
|
package/src/util.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isAnyArray } from 'is-any-array';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* @private
|
|
3
5
|
* Check that a row index is not out of bounds
|
|
@@ -64,46 +66,28 @@ export function checkColumnVector(matrix, vector) {
|
|
|
64
66
|
return vector;
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
export function checkIndices(matrix, rowIndices, columnIndices) {
|
|
68
|
-
return {
|
|
69
|
-
row: checkRowIndices(matrix, rowIndices),
|
|
70
|
-
column: checkColumnIndices(matrix, columnIndices),
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
69
|
export function checkRowIndices(matrix, rowIndices) {
|
|
75
|
-
if (
|
|
76
|
-
throw new TypeError('
|
|
70
|
+
if (!isAnyArray(rowIndices)) {
|
|
71
|
+
throw new TypeError('row indices must be an array');
|
|
77
72
|
}
|
|
78
73
|
|
|
79
|
-
let
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (rowOut) {
|
|
84
|
-
throw new RangeError('row indices are out of range');
|
|
74
|
+
for (let i = 0; i < rowIndices.length; i++) {
|
|
75
|
+
if (rowIndices[i] < 0 || rowIndices[i] >= matrix.rows) {
|
|
76
|
+
throw new RangeError('row indices are out of range');
|
|
77
|
+
}
|
|
85
78
|
}
|
|
86
|
-
|
|
87
|
-
if (!Array.isArray(rowIndices)) rowIndices = Array.from(rowIndices);
|
|
88
|
-
|
|
89
|
-
return rowIndices;
|
|
90
79
|
}
|
|
91
80
|
|
|
92
81
|
export function checkColumnIndices(matrix, columnIndices) {
|
|
93
|
-
if (
|
|
94
|
-
throw new TypeError('
|
|
82
|
+
if (!isAnyArray(columnIndices)) {
|
|
83
|
+
throw new TypeError('column indices must be an array');
|
|
95
84
|
}
|
|
96
85
|
|
|
97
|
-
let
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (columnOut) {
|
|
102
|
-
throw new RangeError('column indices are out of range');
|
|
86
|
+
for (let i = 0; i < columnIndices.length; i++) {
|
|
87
|
+
if (columnIndices[i] < 0 || columnIndices[i] >= matrix.columns) {
|
|
88
|
+
throw new RangeError('column indices are out of range');
|
|
89
|
+
}
|
|
103
90
|
}
|
|
104
|
-
if (!Array.isArray(columnIndices)) columnIndices = Array.from(columnIndices);
|
|
105
|
-
|
|
106
|
-
return columnIndices;
|
|
107
91
|
}
|
|
108
92
|
|
|
109
93
|
export function checkRange(matrix, startRow, endRow, startColumn, endColumn) {
|
|
@@ -4,7 +4,7 @@ import BaseView from './base';
|
|
|
4
4
|
|
|
5
5
|
export default class MatrixColumnSelectionView extends BaseView {
|
|
6
6
|
constructor(matrix, columnIndices) {
|
|
7
|
-
|
|
7
|
+
checkColumnIndices(matrix, columnIndices);
|
|
8
8
|
super(matrix, matrix.rows, columnIndices.length);
|
|
9
9
|
this.columnIndices = columnIndices;
|
|
10
10
|
}
|
|
@@ -4,7 +4,7 @@ import BaseView from './base';
|
|
|
4
4
|
|
|
5
5
|
export default class MatrixRowSelectionView extends BaseView {
|
|
6
6
|
constructor(matrix, rowIndices) {
|
|
7
|
-
|
|
7
|
+
checkRowIndices(matrix, rowIndices);
|
|
8
8
|
super(matrix, rowIndices.length, matrix.columns);
|
|
9
9
|
this.rowIndices = rowIndices;
|
|
10
10
|
}
|
package/src/views/selection.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { checkRowIndices, checkColumnIndices } from '../util';
|
|
2
2
|
|
|
3
3
|
import BaseView from './base';
|
|
4
4
|
|
|
5
5
|
export default class MatrixSelectionView extends BaseView {
|
|
6
6
|
constructor(matrix, rowIndices, columnIndices) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
this.
|
|
7
|
+
checkRowIndices(matrix, rowIndices);
|
|
8
|
+
checkColumnIndices(matrix, columnIndices);
|
|
9
|
+
super(matrix, rowIndices.length, columnIndices.length);
|
|
10
|
+
this.rowIndices = rowIndices;
|
|
11
|
+
this.columnIndices = columnIndices;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
set(rowIndex, columnIndex, value) {
|
package/src/wrap/wrap.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { isAnyArray } from 'is-any-array';
|
|
2
|
+
|
|
1
3
|
import WrapperMatrix1D from './WrapperMatrix1D';
|
|
2
4
|
import WrapperMatrix2D from './WrapperMatrix2D';
|
|
3
5
|
|
|
4
6
|
export function wrap(array, options) {
|
|
5
|
-
if (
|
|
6
|
-
if (array[0] &&
|
|
7
|
+
if (isAnyArray(array)) {
|
|
8
|
+
if (array[0] && isAnyArray(array[0])) {
|
|
7
9
|
return new WrapperMatrix2D(array);
|
|
8
10
|
} else {
|
|
9
11
|
return new WrapperMatrix1D(array, options);
|