11
set
2012
Regressão Linear, de Potência e Polinomial em Javascript
Eu custei a conseguir fazer funcionar e a achar na internet, então resolvi trazer pra cá.
var regression = { |
|
|
|
linear: function(x, y){ |
|
|
|
var lr = {}; |
|
var n = y.length; |
|
var sum_x = 0; |
|
var sum_y = 0; |
|
var sum_xy = 0; |
|
var sum_xx = 0; |
|
var sum_yy = 0; |
|
|
|
for (var i = 0; i < y.length; i++) { |
|
sum_x += x[i]; |
|
sum_y += y[i]; |
|
sum_xy += (x[i] * y[i]); |
|
sum_xx += (x[i] * x[i]); |
|
sum_yy += (y[i] * y[i]); |
|
} |
|
|
|
lr['slope'] = ((n * sum_xy) - (sum_x * sum_y)) / ((n * sum_xx) - (sum_x * sum_x)); |
|
lr['intercept'] = (sum_y - (lr.slope * sum_x)) / n; |
|
lr['r2'] = Math.pow((n*sum_xy - sum_x*sum_y) / Math.sqrt(((n * sum_xx) - (sum_x * sum_x)) * ((n * sum_yy) - (sum_y * sum_y))), 2); |
|
lr['fn'] = function (x) { |
|
return this.slope * x + this.intercept; |
|
}; |
|
|
|
return lr; |
|
|
|
}, |
|
|
|
power: function(data_x, data_y) { |
|
|
|
var n = data_x.length; |
|
if (n < 2 || n != data_y.length) { |
|
return false; |
|
} |
|
|
|
var sumX = 0; |
|
var sumY = 0; |
|
var sumXX = 0; |
|
var sumXY = 0; |
|
for (var i = 0; i < n; i++) { |
|
var x = Math.log(data_x[i]); |
|
var y = Math.log(data_y[i]); |
|
sumX += x; |
|
sumY += y; |
|
var xx = x * x; |
|
sumXX += xx; |
|
var xy = x * y; |
|
sumXY += xy; |
|
} |
|
var sxx = sumXX - (sumX * sumX) / n; |
|
var sxy = sumXY - (sumX * sumY) / n; |
|
var xbar = sumX / n; |
|
var ybar = sumY / n; |
|
|
|
var b = sxy / sxx; |
|
var a = Math.pow(Math.exp(1.0), ybar - b * xbar); |
|
|
|
return { |
|
a: a, |
|
b: b |
|
}; |
|
|
|
}, |
|
|
|
polynomial: function(data_x, data_y, order) { |
|
|
|
var itemCount = data_x.length; |
|
|
|
if (itemCount < order + 1) { |
|
//return false; |
|
} |
|
|
|
var validItems = 0; |
|
|
|
var data = {}; |
|
var validItems = 0; |
|
|
|
var item; |
|
for(item = 0; item < itemCount; item++){ |
|
|
|
var x = data_x[item]; |
|
var y = data_y[item]; |
|
|
|
if (!isNaN(x) && !isNaN(y)){ |
|
|
|
if (typeof data[0] != "object") { |
|
data[0] = {}; |
|
} |
|
|
|
if (typeof data[1] != "object") { |
|
data[1] = {}; |
|
} |
|
|
|
data[0][validItems] = x; |
|
data[1][validItems] = y; |
|
|
|
validItems++; |
|
|
|
} |
|
|
|
} |
|
|
|
if (validItems < order + 1) { |
|
//return false; |
|
} |
|
|
|
var equations = order + 1; |
|
var coefficients = order + 2; |
|
|
|
var result = {}; |
|
var matrix = {}; |
|
|
|
var sumX = 0; |
|
var sumY = 0; |
|
|
|
for(item = 0; item < validItems; item++){ |
|
|
|
sumX += data[0][item]; |
|
sumY += data[1][item]; |
|
|
|
var eq; |
|
for(eq = 0; eq < equations; eq++){ |
|
|
|
var coe; |
|
for(coe = 0; coe < coefficients - 1; coe++){ |
|
|
|
if (typeof matrix[eq] != "object") { |
|
matrix[eq] = {}; |
|
} |
|
|
|
if (typeof matrix[eq][coe] == "undefined") { |
|
matrix[eq][coe] = 0; |
|
} |
|
|
|
matrix[eq][coe] += Math.pow(data[0][item], eq + coe); |
|
|
|
} |
|
|
|
if (typeof matrix[eq][coefficients - 1] == "undefined") { |
|
matrix[eq][coefficients - 1] = 0; |
|
} |
|
|
|
matrix[eq][coefficients - 1] += data[1][item] * Math.pow(data[0][item],eq); |
|
|
|
} |
|
|
|
} |
|
|
|
var subMatrix = regression.calculateSubMatrix(matrix); |
|
|
|
var eq; |
|
for (eq = 1; eq < equations; eq++) { |
|
|
|
matrix[eq][0] = 0; |
|
|
|
var coe; |
|
for (coe = 1; coe < coefficients; coe++) { |
|
matrix[eq][coe] = subMatrix[eq - 1][coe - 1]; |
|
} |
|
|
|
} |
|
|
|
for (eq = equations - 1; eq > -1; eq--) { |
|
|
|
var value = matrix[eq][coefficients - 1]; |
|
|
|
var coe; |
|
for (coe = eq; coe < coefficients -1; coe++) { |
|
value -= matrix[eq][coe] * (isNaN(result[coe]) ? 0 : result[coe]); |
|
} |
|
|
|
result[eq] = value / matrix[eq][eq]; |
|
|
|
} |
|
|
|
var meanY = sumY / validItems; |
|
var yObsSquare = 0; |
|
var yRegSquare = 0; |
|
|
|
for (item = 0; item < validItems; item++) { |
|
var yCalc = 0; |
|
|
|
var eq; |
|
for (eq = 0; eq < equations; eq++) { |
|
yCalc += result[eq] * Math.pow(data[0][item],eq); |
|
} |
|
|
|
yRegSquare += Math.pow(yCalc - meanY, 2); |
|
yObsSquare += Math.pow(data[1][item] - meanY, 2); |
|
|
|
} |
|
var rSquare = yRegSquare / yObsSquare; |
|
|
|
result['r2'] = rSquare; |
|
|
|
return result; |
|
|
|
}, |
|
|
|
calculateSubMatrix: function(matrix){ |
|
|
|
var equations = (typeof matrix == "object" ? Object.keys(matrix).length : 0); |
|
var coefficients = (typeof matrix[0] == "object" ? Object.keys(matrix[0]).length : 0); |
|
|
|
var result = {}; |
|
|
|
var eq; |
|
for (eq = 1; eq < equations; eq++) { |
|
|
|
var factor = matrix[0][0] / matrix[eq][0]; |
|
|
|
var coe; |
|
for (coe = 1; coe < coefficients; coe++) { |
|
|
|
if (typeof result[eq - 1] != "object") { |
|
result[eq - 1] = {}; |
|
} |
|
|
|
result[eq - 1][coe -1] = matrix[0][coe] - matrix[eq][coe] * factor; |
|
|
|
} |
|
|
|
} |
|
|
|
if (equations == 1) { |
|
return result; |
|
} |
|
|
|
// check for zero pivot element |
|
if (result[0][0] == 0) { |
|
|
|
var found = false; |
|
|
|
var i; |
|
for (i = 0; i < result.length; i ++) { |
|
|
|
if (result[i][0] != 0) { |
|
found = true; |
|
var temp = result[0]; |
|
var j; |
|
for (j = 0; j < result[i].length; j++) { |
|
result[0][j] = result[i][j]; |
|
} |
|
for (j = 0; j < temp.length; j++) { |
|
result[i][j] = temp[j]; |
|
} |
|
break; |
|
} |
|
|
|
} |
|
|
|
if (!found) { |
|
|
|
var i, j; |
|
|
|
var retorno = {}; |
|
|
|
for (i = 0; i < equations; i++) { |
|
for (j = 0; j < coefficients; j++) { |
|
if (typeof retorno[i] != "object") { |
|
retorno[i] = {}; |
|
} |
|
retorno[i][j] = 0; |
|
} |
|
} |
|
|
|
return retorno; |
|
|
|
} |
|
|
|
} |
|
|
|
var subMatrix = regression.calculateSubMatrix(result); |
|
|
|
for (eq = 1; eq < equations - 1; eq++) { |
|
result[eq][0] = 0; |
|
|
|
var coe; |
|
for (coe = 1; coe < coefficients - 1; coe++) { |
|
result[eq][coe] = subMatrix[eq - 1][coe - 1]; |
|
} |
|
|
|
} |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
Para usar:
regression.linear(x, y); |
|
retorno: { slope, intercept, r2, fn(x) } |
|
|
|
regression.power(x, y); |
|
retorno: { a, b } |
|
|
|
regression.polynomial(x, y, order); |
|
retorno: { 0, 1, 2, ..., r2 } |
Ainda tenho que limpar o código, comentar, etc, mas já dá pra vocês usarem.
Portei o código da biblioteca Jfree de Java.
Tags: estatística, linear regression, matemática, math, polynomial regression, power regression, regressão, regressão de potência, regressão linear, regressão polinomial, regression
This entry was posted
on terça-feira, setembro 11th, 2012 at 11:06 and is filed under Uncategorized.
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.