diff --git a/SmallerTest.xlsx b/SmallerTest.xlsx new file mode 100644 index 0000000..ca91bcc Binary files /dev/null and b/SmallerTest.xlsx differ diff --git a/TestData.xlsx b/TestData.xlsx index f63621d..8194355 100644 Binary files a/TestData.xlsx and b/TestData.xlsx differ diff --git a/app/enpi_tool.js b/app/enpi_tool.js index a5fa65c..df460ff 100644 --- a/app/enpi_tool.js +++ b/app/enpi_tool.js @@ -1,3 +1,5 @@ +// import {findResults} from './app/maths.ts' + d3 = require('d3'); Json2csvParser = require('json2csv').Parser; converter = require('json-2-csv'); @@ -1966,9 +1968,11 @@ function exportData(){ //date export_formatJson[i][outputKeys[0]] = tables[z]["results"][k][outputKeys[0]][i][0]; + //pValue for model + //export_formatJson[i]["pValue"] = tables[z]["results"][k]["pValue"][i]; for (var j = 1; j < outputKeys.length; j++) { - if(outputKeys[j] != "comboNumber"){ + if(outputKeys[j] != "comboNumber" && outputKeys[j] != "rSquare"){ export_formatJson[i]["(" + dependentNames[z] + ")" + outputKeys[j]] = tables[z]["results"][k][outputKeys[j]][i]; } } diff --git a/app/maths.ts b/app/maths.ts index 5f9a220..cf80df3 100644 --- a/app/maths.ts +++ b/app/maths.ts @@ -1,4 +1,3 @@ - function getCombinations(array) { const results = [[]]; for (const value of array) { @@ -40,6 +39,8 @@ function findResults(json, dependentNumber){ var col = independentCombinations.length; var totalResult = []; + var calc = require('./app/regression_calc.js'); + for(var i = 0; i < col; i++){ var result = []; var variables = []; @@ -53,9 +54,11 @@ function findResults(json, dependentNumber){ Date: [], }; results["rSquare"] = []; + results[i + "rSquare"] = []; results["comboNumber"] = []; results[i + "Intercept"] = []; results[i + "fittedModel"] = []; + results[i + "pValue"] = []; for(var k = 0; k < independentCombinations[i].length; k++){ results[i + independentCombinations[i][k] + "Coeff"] = []; @@ -71,17 +74,19 @@ function findResults(json, dependentNumber){ independentVariables[k] = json.independent[independentCombinations[i][k]].slice(j, j + 12); independentNames[k] = independentCombinations[i][k]; } - var model = calc3(5, dependent, independentVariables, independentNames); + var model = calc.calc3(5, dependent, independentVariables, independentNames); results.Date[j] = json.date[dateKeys[0]][j]; results["rSquare"][j] = model.rSquare; + results[i + "rSquare"][j] = model.rSquare; results["comboNumber"][j] = i; results[i + "Intercept"][j] = model.intercept; + results[i + "pValue"][j] = model.pValue; for(var n = 0; n < independentCombinations[i].length; n++){ results[i + independentCombinations[i][n] + "Coeff"][j] = model.params[n]; - results[i + independentCombinations[i][n] + "pvalue"][j] = "p Value of " + independentCombinations[i][n]; + results[i + independentCombinations[i][n] + "pvalue"][j] = model.coeffPVals[n]; } results[i + "fittedModel"][j] = model.fittedModel; diff --git a/app/regression_calc.js b/app/regression_calc.js index 0c9f47f..c0f82f5 100644 --- a/app/regression_calc.js +++ b/app/regression_calc.js @@ -1,395 +1,310 @@ +const jStat = require('jStat').jStat; +const math = require('mathjs'); var json; -var N = 0; -var maxN = 16; -var M = 4; -var X = new makeArray2(M, maxN); -var Y = new Array; -var SX = 0; -var SY = 0; -var SXX = 0; -var SXY = 0; -var SYY = 0; -var m = 0; -var abort = false; +function slidingRegression() { + var calc = {}; + /***** methods *****/ -var regrCoeff = new Array; -var sigDig =3; - - - -function slidingRegression(){ - -} - - - - -function makeArray2 (X,Y) -{ - var count; - this.length = X+1; - for (var count = 0; count <= X+1; count++) - this[count] = new makeArray(Y); -} + //initializes a 'len' long array with all 0 values + calc.makeArray = function (len) { + var arr = []; + for (var count = 0; count <= len + 1; count++) + arr[count] = 0; + return arr; + } -function makeArray (Y) -{ - var count; - this.length = Y+1; - for (var count = 0; count <= Y+1; count++) - this[count] = 0; -} + //initializes an x by y matrix with all 0 values + calc.makeMatrix = function (x, y) { + var mat = []; + this.length = x + 1; + for (var count = 0; count <= x + 1; count++) + mat[count] = calc.makeArray(y); + return mat; + } -function det(A) -{ - var Length = A.length-1; - if (Length == 1) return (A[1][1]); - else - { - var i; - var sum = 0; - var factor = 1; - for (var i = 1; i <= Length; i++) - { - if (A[1][i] != 0) - { - minor = new makeArray2(Length-1,Length-1); - var m; - var n; - var theColumn; - for (var m = 1; m <= Length-1; m++) - { - if (m < i) theColumn = m; - else theColumn = m+1; - for (var n = 1; n <= Length-1; n++) - { - minor[n][m] = A[n+1][theColumn]; -// alert(minor[n][m]); + //calculates the determinant of a square matrix + calc.det = function (mat) { + var len = mat.length - 1; + if (len == 1) return (mat[1][1]); + else { + var sum = 0; + var factor = 1; + for (var i = 1; i <= len; i++) { + if (mat[1][i] != 0) { + // var minor = new this.makeMatrix(len - 1, len - 1); + var minor = this.makeMatrix(len - 1, len - 1); + var col; + for (var m = 1; m < len; m++) { + if (m < i) col = m; + else col = m + 1; + for (var n = 1; n < len; n++) { + minor[n][m] = mat[n + 1][col]; + } } + sum = sum + mat[1][i] * factor * this.det(minor); } - sum = sum + A[1][i]*factor*det(minor); - } - factor = -factor; - } // end i + factor = -factor; + } // end i + } + return sum; } - return(sum); -} -function inverse(A) { - var Length = A.length - 1; - var B = new makeArray2(Length, Length); - var d = det(A); - if (d == 0) alert("singular matrix--check data"); - else - { - var i; - var j; - for (var i = 1; i <= Length; i++) - { - for (var j = 1; j <= Length; j++) - { - - minor = new makeArray2(Length-1,Length-1); - var m; - var n; - var theColumn; - var theRow; - for (var m = 1; m <= Length-1; m++) - { - if (m < j) theColumn = m; - else theColumn = m+1; - for (var n = 1; n <= Length-1; n++) - { - if (n < i) theRow = n; - else theRow = n+1; - minor[n][m] = A[theRow][theColumn]; -// alert(minor[n][m]); + //returns the inverse of a square matrix + calc.inverse = function (mat) { + // var determinant = this.det(mat); + var determinant = math.det(mat); + if (determinant == 0) { + throw "calc.inverse called with singular matrix."; + } + var len = mat.length - 1; + // var inv = new this.makeMatrix(len, len); + var inv = this.makeMatrix(len, len); + + for (var i = 1; i <= len; i++) { + for (var j = 1; j <= len; j++) { + // minor = new this.makeMatrix(len - 1, len - 1); + minor = this.makeMatrix(len - 1, len - 1); + var col, row; + for (var m = 1; m <= len - 1; m++) { + if (m < j) col = m; + else col = m + 1; + for (var n = 1; n <= len - 1; n++) { + if (n < i) row = n; + else row = n + 1; + minor[n][m] = mat[row][col]; } } - var temp = (i+j)/2; + var temp = (i + j) / 2; if (temp == Math.round(temp)) factor = 1; else factor = -1; - B[j][i] = det(minor)*factor/d; - - - } // j - + inv[j][i] = this.det(minor) * factor / determinant; + } } + return inv; } - return(B); -} -function shiftRight(theNumber, k) { - if (k == 0) return (theNumber) - else - { - var k2 = 1; - var num = k; - if (num < 0) num = -num; - for (var i = 1; i <= num; i++) - { - k2 = k2*10 + calc.shiftRight = function(theNumber, k) { + if (k == 0) return (theNumber) + else { + var k2 = 1; + var num = k; + if (num < 0) num = -num; + for (var i = 1; i <= num; i++) { + k2 = k2 * 10 + } } + if (k > 0) { return (k2 * theNumber) } + else { return (theNumber / k2) } } - if (k>0) - {return(k2*theNumber)} - else - {return(theNumber/k2)} -} -function roundSigDig(theNumber, numDigits) { - with (Math) - { - if (theNumber == 0) return(0); - else if(abs(theNumber) < 0.000000000001) return(0); - else - { - var k = floor(log(abs(theNumber))/log(10))-numDigits - var k2 = shiftRight(round(shiftRight(abs(theNumber),-k)),k) - if (theNumber > 0) return(k2); - else return(-k2) + //rounds 'num' to have 'numDigits' significant digits + calc.roundSigDig = function (num, numDigits) { + with (Math) { + if (num == 0) return (0); + else if (abs(num) < 0.000000000001) return (0); + var k = floor(log(abs(num)) / log(10)) - numDigits + var k2 = this.shiftRight(round(this.shiftRight(abs(num), -k)), k) + if (num > 0) return (k2); + else return (-k2) } } -} - -function clearForms (){ - document.theForm.output.value="" - document.theForm.residual_values.value="" - document.theForm.RMEAN.value="" - - document.theForm.ESQV.value="" - document.theForm.mean1.value="" - document.theForm.mean2.value="" - - document.theForm.VR1.value="" - document.theForm.VR2.value="" - document.theForm.FR1.value="" - - document.theForm.SR2.value="" - document.theForm.DW.value="" - document.theForm.MAE.value="" - - - document.theForm.NCON.value="" - for (i = 0; i <= 15; i++) - { - document.theForm[3+6*i].value="" - document.theForm[4+6*i].value="" - document.theForm[5+6*i].value="" - document.theForm[6+6*i].value="" - document.theForm[7+6*i].value="" - document.theForm[8+6*i].value="" - } -} - -function stripSpaces (InString) { - OutString=""; - for (Count=0; Count < InString.length; Count++) { - TempChar=InString.substring (Count, Count+1); - if (TempChar!=" ") - OutString=OutString+TempChar; - } - return (OutString); -} - -function buildxy() { - e = 2.718281828459045; - pi = 3.141592653589793; - abort = false; - - with (Math) { - N = 0; - var searching = true; - - //This is set to the number of independent because we have in our json - var numvariables = Object.keys(json.independent).length; - - var independentKeys = Object.keys(json.independent); - var dependentKeys = Object.keys(json.dependent); - - - //Runs through as many rows as there are dates available - for (var i = 0; i < json.date.Date.length; i++) { - for(var j = 0; j < numvariables; j++){ - var key = independentKeys[j]; - X[j+1][N] = json["independent"][key][N]; + calc.construct = function (dependent, independent) { + with (Math) { + //number of datapoints + this.n = dependent.length; + //number of independent variables + this.m = independent.length; + // this.indep = this.makeMatrix(this.m, this.n); + // this.dep = this.makeArray(this.n); + this.indep = [[]]; + this.dep = []; + this.xBar = []; + + for (var i = 0; i < this.n; i++) { + this.indep[0][i] = 1; } - Y[N] = json["dependent"][dependentKeys[0]][N]; - - N++; - - } - } - M = numvariables; -} - -function buildxy2(dependent, independent){ - e = 2.718281828459045; - pi = 3.141592653589793; - abort = false; - - with (Math) { - N = 0; - var searching = true; - - //This is set to the number of independent because we have in our json - var numvariables = independent.length; - - //Runs through as many rows as there are dates available - for (var i = 0; i < dependent.length; i++) { - - for(var j = 0; j < numvariables; j++){ - X[j+1][N] = independent[j][N]; + //Runs through each row (12 months) + for (i = 0; i < this.n; i++) { + this.dep[i] = dependent[i][0]; + //Runs through each independent variable + for (var j = 0; j < this.m; j++) { + if (!this.indep[j + 1]) this.indep[j + 1] = []; + this.indep[j + 1][i] = independent[j][i][0]; + if (this.xBar[j]) { + //+s used to prevent JS from turning to string and concatenating + this.xBar[j] = +this.xBar[j] + +independent[j][i]; + } else { + this.xBar[j] = independent[j][i]; + } + } } - - Y[N] = dependent[N][0]; - - N++; + + for (j = 0; j < this.m; j++) { + this.xBar[j] /= this.n; + } + } } - M = numvariables; -} - -function linregr() -{ - if (!abort) { - e = 2.718281828459045; - pi = 3.141592653589793; + calc.linregr = function () { var k; var i; var j; var sum; - B = new makeArray(M+1); - P = new makeArray2(M+1, M+1); - invP = new makeArray2(M+1, M+1); - var mtemp = M+1; - -// if (N < M+1) alert("your need at least "+ mtemp +" points"); - with (Math) - { - for (i = 0; i < N; i++) X[0][i] = 1; - for (i = 1; i <= M+1; i++) - { + // this.B = new this.makeArray(this.m + 1); + // var P = new this.makeMatrix(this.m + 1, this.m + 1); + // this.invP = new this.makeMatrix(this.m + 1, this.m + 1); + //this.m + 1 + var B = this.makeArray(this.m - 1); + //this.m + 1, this.m + 1 + var P = this.makeMatrix(this.m - 1, this.m - 1); + // var invP = this.makeMatrix(this.m + 1, this.m + 1); + + with (Math) { + //i = 1; i <= this.m + 1 + for (i = 0; i <= this.m; i++) { sum = 0; - for (k = 0; k < N; k++){ - sum = sum + X[i-1][k]*Y[k]; + for (k = 0; k < this.n; k++) { + //indep[i-1] + sum = sum + this.indep[i][k] * this.dep[k]; } B[i] = sum; - for (j = 1; j <= M+1; j++) - { + //j = 1; j <= this.m + 1 + for (j = 0; j <= this.m; j++) { sum = 0; - for (k = 0; k < N; k++) sum = sum + X[i-1][k]*X[j-1][k]; + //indep[i - 1], indep[j - 1] + for (k = 0; k < this.n; k++) sum = sum + this.indep[i][k] * this.indep[j][k]; P[i][j] = sum; } } - invP = inverse(P); - for (k = 0; k <= M; k++) - { + // this.invP = this.inverse(this.P); + var invP = math.inv(P); + for (k = 0; k <= this.m; k++) { sum = 0; - for (j = 1; j <= M+1; j++) - { - sum = sum + invP[k+1][j]*B[j]; + //j = 1; j <= this.m + 1 + for (j = 0; j <= this.m; j++) { + //invP[k + 1] + sum = sum + invP[k][j] * B[j]; } -// alert("here"); - regrCoeff[k] = sum; + // alert("here"); + this.regrCoeff[k] = sum; } } } -} - -function calc2(){ - - var num = calc2.arguments[0]; - json = calc2.arguments[1]; - var model = { - fittedModel: "", - params: [], - yValues: "", - rSquare: "", - fStatistic: "", - mean: "", - variance: "", - mean_1: "", - mean_2: "", - vari1: "", - vari2: "", - firstO: "", - secondO: "", - durbanWatson: "", - meanAbsE: "", - normalityCond: "", - iResidual: [] - }; - if (num == 1) - { + calc.coeffTest = function (SSE, params) { + //sum of squares of x (sum of (xi-xBar)^2) + // var xSS = new Array; + // var tVals = new Array; + // for (var i = 0; i < this.m; i++) { + // xSS[i] = 0; + // for (var j = 0; j < this.n; j++) { + // //+s used to prevent JS from turning to string and concatenating + // xSS[i] = +xSS[i] + +Math.pow(this.indep[i][j] - this.xBar[i], 2); + // } + + // } + // sse / (this.n - 2) + + //sigma ^ 2 + var stdev = SSE / (this.n - this.m - 1); + //covariance matrix + var trans = math.transpose(this.indep); + var prod = math.multiply(this.indep, trans); + var inv = math.inv(prod); + var C = jStat.multiply(inv, stdev); + var tstats = []; + var pvals = []; + for (var i = 0; i < this.m; i++) { + tstats[i] = params[i] / math.sqrt(C[i+1][i+1]); + pvals[i] = jStat.ttest(tstats[i], this.n - this.m, 2); + } + + return pvals; } - else if (num == 2) - { - } - else if (num == 3) - { - } - else if (num == 4) - { - } - else if (num == 5) - { - with (Math) - { - buildxy(); -// alert("here"); - linregr(); + calc.calc3 = function (num, dependent, independent, independentNames) { + + var model = { + fittedModel: "", + params: [], + yValues: "", + rSquare: "", + fStatistic: "", + pValue: "", + coeffPVals: [], + mean: "", + variance: "", + mean_1: "", + mean_2: "", + vari1: "", + vari2: "", + firstO: "", + secondO: "", + durbanWatson: "", + meanAbsE: "", + normalityCond: "", + intercept: "", + iResidual: [] + }; + with (Math) { + this.construct(dependent, independent); + + this.linregr(); var predicted = new Array; var residual = new Array; - var output = "Y = " + roundSigDig(regrCoeff[0], sigDig); - var SE=0; + var output = "Y = " + this.roundSigDig(this.regrCoeff[0], this.sigDig); + model.intercept = this.regrCoeff[0]; + var SE = 0; var ST = 0; - - for (i = 1; i <=M; i++) { - output += " + (" + roundSigDig(regrCoeff[i], sigDig) + ")X" + i; - model.params[i-1] = roundSigDig(regrCoeff[i], sigDig); + for (var i = 1; i <= this.m; i++) { + output += " + (" + this.roundSigDig(this.regrCoeff[i], this.sigDig) + ")" + independentNames[i - 1]; + model.params[i - 1] = this.roundSigDig(this.regrCoeff[i], this.sigDig); } //console.log("The Fitted Model is :" + output); model.fittedModel = output; - for ( i = -1; i < N-1; i++) - { - y = regrCoeff[0]; + for (i = -1; i < this.n - 1; i++) { + this.y = this.regrCoeff[0]; - for (j = 1; j <=M; j++) y +=regrCoeff[j]*X[j][i+1]; + for (j = 1; j <= this.m; j++) this.y += this.regrCoeff[j] * this.indep[j][i + 1]; - //console.log("Predicted Y Value " + (i+2) + ": " + roundSigDig(y, sigDig)); - model.yValues[i+2] = "Predicted Y Value " + (i+2) + ": " + roundSigDig(y, sigDig); + //console.log("Predicted Y Value " + (i+2) + ": " + this.roundSigDig(y, this.sigDig)); + model.yValues[i + 2] = "Predicted Y Value " + (i + 2) + ": " + this.roundSigDig(this.y, this.sigDig); - predicted[i] = roundSigDig(y, sigDig); + predicted[i] = this.roundSigDig(this.y, this.sigDig); - residual[i] = (Y[i+1] - predicted[i]); + residual[i] = (this.dep[i + 1] - predicted[i]); //console.log("ith Residual: " + "("+(i+2)+")"+ Math.round(residual[i]*Math.pow(10,4))/Math.pow(10,4)+" "); - model.iResidual[i+1] = ("("+(i+2)+") "+ Math.round(residual[i]*Math.pow(10,4))/Math.pow(10,4)+"\t\t"); + model.iResidual[i + 1] = ("(" + (i + 2) + ") " + Math.round(residual[i] * Math.pow(10, 4)) / Math.pow(10, 4) + "\t\t"); SE += residual[i]; - ST += Y[i+1]; + //console.log(Number(Y[i+1])); + + //remove commas for getting number + // Y[i+1] = parseFloat(Y[i+1].replace(/,/g, '')); + // + // console.log(Number(Y[i+1])); + + ST += Number(this.dep[i + 1]); } @@ -397,384 +312,461 @@ function calc2(){ var MSE = 0; var MST = 0; - MSE = SE/N; - MST = ST/N; + //console.log(ST); + // console.log(N); + + MSE = SE / this.n; + MST = ST / this.n; var SSE = 0; var SST = 0; + for (i = 0; i < this.n; i++) { + SSE += (residual[i - 1] - MSE) * (residual[i - 1] - MSE); - for (i = 0; i < N; i++) { - SSE += (residual[i-1] - MSE)*(residual[i-1] - MSE); + SST += (this.dep[i] - MST) * (this.dep[i] - MST); + } - SST += (Y[i] - MST) *(Y[i] - MST); + // console.log(SST); + // console.log("/////////////////////////////////////////////////////////"); - } var FR; var RRSQ; - RRSQ = 1-(SSE/SST); + RRSQ = 1 - (SSE / SST); + + FR = ((this.n - this.m - 1) * (SST - SSE)) / (this.m * SSE); + var dfNum, dfDenom, pValue; + //number of parameters in model + dfNum = this.m; + //number of data points - number of parameters - 1 + dfDenom = this.n - this.m - 1; + pValue = jStat.ftest(FR, dfNum, dfDenom); + + model.coeffPVals = this.coeffTest(SSE, model.params); - FR = ((N-M-1)*(SST-SSE))/(M*SSE); //console.log("F-Statistic: " + FR); model.fStatistic = FR; + //console.log("P-value: " + pValue); + model.pValue = pValue; //console.log("R-Square: " + RRSQ); model.rSquare = RRSQ; + //start analysis************************************************************ - } - //start analysis************************************************************ + var PiD2 = PI / 2; var PiD4 = PI / 4; var Pi2 = 2 * PI + var e = 2.718281828459045235; var e10 = 1.105170918075647625 + var Deg = 180 / PI + function Norm(z) { + z = Math.abs(z) + var p = 1 + z * (0.04986735 + z * (0.02114101 + z * (0.00327763 + z * (0.0000380036 + z * (0.0000488906 + z * 0.000005383))))) + p = p * p; p = p * p; p = p * p + return 1 / (p * p) + } - var Pi=Math.PI; var PiD2=Pi/2; var PiD4=Pi/4; var Pi2=2*Pi - var e=2.718281828459045235; var e10 = 1.105170918075647625 - var Deg=180/Pi + function CalcNr(theForm) { + console.log("NR: " + Fmt(ANorm(eval(document.theForm.pn.value)))); + } - function Norm(z) { - z=Math.abs(z) - var p=1+ z*(0.04986735+ z*(0.02114101+ z*(0.00327763+ z*(0.0000380036+ z*(0.0000488906+ z*0.000005383))))) - p=p*p; p=p*p; p=p*p - return 1/(p*p) - } + function ANorm(p) { + var v = 0.5; var dv = 0.5; var z = 0 + while (dv > 1e-6) { z = 1 / v - 1; dv = dv / 2; if (Norm(z) > p) { v = v - dv } else { v = v + dv } } + return z + } - function CalcNr(theForm) { - console.log("NR: " + Fmt(ANorm(eval(document.theForm.pn.value)))); - } + function Fmt(x) { + var v + if (x >= 0) { v = '' + (x + 0.00005) } else { v = '' + (x - 0.00005) } + return v.substring(0, v.indexOf('.') + 5) + } + function FishF(f, n1, n2) { + var x = n2 / (n1 * f + n2) + if ((n1 % 2) == 0) { return StatCom(1 - x, n2, n1 + n2 - 4, n2 - 2) * Math.pow(x, n2 / 2) } + if ((n2 % 2) == 0) { return 1 - StatCom(x, n1, n1 + n2 - 4, n1 - 2) * Math.pow(1 - x, n1 / 2) } + + var th = Math.atan(Math.sqrt(n1 * f / n2)); var a = th / PiD2; var sth = Math.sin(th); var cth = Math.cos(th) + if (n2 > 1) { a = a + sth * cth * StatCom(cth * cth, 2, n2 - 3, -1) / PiD2 } + if (n1 == 1) { return 1 - a } + var c = 4 * StatCom(sth * sth, n2 + 1, n1 + n2 - 4, n2 - 2) * sth * Math.pow(cth, n2) / PI + if (n2 == 1) { return 1 - a + c / 2 } + var k = 2; while (k <= (n2 - 1) / 2) { c = c * k / (k - .5); k = k + 1 } + return 1 - a + c + } + function StatCom(q, i, j, b) { + var zz = 1; var z = zz; var k = i; while (k <= j) { zz = zz * q * k / (k - b); z = z + zz; k = k + 2 } + return z + } - function ANorm(p) { var v=0.5; var dv=0.5; var z=0 - while(dv>1e-6) { z=1/v-1; dv=dv/2; if(Norm(z)>p) { v=v-dv } else { v=v+dv } } - return z - } + function AFishF(p, n1, n2) { + var v = 0.5; var dv = 0.5; var f = 0 + while (dv > 1e-10) { f = 1 / v - 1; dv = dv / 2; if (FishF(f, n1, n2) > p) { v = v - dv } else { v = v + dv } } + return f + } - function Fmt(x) { - var v - if(x>=0) { v=''+(x+0.00005) } else { v=''+(x-0.00005) } - return v.substring(0,v.indexOf('.')+5) - } - function FishF(f,n1,n2) { - var x=n2/(n1*f+n2) - if((n1%2)==0) { return StatCom(1-x,n2,n1+n2-4,n2-2)*Math.pow(x,n2/2) } - if((n2%2)==0){ return 1-StatCom(x,n1,n1+n2-4,n1-2)*Math.pow(1-x,n1/2) } - - var th=Math.atan(Math.sqrt(n1*f/n2)); var a=th/PiD2; var sth=Math.sin(th); var cth=Math.cos(th) - if(n2>1) { a=a+sth*cth*StatCom(cth*cth,2,n2-3,-1)/PiD2 } - if(n1==1) { return 1-a } - var c=4*StatCom(sth*sth,n2+1,n1+n2-4,n2-2)*sth*Math.pow(cth,n2)/Pi - if(n2==1) { return 1-a+c/2 } - var k=2; while(k<=(n2-1)/2) {c=c*k/(k-.5); k=k+1 } - return 1-a+c - } - function StatCom(q,i,j,b) { - var zz=1; var z=zz; var k=i; while(k<=j) { zz=zz*q*k/(k-b); z=z+zz; k=k+2 } - return z - } + var SUME = 0.0; + var StdE = 0.0; + for (i = 0; i < this.n - 1; i++) { + SUME += residual[i - 1]; + } + var len = this.n - 1; + var mid = Math.floor(len / 2); + var SUME1 = 0; + var SUME2 = 0; + var NE1 = 0; + var NE2 = 0; + for (i = 0; i < mid; i++) { + SUME1 += residual[i - 1]; + NE1++; + } + for (i = mid; i < len; i++) { + SUME2 += residual[i - 1]; + NE2++; + } + var mean1 = SUME1 / NE1; + var mean2 = SUME2 / NE2; + // Do the math + var XE = SUME / len; + var XE1 = Math.round(10000000 * XE) / 10000000; + var mn1 = Math.round(10000000 * mean1) / 10000000; + var mn2 = Math.round(10000000 * mean2) / 10000000; + //console.log("Mean: " + XE1); + model.mean = XE1; + //console.log("Mean: First Half: " + mn1); + model.mean_1 = mn1; + //console.log("Mean: Second Half: " + mn2); + model.mean_2 = mn2; + + //calculate Standard Deviation + // Run through all the input, add those that have valid values + for (i = 0; i < this.n - 1; i++) { + StdE += Math.pow((residual[i - 1] - XE), 2); + } + var V1 = StdE / (len - 2); + var Vari2 = Math.round(V1 * 10000000) / 10000000; + //console.log("Variance : " + Vari2); + model.variance = Vari2; + //Standard deviation for both parts + var StdE1 = 0; + var StdE2 = 0; + for (i = 0; i < mid; i++) { + StdE1 += Math.pow(((residual[i - 1]) - mean1), 2); + } + for (i = mid; i < len; i++) { + StdE2 += Math.pow(((residual[i - 1]) - mean2), 2); + } + var VR1 = StdE1 / (NE1 - 2); + var var1 = Math.round(10000000 * VR1) / 10000000; + //console.log("Variance: The First Half: " + var1); + model.vari1 = var1; + var VR2 = StdE2 / (NE2 - 2); + var var2 = Math.round(10000000 * VR2) / 10000000; + //console.log("Variance: The Second Half: " + var2); + model.vari2 = var2; + + //AUTO CORRELATIONS + var listA = new Array(); + var listB = new Array(); + var listC = new Array(); + var listA2 = new Array(); + var a1 = 0; + var sumA = 0; + for (i = 1; i < len; i++) { + listA[a1] = parseFloat(residual[i - 1]); + sumA += parseFloat(residual[i - 1]); + a1++; + } + var a4 = 0; + var sumA2 = 0; + for (i = 2; i < len; i++) { + listA2[a4] = parseFloat(residual[i - 1]); + sumA2 += parseFloat(residual[i - 1]); + a4++; + } + var a2 = 0; + var sumB = 0; + for (i = 0; i < len - 1; i++) { + listB[a2] = parseFloat(residual[i - 1]); + sumB += parseFloat(residual[i - 1]); + a2++; + } + var a3 = 0; + var sumC = 0; + for (i = 0; i < len - 2; i++) { + listC[a3] = parseFloat(residual[i - 1]); + sumC += parseFloat(residual[i - 1]); + a3++; + } + var meanA = sumA / a1; + var meanA2 = sumA2 / a4; + var meanB = sumB / a2; + var meanC = sumC / a3; + //calculate variance and co-variance + var varA = 0; + var varB = 0; + var covarAB = 0; + for (i = 0; i < listA.length; i++) { + varA += Math.pow((listA[i] - meanA), 2); + varB += Math.pow((listB[i] - meanB), 2); + covarAB += ((listB[i] - meanB) * (listA[i] - meanA)); + } + var R1 = covarAB / Math.sqrt(varA * varB); + var R11 = Math.round(10000000 * R1) / 10000000; + //console.log("First Order Serial-Correlation: " + R11); + model.firstO = R11; + //****************** + var varA2 = 0; + var varC = 0; + var covarA2C = 0; + for (i = 0; i < listA2.length; i++) { + varA2 += Math.pow((listA2[i] - meanA2), 2); + varC += Math.pow((listC[i] - meanC), 2); + covarA2C += ((listA2[i] - meanA2) * (listC[i] - meanC)); + } + var R2 = covarA2C / Math.sqrt(varA2 * varC); + var R21 = Math.round(10000000 * R2) / 10000000; + //console.log("Second Order Serial-Correlation: " + R21); + model.secondO = R21; + + + var ERR = residual[-1]; + var SUMABSERR = Math.abs(ERR); + var SSE = residual[-1] * residual[-1]; + var DWNN = 0; + var DWND = (residual[-1] * residual[-1]); + var SUMERR = residual[-1]; + var DWN = 0; var MAE = 0; + for (i = 1; i < this.n; i++) { + ERR = residual[i - 1]; + SUMERR = SUMERR + ERR; + SUMABSERR = SUMABSERR + Math.abs(ERR); + DWNN = DWNN + (residual[i - 1] - residual[i - 2]) * (residual[i - 1] - residual[i - 2]); + DWND = DWND + (residual[i - 1] * residual[i - 1]); + SSE = SSE + ERR * ERR; + } + var MAE = SUMABSERR / this.n; + var DW = DWNN / DWND; + MAE = Math.round(MAE * 100000) / 100000; + //console.log("Mean Absolute Error: " + MAE); + model.meanAbsE = MAE; + DW = Math.round(DW * 100000) / 100000; + //console.log("Durbin Watson Statistic: " + DW); + model.durbanWatson = DW; + + //NORMALITY + var SUMF = 0; + var FXX = 0; + var FX = 0; + var xvalN = new Array(); + var freq = new Array(); + + + for (i = 0; i < len; i++) { + xvalN[i] = residual[i]; + freq[i] = 1 + } - function AFishF(p,n1,n2) { var v=0.5; var dv=0.5; var f=0 - while(dv>1e-10) { f=1/v-1; dv=dv/2; if(FishF(f,n1,n2)>p) { v=v-dv } else { v=v+dv } } - return f - } - var SUME = 0.0; - var StdE = 0.0; - for(i=0; i= 0) { + fval[i6] = 1 - (F1) / 2; + } + else { + fval[i6] = F1 / 2; + } + F1 = 0; + } - //AUTO CORRELATIONS - var listA = new Array(); - var listB = new Array(); - var listC = new Array(); - var listA2 = new Array(); - var a1 = 0; - var sumA=0; - for(i=1; i D025) { + //console.log("Evidence against normality"); + model.normalityCond = "Evidence against normality"; + } + else if ((t2N <= D025) && (t2N > D05)) { + //console.log("Sufficient evidence against normality"); + model.normalityCond = "Sufficient evidence against normality"; + } + else if ((t2N <= D05) && (t2N > D10)) { + //console.log("Suggestive evidence against normality"); + model.normalityCond = "Suggestive evidence against normality"; + } + else if ((t2N <= D10) && (t2N > D15)) { + //console.log("Little evidence against normality"); + model.normalityCond = "Little evidence against normality"; + } + else if (t2N <= D15) { + //console.log("No evidences against normality"); + model.normalityCond = "No evidences against normality"; + } + else { + //console.log("Evidence against normality"); + model.normalityCond = "Evidence against normality"; + } - for(i = 0; i < len; i++) { - xvalN[i] = residual[i]; - freq[i] = 1 } + console.log(model); + return model; + } - //calculate FX and FXX - for(i2=0; i2=0) { - fval[i6] = 1 - (F1)/2; } - else { - fval[i6] = F1/2; } - F1=0; - } + with (Math) { + N = 0; + var searching = true; - //calculate J from here - var jval = new Array(); - jval[0] = freqS[0]/SUMF; + //This is set to the number of independent because we have in our json + var numvariables = Object.keys(json.independent).length; - for(i7=1; i7 D025) { - //console.log("Evidence against normality"); - model.normalityCond = "Evidence against normality"; } - else if ((t2N <= D025) && (t2N > D05)) { - //console.log("Sufficient evidence against normality"); - model.normalityCond = "Sufficient evidence against normality"; - } - else if ((t2N <= D05) && (t2N > D10)) { - //console.log("Suggestive evidence against normality"); - model.normalityCond = "Suggestive evidence against normality"; - } - else if ((t2N <= D10) && (t2N > D15)) { - //console.log("Little evidence against normality"); - model.normalityCond = "Little evidence against normality"; - } - else if (t2N <=D15) { - //console.log("No evidences against normality"); - model.normalityCond = "No evidences against normality"; - } - else { - //console.log("Evidence against normality"); - model.normalityCond = "Evidence against normality"; - } - - } - else if (num == 6) - { } - return model; + this.m = numvariables; } -function calc3(num, dependent, independent, independentNames){ +function calc2() { + var num = calc2.arguments[0]; + json = calc2.arguments[1]; var model = { fittedModel: "", params: [], yValues: "", rSquare: "", fStatistic: "", + pval: "", mean: "", variance: "", mean_1: "", @@ -786,74 +778,59 @@ function calc3(num, dependent, independent, independentNames){ durbanWatson: "", meanAbsE: "", normalityCond: "", - intercept: "", iResidual: [] }; - if (num == 1) - { + if (num == 1) { } - else if (num == 2) - { + else if (num == 2) { } - else if (num == 3) - { + else if (num == 3) { } - else if (num == 4) - { + else if (num == 4) { } - else if (num == 5) - { - with (Math) - { - buildxy2(dependent, independent); - + else if (num == 5) { + with (Math) { + buildxy(); + // alert("here"); linregr(); var predicted = new Array; var residual = new Array; - var output = "Y = " + roundSigDig(regrCoeff[0], sigDig); - model.intercept = regrCoeff[0]; + var output = "Y = " + this.roundSigDig(regrCoeff[0], sigDig); var SE = 0; var ST = 0; - for (i = 1; i <=M; i++) { - output += " + (" + roundSigDig(regrCoeff[i], sigDig) + ")" + independentNames[i-1]; - model.params[i-1] = roundSigDig(regrCoeff[i], sigDig); + + for (i = 1; i <= this.m; i++) { + output += " + (" + this.roundSigDig(regrCoeff[i], sigDig) + ")f" + i; + model.params[i - 1] = this.roundSigDig(regrCoeff[i], sigDig); } //console.log("The Fitted Model is :" + output); model.fittedModel = output; - for ( i = -1; i < N-1; i++) - { + for (i = -1; i < N - 1; i++) { y = regrCoeff[0]; - for (j = 1; j <=M; j++) y +=regrCoeff[j]*X[j][i+1]; + for (j = 1; j <= this.m; j++) y += regrCoeff[j] * X[j][i + 1]; - //console.log("Predicted Y Value " + (i+2) + ": " + roundSigDig(y, sigDig)); - model.yValues[i+2] = "Predicted Y Value " + (i+2) + ": " + roundSigDig(y, sigDig); + //console.log("Predicted Y Value " + (i+2) + ": " + this.roundSigDig(y, sigDig)); + model.yValues[i + 2] = "Predicted Y Value " + (i + 2) + ": " + this.roundSigDig(y, sigDig); - predicted[i] = roundSigDig(y, sigDig); + predicted[i] = this.roundSigDig(y, sigDig); - residual[i] = (Y[i+1] - predicted[i]); + residual[i] = (Y[i + 1] - predicted[i]); //console.log("ith Residual: " + "("+(i+2)+")"+ Math.round(residual[i]*Math.pow(10,4))/Math.pow(10,4)+" "); - model.iResidual[i+1] = ("("+(i+2)+") "+ Math.round(residual[i]*Math.pow(10,4))/Math.pow(10,4)+"\t\t"); + model.iResidual[i + 1] = ("(" + (i + 2) + ") " + Math.round(residual[i] * Math.pow(10, 4)) / Math.pow(10, 4) + "\t\t"); SE += residual[i]; - //console.log(Number(Y[i+1])); - - //remove commas for getting number - // Y[i+1] = parseFloat(Y[i+1].replace(/,/g, '')); - // - // console.log(Number(Y[i+1])); - - ST += Number(Y[i+1]); + ST += Y[i + 1]; } @@ -861,30 +838,25 @@ function calc3(num, dependent, independent, independentNames){ var MSE = 0; var MST = 0; - //console.log(ST); - // console.log(N); - - MSE = SE/N; - MST = ST/N; + MSE = SE / N; + MST = ST / N; var SSE = 0; var SST = 0; - for (i = 0; i < N; i++) { - SSE += (residual[i-1] - MSE)*(residual[i-1] - MSE); - SST += (Y[i] - MST) *(Y[i] - MST); - } + for (i = 0; i < N; i++) { + SSE += (residual[i - 1] - MSE) * (residual[i - 1] - MSE); - // console.log(SST); - // console.log("/////////////////////////////////////////////////////////"); + SST += (Y[i] - MST) * (Y[i] - MST); + } var FR; var RRSQ; - RRSQ = 1-(SSE/SST); + RRSQ = 1 - (SSE / SST); - FR = ((N-M-1)*(SST-SSE))/(M*SSE); + FR = ((N - this.m - 1) * (SST - SSE)) / (this.m * SSE); //console.log("F-Statistic: " + FR); model.fStatistic = FR; //console.log("R-Square: " + RRSQ); @@ -896,80 +868,82 @@ function calc3(num, dependent, independent, independentNames){ //start analysis************************************************************ - var Pi=Math.PI; var PiD2=Pi/2; var PiD4=Pi/4; var Pi2=2*Pi - var e=2.718281828459045235; var e10 = 1.105170918075647625 - var Deg=180/Pi + var Pi = Math.PI; var PiD2 = Pi / 2; var PiD4 = Pi / 4; var Pi2 = 2 * Pi + var e = 2.718281828459045235; var e10 = 1.105170918075647625 + var Deg = 180 / Pi function Norm(z) { - z=Math.abs(z) - var p=1+ z*(0.04986735+ z*(0.02114101+ z*(0.00327763+ z*(0.0000380036+ z*(0.0000488906+ z*0.000005383))))) - p=p*p; p=p*p; p=p*p - return 1/(p*p) + z = Math.abs(z) + var p = 1 + z * (0.04986735 + z * (0.02114101 + z * (0.00327763 + z * (0.0000380036 + z * (0.0000488906 + z * 0.000005383))))) + p = p * p; p = p * p; p = p * p + return 1 / (p * p) } function CalcNr(theForm) { console.log("NR: " + Fmt(ANorm(eval(document.theForm.pn.value)))); } - function ANorm(p) { var v=0.5; var dv=0.5; var z=0 - while(dv>1e-6) { z=1/v-1; dv=dv/2; if(Norm(z)>p) { v=v-dv } else { v=v+dv } } + function ANorm(p) { + var v = 0.5; var dv = 0.5; var z = 0 + while (dv > 1e-6) { z = 1 / v - 1; dv = dv / 2; if (Norm(z) > p) { v = v - dv } else { v = v + dv } } return z } function Fmt(x) { var v - if(x>=0) { v=''+(x+0.00005) } else { v=''+(x-0.00005) } - return v.substring(0,v.indexOf('.')+5) - } - function FishF(f,n1,n2) { - var x=n2/(n1*f+n2) - if((n1%2)==0) { return StatCom(1-x,n2,n1+n2-4,n2-2)*Math.pow(x,n2/2) } - if((n2%2)==0){ return 1-StatCom(x,n1,n1+n2-4,n1-2)*Math.pow(1-x,n1/2) } - - var th=Math.atan(Math.sqrt(n1*f/n2)); var a=th/PiD2; var sth=Math.sin(th); var cth=Math.cos(th) - if(n2>1) { a=a+sth*cth*StatCom(cth*cth,2,n2-3,-1)/PiD2 } - if(n1==1) { return 1-a } - var c=4*StatCom(sth*sth,n2+1,n1+n2-4,n2-2)*sth*Math.pow(cth,n2)/Pi - if(n2==1) { return 1-a+c/2 } - var k=2; while(k<=(n2-1)/2) {c=c*k/(k-.5); k=k+1 } - return 1-a+c - } - function StatCom(q,i,j,b) { - var zz=1; var z=zz; var k=i; while(k<=j) { zz=zz*q*k/(k-b); z=z+zz; k=k+2 } + if (x >= 0) { v = '' + (x + 0.00005) } else { v = '' + (x - 0.00005) } + return v.substring(0, v.indexOf('.') + 5) + } + function FishF(f, n1, n2) { + var x = n2 / (n1 * f + n2) + if ((n1 % 2) == 0) { return StatCom(1 - x, n2, n1 + n2 - 4, n2 - 2) * Math.pow(x, n2 / 2) } + if ((n2 % 2) == 0) { return 1 - StatCom(x, n1, n1 + n2 - 4, n1 - 2) * Math.pow(1 - x, n1 / 2) } + + var th = Math.atan(Math.sqrt(n1 * f / n2)); var a = th / PiD2; var sth = Math.sin(th); var cth = Math.cos(th) + if (n2 > 1) { a = a + sth * cth * StatCom(cth * cth, 2, n2 - 3, -1) / PiD2 } + if (n1 == 1) { return 1 - a } + var c = 4 * StatCom(sth * sth, n2 + 1, n1 + n2 - 4, n2 - 2) * sth * Math.pow(cth, n2) / Pi + if (n2 == 1) { return 1 - a + c / 2 } + var k = 2; while (k <= (n2 - 1) / 2) { c = c * k / (k - .5); k = k + 1 } + return 1 - a + c + } + function StatCom(q, i, j, b) { + var zz = 1; var z = zz; var k = i; while (k <= j) { zz = zz * q * k / (k - b); z = z + zz; k = k + 2 } return z } - function AFishF(p,n1,n2) { var v=0.5; var dv=0.5; var f=0 - while(dv>1e-10) { f=1/v-1; dv=dv/2; if(FishF(f,n1,n2)>p) { v=v-dv } else { v=v+dv } } + function AFishF(p, n1, n2) { + var v = 0.5; var dv = 0.5; var f = 0 + while (dv > 1e-10) { f = 1 / v - 1; dv = dv / 2; if (FishF(f, n1, n2) > p) { v = v - dv } else { v = v + dv } } return f } var SUME = 0.0; var StdE = 0.0; - for(i=0; i=0) { - fval[i6] = 1 - (F1)/2; } - else { - fval[i6] = F1/2; } - F1=0; + if (zvalS[i6] >= 0) { + fval[i6] = 1 - (F1) / 2; + } + else { + fval[i6] = F1 / 2; + } + F1 = 0; } //calculate J from here var jval = new Array(); - jval[0] = freqS[0]/SUMF; + jval[0] = freqS[0] / SUMF; - for(i7=1; i7 D025) { + if (t2N > D025) { //console.log("Evidence against normality"); model.normalityCond = "Evidence against normality"; } - else if ((t2N <= D025) && (t2N > D05)) { + else if ((t2N <= D025) && (t2N > D05)) { //console.log("Sufficient evidence against normality"); model.normalityCond = "Sufficient evidence against normality"; } - else if ((t2N <= D05) && (t2N > D10)) { + else if ((t2N <= D05) && (t2N > D10)) { //console.log("Suggestive evidence against normality"); model.normalityCond = "Suggestive evidence against normality"; } - else if ((t2N <= D10) && (t2N > D15)) { + else if ((t2N <= D10) && (t2N > D15)) { //console.log("Little evidence against normality"); model.normalityCond = "Little evidence against normality"; } - else if (t2N <=D15) { + else if (t2N <= D15) { //console.log("No evidences against normality"); model.normalityCond = "No evidences against normality"; } @@ -1230,10 +1206,10 @@ function calc3(num, dependent, independent, independentNames){ } } - else if (num == 6) - { + else if (num == 6) { } - - console.log(model); return model; } +*/ + + diff --git a/package.json b/package.json index fba8dcb..17fdb0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Sliding-Regression-Tool", "version": "0.0.1", - "author": "Michael Whitmer, Preston Shires, Michael Kaminski", + "author": "Michael Whitmer, Preston Shires, Michael Kaminski, Benjamin Rappoport", "license": "MIT", "main": "main.js", "scripts": { @@ -25,11 +25,13 @@ "excel-as-json": "^2.0.1", "file-saver": "^1.3.8", "font-awesome": "^4.7.0", + "jStat": "^1.7.1", "jquery": "^3.3.1", "json-2-csv": "^2.2.0", "json2csv": "^4.1.2", "jsonexport": "^2.0.11", "less": "^3.0.1", + "mathjs": "^5.0.4", "ng2-bootstrap-modal": "^1.0.1", "ng2-toasty": "^4.0.2", "rxjs": "^5.5.6",