@progress/kendo-charts
Version:
Kendo UI platform-independent Charts library
84 lines (69 loc) • 2.52 kB
JavaScript
import { Matrix } from '../../common';
const MIN_ORDER = 1;
const MAX_ORDER = 6;
function calculatePolynomial(sourceValues, valueGetter, order) {
let k = Math.min(Math.max(order || MIN_ORDER, MIN_ORDER), MAX_ORDER) + 1;
let X = new Matrix();
let Y = new Matrix();
let count = 0;
let xMin = Number.MAX_VALUE;
let xMax = Number.MIN_VALUE;
let valueMapper = x => x;
let coefficients = [];
for (let i = 0; i < sourceValues.length; i++) {
const value = sourceValues[i];
let { xValue, yValue } = valueGetter(value);
if (isFinite(xValue) && xValue !== null && isFinite(yValue) && yValue !== null) {
xMin = Math.min(xValue, xMin);
xMax = Math.max(xValue, xMax);
count++;
// Set Y value in matrix
Y.set(i, 0, yValue);
// Set indicator column to 1 for valid values
X.set(i, 0, 1);
X.set(i, 1, xValue);
for (let pow = 2; pow <= k; pow++) {
X.set(i, pow, Math.pow(X.get(i, 1), pow));
}
} else {
// Set indicator column to 0 for missing values
X.set(i, 0, 0);
}
}
// Limit order to number of values.
X.width = Math.min(k, count);
if (count > 0) {
// Polynomial trendline equation:
// y = aN * x^N + ... + a2 * x^2 + a1 * x + a0
coefficients = linearRegression(X, Y);
valueMapper = x => coefficients.reduce((y, a, n) => y + a * Math.pow(x, n), 0);
}
return {
coefficients,
count,
valueMapper,
xMin,
xMax
};
}
function linearRegression(X, Y) {
const Xt = X.transpose();
const B = Xt.multiply(X).inverse().multiply(Xt).multiply(Y); // the last square estimate of the coefficients
const coefficients = [];
for (let i = 0; i < B.height; i++) {
coefficients.push(B.get(i, 0));
}
// y_intercept and regression coefficients ('slopes')
return coefficients;
// It's possible to calculate statistics for the regression based on
// the LINEST function implementation in kendo-spreadsheet-common/src/calc.js
//
// * The standard errors (of coefficients and y-intercept)
// * The coefficient of determination (R^2)
// * The standard error for the y estimate
// * The F statistic
// * The degrees of freedom
// * The regression sum of squares (SSR)
// * The residual sum of squares (SSE)
}
export default calculatePolynomial;