time-to-botec/squiggle/node_modules/jstat/src/models.js
NunoSempere b6addc7f05 feat: add the node modules
Necessary in order to clearly see the squiggle hotwiring.
2022-12-03 12:44:49 +00:00

114 lines
3.4 KiB
JavaScript

jStat.models = (function(){
function sub_regress(exog) {
var var_count = exog[0].length;
var modelList = jStat.arange(var_count).map(function(endog_index) {
var exog_index =
jStat.arange(var_count).filter(function(i){return i!==endog_index});
return ols(jStat.col(exog, endog_index).map(function(x){ return x[0] }),
jStat.col(exog, exog_index))
});
return modelList;
}
// do OLS model regress
// exog have include const columns ,it will not generate it .In fact, exog is
// "design matrix" look at
//https://en.wikipedia.org/wiki/Design_matrix
function ols(endog, exog) {
var nobs = endog.length;
var df_model = exog[0].length - 1;
var df_resid = nobs-df_model - 1;
var coef = jStat.lstsq(exog, endog);
var predict =
jStat.multiply(exog, coef.map(function(x) { return [x] }))
.map(function(p) { return p[0] });
var resid = jStat.subtract(endog, predict);
var ybar = jStat.mean(endog);
// constant cause problem
// var SST = jStat.sum(endog.map(function(y) {
// return Math.pow(y-ybar,2);
// }));
var SSE = jStat.sum(predict.map(function(f) {
return Math.pow(f - ybar, 2);
}));
var SSR = jStat.sum(endog.map(function(y, i) {
return Math.pow(y - predict[i], 2);
}));
var SST = SSE + SSR;
var R2 = (SSE / SST);
return {
exog:exog,
endog:endog,
nobs:nobs,
df_model:df_model,
df_resid:df_resid,
coef:coef,
predict:predict,
resid:resid,
ybar:ybar,
SST:SST,
SSE:SSE,
SSR:SSR,
R2:R2
};
}
// H0: b_I=0
// H1: b_I!=0
function t_test(model) {
var subModelList = sub_regress(model.exog);
//var sigmaHat=jStat.stdev(model.resid);
var sigmaHat = Math.sqrt(model.SSR / (model.df_resid));
var seBetaHat = subModelList.map(function(mod) {
var SST = mod.SST;
var R2 = mod.R2;
return sigmaHat / Math.sqrt(SST * (1 - R2));
});
var tStatistic = model.coef.map(function(coef, i) {
return (coef - 0) / seBetaHat[i];
});
var pValue = tStatistic.map(function(t) {
var leftppf = jStat.studentt.cdf(t, model.df_resid);
return (leftppf > 0.5 ? 1 - leftppf : leftppf) * 2;
});
var c = jStat.studentt.inv(0.975, model.df_resid);
var interval95 = model.coef.map(function(coef, i) {
var d = c * seBetaHat[i];
return [coef - d, coef + d];
})
return {
se: seBetaHat,
t: tStatistic,
p: pValue,
sigmaHat: sigmaHat,
interval95: interval95
};
}
function F_test(model) {
var F_statistic =
(model.R2 / model.df_model) / ((1 - model.R2) / model.df_resid);
var fcdf = function(x, n1, n2) {
return jStat.beta.cdf(x / (n2 / n1 + x), n1 / 2, n2 / 2)
}
var pvalue = 1 - fcdf(F_statistic, model.df_model, model.df_resid);
return { F_statistic: F_statistic, pvalue: pvalue };
}
function ols_wrap(endog, exog) {
var model = ols(endog,exog);
var ttest = t_test(model);
var ftest = F_test(model);
// Provide the Wherry / Ezekiel / McNemar / Cohen Adjusted R^2
// Which matches the 'adjusted R^2' provided by R's lm package
var adjust_R2 =
1 - (1 - model.R2) * ((model.nobs - 1) / (model.df_resid));
model.t = ttest;
model.f = ftest;
model.adjust_R2 = adjust_R2;
return model;
}
return { ols: ols_wrap };
})();