-
Notifications
You must be signed in to change notification settings - Fork 0
/
scaleWithNulls.js
84 lines (60 loc) · 3.34 KB
/
scaleWithNulls.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Function: scaleWithNulls()
// Authors: Corey Devin Anderson and Kirankumar Batchu
// -----------------------------------------------------------------------------
// Description:
// Takes an input Array or math.js DenseMatrix and returns an Array of the same
// number of dimensions containing the mean-centered values or standard (z)
// scores.
// For arrays containing null values, nulls are removed prior to calculating
// means (and/or standard deviations), but are retained in the output array.
// The original version of this function (scale()) does not handle null
// values.
// -----------------------------------------------------------------------------
// Parameters:
// yourMatrix : a math.js "DenseMatrix" or JavaScript "Array" to be rescaled.
// method : rescaling to be applied to each array. Current options are "zscore"
// or "centered". Default is "centered".
// Returns:
// An Array of equal dimensions containing either mean-centerd or standard
// (z) scores.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Function: scaleWithNulls()
// START
function scaleWithNulls(yourMatrix, method = "centered") {
matrixType = math.typeOf(yourMatrix);
console.log("Input type: " + matrixType)
if (matrixType == "Array") {
yourMatrix = math.matrix(yourMatrix)
}
let yourMatrixDims = math.size(yourMatrix); // get dimensions of input matrix
let nrow = yourMatrixDims.get([0]); // get number of rows for iteration
let standardized = math.zeros(yourMatrixDims["_data"]); // make matrix of zeros to replace based on input array dimensions
for (i = 0; i < nrow; i++){ // for each vector (1D Array) in the matrix.
let row = yourMatrix["_data"][i]; // pull the Array out of dense matrix "_data" slot
// .filter the data to return only those that are not null
let rowClean = row.filter(function(x) {if (x != null) {return true} else {return false}});
// Get the mean and standard deviation of the null filtered Array
let rowMean = math.mean(rowClean); // take the mean of the Array using math.js
let rowStd = math.std(rowClean); // take the standard deviation of the Array using math.js
// .map a new Array of mean-centered values; returns null if null for that component.
// Round each to four decimal places.
// The +(unary plus operator) forces a number to be returned (otherwise you get a string).
let centered = row.map(function(x){if (x == null) {return null} else if (x != null) {return +(x - rowMean).toFixed(4)}});
// If the user chooses "zscore"
// divide each mean-centered value by the standard deviation to get an Array of z-scores
if (method == "zscore") {
standardized[i] = centered.map(function(x){
if (x == null) {
return null
} else if (x != null) {
return +(x / rowStd).toFixed(4)}});
} else if (method == "centered") {
standardized[i] = centered
}
}
return standardized;
}
// END
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------