node-red-contrib-prib-functions 0.18.0 → 0.19.2
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 +16 -17
- package/dataAnalysis/pca.js +399 -0
- package/documentation/loadInjector.png +0 -0
- package/matrix/matrix.js +48 -2
- package/matrix/matrixNode.html +144 -154
- package/matrix/matrixNode.js +26 -9
- package/package.json +16 -5
- package/test/01-base.js +88 -0
- package/test/data/.flow.json.backup +3192 -0
- package/test/data/flow.json +3212 -0
- package/test/data/settings.js +544 -0
- package/test/matrix/02base.js +36 -0
- package/testing/data/countries.csv +250 -0
- package/testing/hostAvailable.html +0 -2
- package/testing/load-injector.html +76 -21
- package/testing/load-injector.js +35 -54
- package/testing/test.js +1 -0
- package/transform/transform.html +61 -19
- package/transform/transform.js +110 -6
- package/documentation/LoadInjector.JPG +0 -0
package/README.md
CHANGED
|
@@ -111,8 +111,12 @@ Transformations:
|
|
|
111
111
|
* Array to ISO8385
|
|
112
112
|
* Array to Messages
|
|
113
113
|
* Array to xlsx / xlsx object (excel uses [xlsx][7])
|
|
114
|
-
* AVRO to JSON (uses [avsc][6])
|
|
114
|
+
* AVRO to JSON (uses [avsc][6])
|
|
115
|
+
* Buffer to comprossed
|
|
115
116
|
* Confluence to JSON
|
|
117
|
+
* Compressed to Buffer
|
|
118
|
+
* Compressed to String
|
|
119
|
+
* COmpressed to JSON
|
|
116
120
|
* CSV to Array
|
|
117
121
|
* CSV to HTML
|
|
118
122
|
* CSV to Messages
|
|
@@ -199,7 +203,13 @@ The levenshtein distance between two character strings.
|
|
|
199
203
|
Inject messages for a set period of time with varying think time.
|
|
200
204
|
Primary purpose is testing and useful for load/stress testing.
|
|
201
205
|
|
|
202
|
-
|
|
206
|
+
Has 3 extra data types
|
|
207
|
+
1. generated id - Unique id for each message
|
|
208
|
+
2. generated data - string text generated using [dummy-json][3]
|
|
209
|
+
3. generated json - json generated using [dummy-json][3]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+

