/**
* [决定系数(R²)](http://en.wikipedia.org/wiki/Coefficient_of_determination)
* 用于评估回归函数`f`对数据的拟合程度,计算预测值与实际值的平方差异和。
*
* @param {Array<Array<number>>} x 输入数据:二维数组结构,每项格式为[自变量, 因变量]
* @param {Function} func 回归函数(接受自变量值返回预测值)
* @returns {number} R²值(范围[0,1])
* @example
* var samples = [[0, 0], [1, 1]];
* var regressionLine = linearRegressionLine(linearRegression(samples));
* rSquared(samples, regressionLine); // = 1 表示完美拟合
*/
function rSquared(x, func) {
// 数据量不足时直接返回完美拟合
if (x.length < 2) {
return 1;
}
// 计算实际数据的因变量平均值(用于计算总平方和SST)
let sum = 0;
for (let i = 0; i < x.length; i++) {
sum += x[i][1];
}
const average = sum / x.length;
// 计算总平方和(SST):各数据点与均值的平方差异和
let sumOfSquares = 0;
for (let j = 0; j < x.length; j++) {
sumOfSquares += Math.pow(average - x[j][1], 2);
}
// 计算误差平方和(SSE):预测值与实际值的平方差异和
let err = 0;
for (let k = 0; k < x.length; k++) {
err += Math.pow(x[k][1] - func(x[k][0]), 2);
}
// 计算R²值:1 - (SSE/SST)
// 当误差增大时,其与总平方和的比率上升,导致R²值降低
return 1 - err / sumOfSquares;
}
export default rSquared;