|
|
203
213
|
|
|
204
214
|
Test example:
|
|
205
215
|
|
|
@@ -278,27 +288,14 @@ Test/example flow in test/generalTest.json
|
|
|
278
288
|
|
|
279
289
|
# Version
|
|
280
290
|
|
|
291
|
+
0.19.0 Improve load injector, fix bug in test comparing buffers, add compression tranforms
|
|
292
|
+
|
|
281
293
|
0.18.0 Add matrix node
|
|
282
294
|
|
|
283
295
|
0.17.0 Add finished wire to load injector
|
|
284
296
|
|
|
285
|
-
0.16.10 data analysis add eulcidean distance functions. Add array pairs
|
|
286
|
-
|
|
287
297
|
0.16.0 fix data analysis variance and stddev, add sample, add tests
|
|
288
298
|
|
|
289
|
-
0.14.2 fix general test flows. Add icon for data analysis
|
|
290
|
-
|
|
291
|
-
0.14.1 fix capitalization issue with levenshtein Distance
|
|
292
|
-
|
|
293
|
-
0.14.0 add xlsx transformer
|
|
294
|
-
|
|
295
|
-
0.13.0 Confluence AVRO message converter
|
|
296
|
-
|
|
297
|
-
0.12.0 added xml to json and json to xml. Make snappy installed separately as can cause install issues
|
|
298
|
-
|
|
299
|
-
0.11.1 Fix spelling of AVRO.
|
|
300
|
-
|
|
301
|
-
0.11.0 Transform for AVRO and snappy. Add JSON to CSV
|
|
302
299
|
|
|
303
300
|
|
|
304
301
|
# Author
|
|
@@ -318,3 +315,5 @@ Test/example flow in test/generalTest.json
|
|
|
318
315
|
[6]: https://www.npmjs.com/package/avsc "avsc"
|
|
319
316
|
|
|
320
317
|
[7]: https://www.npmjs.com/package/xlsx "xlsx"
|
|
318
|
+
|
|
319
|
+
[8]: https://www.npmjs.com/package/dummy-json "dummy-json"
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
function PCA() {
|
|
2
|
+
}
|
|
3
|
+
PCA.prototype.computeDeviationMatrix=function(matrix) {
|
|
4
|
+
return this.subtract(matrix, this.scale(this.multiply(this.unitSquareMatrix(matrix.length), matrix), 1 / matrix.length));
|
|
5
|
+
}
|
|
6
|
+
PCA.prototype.computeDeviationScores=function(deviation) {
|
|
7
|
+
return this.multiply(this.transpose(deviation), deviation);
|
|
8
|
+
}
|
|
9
|
+
PCA.prototype.computeVarianceCovariance=function(devSumOfSquares, sample) {
|
|
10
|
+
return this.scale(devSumOfSquares, 1 / (devSumOfSquares.length - sample?1:0));
|
|
11
|
+
}
|
|
12
|
+
PCA.prototype.computeSVD=function((atrix){
|
|
13
|
+
const result = svd(matrix);
|
|
14
|
+
const eigenvectors = result.U;
|
|
15
|
+
const eigenvalues = result.S;
|
|
16
|
+
return eigenvalues.map((value,i)=>{
|
|
17
|
+
return {
|
|
18
|
+
eigenvalue:value,
|
|
19
|
+
vector:eigenvectors.map((vector,j)=>-vector[i]) //HACK prevent completely negative vectors
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Get reduced dataset after removing some dimensions
|
|
24
|
+
PCA.prototype.computeAdjustedData=function(data, ...vectorObjs){
|
|
25
|
+
const vectors = vectorObjs.map((v)=>v.vector);
|
|
26
|
+
const matrixMinusMean = this.computeDeviationMatrix(data);
|
|
27
|
+
const adjustedData = this.multiply(vectors, this.transpose(matrixMinusMean));
|
|
28
|
+
const unit = this.unitSquareMatrix(data.length);
|
|
29
|
+
const avgData = this.scale(multiply(unit, data), -1 / data.length); //NOTE get the averages to add back
|
|
30
|
+
return {
|
|
31
|
+
adjustedData: adjustedData,
|
|
32
|
+
formattedAdjustedData:formatData(adjustedData, 2),
|
|
33
|
+
avgData: avgData,
|
|
34
|
+
selectedVectors: vectors
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Get original data set from reduced data set (decompress)
|
|
38
|
+
PCA.prototype.computeOriginalData=function(adjustedData, vectors, avgData) {
|
|
39
|
+
const originalWithoutMean = this.transpose(multiply(transpose(vectors), adjustedData));
|
|
40
|
+
const originalWithMean = this.subtract(originalWithoutMean, avgData);
|
|
41
|
+
return {
|
|
42
|
+
originalData: originalWithMean,
|
|
43
|
+
formattedOriginalData: this.formatData(originalWithMean, 2)
|
|
44
|
+
}
|
|
45
|
+
PCA.prototype.computePercentageExplained=function(vectors, ...selected) {
|
|
46
|
+
const total = vectors.map((v)=>v.eigenvalue).reduce((a,b)=>a+b);
|
|
47
|
+
const explained = selected.map((v)=>v.eigenvalue).reduce((a,b)=>a+b);
|
|
48
|
+
return (explained / total);
|
|
49
|
+
}
|
|
50
|
+
PCA.prototype.getEigenVectors=function(data) {
|
|
51
|
+
return this.computeSVD(this.computeVarianceCovariance(this.computeDeviationScores(this.computeDeviationMatrix(data)), false));
|
|
52
|
+
}
|
|
53
|
+
PCA.prototype.analyseTopResult=function(data){
|
|
54
|
+
const eigenVectors = this.getEigenVectors(data);
|
|
55
|
+
const sorted = this.eigenVectors.sort((a, b)=>b.eigenvalue-a.eigenvalue);
|
|
56
|
+
const selected = sorted[0].vector;
|
|
57
|
+
return this.computeAdjustedData(data, selected);
|
|
58
|
+
}
|
|
59
|
+
PCA.prototype.formatData=function(data, precision) {
|
|
60
|
+
const factor= Math.pow(10, precision || 2);
|
|
61
|
+
return data.map((d,i)=>d.map((n)=>Math.round(n * factor) / factor))
|
|
62
|
+
}
|
|
63
|
+
PCA.prototype.testMatrix=function(a){
|
|
64
|
+
if(!a[0] || !a.length) throw Error("Not matrix")
|
|
65
|
+
}
|
|
66
|
+
PCA.prototype.multiply=function(a, b){
|
|
67
|
+
this.testMatrix(a);
|
|
68
|
+
this.testMatrix(b);
|
|
69
|
+
if(b.length !== a[0].length) throw new Error('Columns in A should be the same as the number of rows in B');
|
|
70
|
+
const product = [];
|
|
71
|
+
for(let i = 0; i < a.length; i++) {
|
|
72
|
+
product[i] = []; //initialize a new row
|
|
73
|
+
for (var j = 0; j < b[0].length; j++) {
|
|
74
|
+
for (var k = 0; k < a[0].length; k++) {
|
|
75
|
+
(product[i])[j] = !!(product[i])[j] ? (product[i])[j] + (a[i])[k] * (b[k])[j] : (a[i])[k] * (b[k])[j];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return product;
|
|
80
|
+
}
|
|
81
|
+
PCA.prototype.subtract=function(a,b) {
|
|
82
|
+
if(!(a.length === b.length && a[0].length === b[0].length)) throw Error('Both A and B should have the same dimensions');
|
|
83
|
+
const result=[];
|
|
84
|
+
for(let i=0;i< a.length;i++){
|
|
85
|
+
result[i]=[];
|
|
86
|
+
for (let j = 0; j < b[0].length; j++) {
|
|
87
|
+
(result[i])[j] = (a[i])[j] - (b[i])[j];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
PCA.prototype.scale=function(matrix, factor) {
|
|
93
|
+
const result = [];
|
|
94
|
+
for(let i = 0; i < matrix.length; i++) {
|
|
95
|
+
result[i] = [];
|
|
96
|
+
for(let j = 0; j < matrix[0].length; j++) {
|
|
97
|
+
(result[i])[j] = (matrix[i])[j] * factor;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
PCA.prototype.unitSquareMatrix=function(rows) {
|
|
103
|
+
const result = [];
|
|
104
|
+
for(let i = 0; i < rows; i++) {
|
|
105
|
+
result[i] = [];
|
|
106
|
+
for (var j = 0; j < rows; j++) {
|
|
107
|
+
(result[i])[j] = 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
PCA.prototype.transpose=function(matrix) {
|
|
113
|
+
const operated = this.clone(matrix);
|
|
114
|
+
return operated[0].map((m,c)=>matrix.map((r)=>r[c]));
|
|
115
|
+
}
|
|
116
|
+
PCA.prototype.clone=function(m) {
|
|
117
|
+
return m.map(r=>r.map(c=>c));
|
|
118
|
+
}
|
|
119
|
+
PCA.prototype.svd=function(A) {
|
|
120
|
+
let temp;
|
|
121
|
+
const prec = Math.pow(2, -52) // double presision
|
|
122
|
+
const tolerance = 1.e-64 // precision;
|
|
123
|
+
const itmax = 50;
|
|
124
|
+
let c = 0;
|
|
125
|
+
let i = 0;
|
|
126
|
+
let j = 0;
|
|
127
|
+
let k = 0;
|
|
128
|
+
let l = 0;
|
|
129
|
+
const u = this.clone(A);
|
|
130
|
+
const m = u.length;
|
|
131
|
+
const n = u[0].length;
|
|
132
|
+
if (m < n) throw "Need more rows than columns"
|
|
133
|
+
|
|
134
|
+
const e = new Array(n); //vector1
|
|
135
|
+
const q = new Array(n); //vector2
|
|
136
|
+
for (i = 0; i < n; i++) e[i] = q[i] = 0.0;
|
|
137
|
+
var v = rep([n, n], 0);
|
|
138
|
+
|
|
139
|
+
function pythag(a, b) {
|
|
140
|
+
a = Math.abs(a)
|
|
141
|
+
b = Math.abs(b)
|
|
142
|
+
if(a > b) return a * Math.sqrt(1.0 + (b * b / a / a))
|
|
143
|
+
if(b == 0.0) return a
|
|
144
|
+
return b * Math.sqrt(1.0 + (a * a / b / b))
|
|
145
|
+
}
|
|
146
|
+
function rep(s, v, k=0) {
|
|
147
|
+
const n=s[k],
|
|
148
|
+
ret=Array(n);
|
|
149
|
+
let i;
|
|
150
|
+
if(k === s.length - 1) {
|
|
151
|
+
for(i=n-2; i >= 0; i-=2) {
|
|
152
|
+
ret[i+1] = v;
|
|
153
|
+
ret[i] = v;
|
|
154
|
+
}
|
|
155
|
+
if(i === -1) ret[0] = v;
|
|
156
|
+
return ret;
|
|
157
|
+
}
|
|
158
|
+
const kPlusOne=k++;
|
|
159
|
+
for (i= n-1; i>=0; i--) {
|
|
160
|
+
ret[i] = rep(s, v, kPlusOne);
|
|
161
|
+
}
|
|
162
|
+
return ret;
|
|
163
|
+
}
|
|
164
|
+
let f = 0.0;
|
|
165
|
+
let g = 0.0;
|
|
166
|
+
let h = 0.0;
|
|
167
|
+
let x = 0.0;
|
|
168
|
+
let y = 0.0;
|
|
169
|
+
let z = 0.0;
|
|
170
|
+
let s = 0.0;
|
|
171
|
+
|
|
172
|
+
for(i=0; i<n; i++) {
|
|
173
|
+
e[i] = g; //vector
|
|
174
|
+
s = 0.0; //sum
|
|
175
|
+
l = i+1; //stays i+1
|
|
176
|
+
for(j=i; j<m; j++)
|
|
177
|
+
s += (u[j][i] * u[j][i]);
|
|
178
|
+
if(s <= tolerance)
|
|
179
|
+
g = 0.0;
|
|
180
|
+
else {
|
|
181
|
+
f = u[i][i];
|
|
182
|
+
g = Math.sqrt(s);
|
|
183
|
+
if(f >= 0.0) g = -g;
|
|
184
|
+
h = f * g - s
|
|
185
|
+
u[i][i] = f - g;
|
|
186
|
+
for(j=l; j<n; j++) {
|
|
187
|
+
s = 0.0
|
|
188
|
+
for(k=i; k < m; k++)
|
|
189
|
+
s += u[k][i] * u[k][j]
|
|
190
|
+
f = s / h
|
|
191
|
+
for(k=i; k<m; k++)
|
|
192
|
+
u[k][j] += f * u[k][i]
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
q[i] = g
|
|
196
|
+
s = 0.0
|
|
197
|
+
for(j=l; j<n; j++)
|
|
198
|
+
s = s + u[i][j] * u[i][j]
|
|
199
|
+
if (s <= tolerance)
|
|
200
|
+
g = 0.0
|
|
201
|
+
else {
|
|
202
|
+
f = u[i][i + 1]
|
|
203
|
+
g = Math.sqrt(s)
|
|
204
|
+
if (f >= 0.0) g = -g
|
|
205
|
+
h = f * g - s
|
|
206
|
+
u[i][i + 1] = f - g;
|
|
207
|
+
for(j=l; j < n; j++) e[j] = u[i][j] / h
|
|
208
|
+
for(j=l; j < m; j++) {
|
|
209
|
+
s = 0.0
|
|
210
|
+
for(k=l; k<n; k++)
|
|
211
|
+
s += (u[j][k] * u[i][k])
|
|
212
|
+
for(k=l; k<n; k++)
|
|
213
|
+
u[j][k] += s * e[k]
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
y = Math.abs(q[i]) + Math.abs(e[i])
|
|
217
|
+
if(y > x)
|
|
218
|
+
x = y
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// accumulation of right hand transformations
|
|
222
|
+
for(i = n-1; i!=-1; i--) {
|
|
223
|
+
if (g != 0.0) {
|
|
224
|
+
h = g * u[i][i + 1]
|
|
225
|
+
for (j = l; j < n; j++)
|
|
226
|
+
v[j][i] = u[i][j] / h //u is array, v is square of columns
|
|
227
|
+
for (j = l; j < n; j++) {
|
|
228
|
+
s = 0.0
|
|
229
|
+
for (k = l; k < n; k++)
|
|
230
|
+
s += u[i][k] * v[k][j]
|
|
231
|
+
for (k = l; k < n; k++)
|
|
232
|
+
v[k][j] += (s * v[k][i])
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
for (j = l; j < n; j++) {
|
|
236
|
+
v[i][j] = 0;
|
|
237
|
+
v[j][i] = 0;
|
|
238
|
+
}
|
|
239
|
+
v[i][i] = 1;
|
|
240
|
+
g = e[i]
|
|
241
|
+
l = i
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// accumulation of left hand transformations
|
|
245
|
+
for(i=n-1; i != -1; i += -1) {
|
|
246
|
+
l = i + 1
|
|
247
|
+
g = q[i]
|
|
248
|
+
for (j = l; j < n; j++)
|
|
249
|
+
u[i][j] = 0;
|
|
250
|
+
if (g != 0.0) {
|
|
251
|
+
h = u[i][i] * g
|
|
252
|
+
for (j = l; j < n; j++) {
|
|
253
|
+
s = 0.0
|
|
254
|
+
for (k = l; k < m; k++) s += u[k][i] * u[k][j];
|
|
255
|
+
f = s / h
|
|
256
|
+
for (k = i; k < m; k++) u[k][j] += f * u[k][i];
|
|
257
|
+
}
|
|
258
|
+
for (j = i; j < m; j++) u[j][i] = u[j][i] / g;
|
|
259
|
+
} else
|
|
260
|
+
for (j = i; j < m; j++) u[j][i] = 0;
|
|
261
|
+
u[i][i] += 1;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// diagonalization of the bidiagonal form
|
|
265
|
+
prec = prec * x
|
|
266
|
+
for(k=n-1; k != -1; k--) {
|
|
267
|
+
const kPlusOne=k+1;
|
|
268
|
+
const kMinusOne=k-1;
|
|
269
|
+
for(let iteration = 0; iteration < itmax; iteration++) { // test f splitting
|
|
270
|
+
let test_convergence = false
|
|
271
|
+
for(l=k; l != -1; l--) {
|
|
272
|
+
if(Math.abs(e[l]) <= prec) {
|
|
273
|
+
test_convergence = true
|
|
274
|
+
break
|
|
275
|
+
}
|
|
276
|
+
if (Math.abs(q[l - 1]) <= prec)
|
|
277
|
+
break
|
|
278
|
+
}
|
|
279
|
+
if (!test_convergence) { // cancellation of e[l] if l>0
|
|
280
|
+
c = 0.0
|
|
281
|
+
s = 1.0
|
|
282
|
+
const l1 = l - 1
|
|
283
|
+
for(i=l; i<kPlusOne; i++) {
|
|
284
|
+
f = s * e[i]
|
|
285
|
+
e[i] = c * e[i]
|
|
286
|
+
if (Math.abs(f) <= prec)
|
|
287
|
+
break
|
|
288
|
+
g = q[i]
|
|
289
|
+
h = pythag(f, g)
|
|
290
|
+
q[i] = h
|
|
291
|
+
c = g / h
|
|
292
|
+
s = -f / h
|
|
293
|
+
for(j = 0; j<m; j++) {
|
|
294
|
+
y = u[j][l1]
|
|
295
|
+
z = u[j][i]
|
|
296
|
+
u[j][l1] = y * c + (z * s)
|
|
297
|
+
u[j][i] = -y * s + (z * c)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// test f convergence
|
|
302
|
+
z = q[k]
|
|
303
|
+
if(l == k) { //convergence
|
|
304
|
+
if(z < 0.0) { //q[k] is made non-negative
|
|
305
|
+
q[k] = -z
|
|
306
|
+
for (j=0; j<n; j++)
|
|
307
|
+
v[j][k] = -v[j][k]
|
|
308
|
+
}
|
|
309
|
+
break //break out of iteration loop and move on to next k value
|
|
310
|
+
}
|
|
311
|
+
if (iteration >= itmax - 1)
|
|
312
|
+
throw 'Error: no convergence.'
|
|
313
|
+
// shift from bottom 2x2 minor
|
|
314
|
+
x = q[l]
|
|
315
|
+
y = q[kMinusOne]
|
|
316
|
+
g = e[kMinusOne]
|
|
317
|
+
h = e[k]
|
|
318
|
+
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y)
|
|
319
|
+
g = pythag(f, 1.0)
|
|
320
|
+
if(f < 0.0)
|
|
321
|
+
f = ((x - z) * (x + z) + h * (y / (f - g) - h)) / x
|
|
322
|
+
else
|
|
323
|
+
f = ((x - z) * (x + z) + h * (y / (f + g) - h)) / x
|
|
324
|
+
// next QR transformation
|
|
325
|
+
c = 1.0
|
|
326
|
+
s = 1.0
|
|
327
|
+
for(i=l+1; i<kPlusOne; i++) {
|
|
328
|
+
g = e[i]
|
|
329
|
+
y = q[i]
|
|
330
|
+
h = s * g
|
|
331
|
+
g = c * g
|
|
332
|
+
z = pythag(f, h)
|
|
333
|
+
e[i - 1] = z
|
|
334
|
+
c = f / z
|
|
335
|
+
s = h / z
|
|
336
|
+
f = x * c + g * s
|
|
337
|
+
g = -x * s + g * c
|
|
338
|
+
h = y * s
|
|
339
|
+
y = y * c
|
|
340
|
+
for (j = 0; j < n; j++) {
|
|
341
|
+
x = v[j][i - 1]
|
|
342
|
+
z = v[j][i]
|
|
343
|
+
v[j][i - 1] = x * c + z * s
|
|
344
|
+
v[j][i] = -x * s + z * c
|
|
345
|
+
}
|
|
346
|
+
z = pythag(f, h)
|
|
347
|
+
q[i - 1] = z
|
|
348
|
+
c = f / z
|
|
349
|
+
s = h / z
|
|
350
|
+
f = c * g + s * y
|
|
351
|
+
x = -s * g + c * y
|
|
352
|
+
for (j = 0; j < m; j++) {
|
|
353
|
+
y = u[j][i - 1]
|
|
354
|
+
z = u[j][i]
|
|
355
|
+
u[j][i - 1] = y * c + z * s
|
|
356
|
+
u[j][i] = -y * s + z * c
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
e[l] = 0.0
|
|
360
|
+
e[k] = f
|
|
361
|
+
q[k] = x
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const ql=q.length;
|
|
365
|
+
for(i=0; i<ql; i++)
|
|
366
|
+
if (q[i] < prec) q[i] = 0
|
|
367
|
+
|
|
368
|
+
//sort eigenvalues
|
|
369
|
+
for(i=0; i<n; i++) {
|
|
370
|
+
for(j=i-1; j>=0; j--) {
|
|
371
|
+
if(q[j] < q[i]) {
|
|
372
|
+
c = q[j]
|
|
373
|
+
q[j] = q[i]
|
|
374
|
+
q[i] = c
|
|
375
|
+
const ul=u.length;
|
|
376
|
+
for(k = 0; k< ul; k++) {
|
|
377
|
+
temp = u[k][i];
|
|
378
|
+
u[k][i] = u[k][j];
|
|
379
|
+
u[k][j] = temp;
|
|
380
|
+
}
|
|
381
|
+
const vl=v.length;
|
|
382
|
+
for(k=0; k<vl; k++) {
|
|
383
|
+
temp = v[k][i];
|
|
384
|
+
v[k][i] = v[k][j];
|
|
385
|
+
v[k][j] = temp;
|
|
386
|
+
}
|
|
387
|
+
i = j
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
U: u,
|
|
393
|
+
S: q,
|
|
394
|
+
V: v
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
module.exports = PCA;
|
|
Binary file
|
package/matrix/matrix.js
CHANGED
|
@@ -30,7 +30,12 @@ Matrix.prototype.addCell=function(row,column,value){
|
|
|
30
30
|
this.vector[this.getIndex(row,column)]+=value;
|
|
31
31
|
return this;
|
|
32
32
|
}
|
|
33
|
-
Matrix.prototype.addRow=function(
|
|
33
|
+
Matrix.prototype.addRow=function(row,vectorIn){
|
|
34
|
+
if(vectorIn & row>=0){
|
|
35
|
+
this.forRowCells(row,(value,column,offset,vector)=>vector[offset]+=vectorIn[column]);
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
const vector=vectorIn?vectorIn:row;
|
|
34
39
|
if(this.size==this.sizeMax){
|
|
35
40
|
this.vector.copyWithin(0,this.columns,this.sizeMax);
|
|
36
41
|
this.rows--;
|
|
@@ -172,7 +177,7 @@ Matrix.prototype.fillArray=function(a){
|
|
|
172
177
|
Matrix.prototype.findColumnRow=function(column,call,startRow=0,endRow=this.rows-1){
|
|
173
178
|
let offset=startRow*this.columns+column;
|
|
174
179
|
for(let row=startRow;row<=this.rows;row++){
|
|
175
|
-
if(call.apply(this,[this.vector[offset],row,offset,this.vector])) {
|
|
180
|
+
if(call.apply(this,[this.vector[offset],row,column,offset,this.vector])) {
|
|
176
181
|
return row;
|
|
177
182
|
}
|
|
178
183
|
offset+=this.columns;
|
|
@@ -205,6 +210,17 @@ Matrix.prototype.forEachCell=function(call){
|
|
|
205
210
|
}
|
|
206
211
|
return this;
|
|
207
212
|
}
|
|
213
|
+
Matrix.prototype.forEachCellLowerTriangle=function(call){
|
|
214
|
+
this.testIsSquare();
|
|
215
|
+
for(let row=0;row<this.rows;row++) {
|
|
216
|
+
let offset=row*this.columns;
|
|
217
|
+
for(let column=0;column<=row;column++) {
|
|
218
|
+
call.apply(this,[this.vector[offset],row,column,this.vector,offset,this]);
|
|
219
|
+
offset++
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return this;
|
|
223
|
+
}
|
|
208
224
|
Matrix.prototype.forEachCellPairSet=function(matrix,call){
|
|
209
225
|
if(matrix instanceof Matrix){
|
|
210
226
|
if(this.rows!=matrix.rows) throw Error("number of rows different");
|
|
@@ -223,6 +239,17 @@ Matrix.prototype.forEachCellPairSet=function(matrix,call){
|
|
|
223
239
|
}
|
|
224
240
|
return this;
|
|
225
241
|
}
|
|
242
|
+
Matrix.prototype.forEachCellUpperTriangle=function(call){
|
|
243
|
+
this.testIsSquare();
|
|
244
|
+
for(let row=0;row<this.rows;row++) {
|
|
245
|
+
let offset=row*this.columns;
|
|
246
|
+
for(let column=row;column<=this.columns;column++) {
|
|
247
|
+
call.apply(this,[this.vector[offset],row,column,this.vector,offset,this]);
|
|
248
|
+
offset++
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
226
253
|
Matrix.prototype.forEachRow=function(call){
|
|
227
254
|
for(let row=0;row<this.rows;row++) {
|
|
228
255
|
const rowVector=this.getRow(row);
|
|
@@ -386,6 +413,11 @@ Matrix.prototype.getRow=function(row){
|
|
|
386
413
|
const start=row*this.columns;
|
|
387
414
|
return this.vector.subarray(start,start+this.columns);
|
|
388
415
|
}
|
|
416
|
+
Matrix.prototype.getVandermonde=function(vectorIn,columns){
|
|
417
|
+
const matrix = new Matrix(vectorIn.length,columns);
|
|
418
|
+
matrix.forEachCell((cell,row,column,vector,offset,object)=>vector[offset]=vectorIn[row]**column)
|
|
419
|
+
return matrix;
|
|
420
|
+
}
|
|
389
421
|
Matrix.prototype.getZeroed=function(row, column){
|
|
390
422
|
const offset=row*this.columns+column;
|
|
391
423
|
const value=this.vector[offset];
|
|
@@ -439,6 +471,16 @@ Matrix.prototype.multiplyRow=function(row,factor){
|
|
|
439
471
|
this.forRowCells(row,(cell,column,offset,vector)=>vector[offset]*=factor)
|
|
440
472
|
return this;
|
|
441
473
|
}
|
|
474
|
+
Matrix.prototype.norm=function(){
|
|
475
|
+
|
|
476
|
+
return Math.sqrt(this.reduce((aggregate,cell)=>aggregate+cell*cell))
|
|
477
|
+
}
|
|
478
|
+
Matrix.prototype.reduce=function(call,aggregate=0){
|
|
479
|
+
this.forEachCell((cell,row,column,vector,offset,object)=>
|
|
480
|
+
aggregate=call.apply(this,[aggregate,cell,row,column,vector,offset,object])
|
|
481
|
+
);
|
|
482
|
+
return aggregate;
|
|
483
|
+
}
|
|
442
484
|
Matrix.prototype.reducedRowEchelonForm=function(){
|
|
443
485
|
const lastColumn=this.columns-1;
|
|
444
486
|
for(let pivotColumn=0,pivotRow=0;pivotRow<this.rows;pivotRow++){
|
|
@@ -526,6 +568,10 @@ Matrix.prototype.setRow=function(vector,row){
|
|
|
526
568
|
this.vector.set(vector, row*this.columns);
|
|
527
569
|
return this;
|
|
528
570
|
}
|
|
571
|
+
Matrix.prototype.setRunningSum=function(){
|
|
572
|
+
this.forEachCellLowerTriangle((cell,row,column,vector,offset,object)=>vector[offset]=1);
|
|
573
|
+
return this;
|
|
574
|
+
}
|
|
529
575
|
Matrix.prototype.substract=function(matrix){
|
|
530
576
|
this.forEachCellPairSet(matrix,(cellA,cellB)=>cellA-cellB)
|
|
531
577
|
return this;
|