vega-statistics
Advanced tools
Comparing version 1.3.1 to 1.4.0
@@ -62,19 +62,19 @@ (function (global, factory) { | ||
function numbers(array, f) { | ||
var numbers = [], | ||
n = array.length, | ||
i = -1, a; | ||
if (f == null) { | ||
while (++i < n) if (!isNaN(a = number(array[i]))) numbers.push(a); | ||
function* numbers(values, valueof) { | ||
if (valueof === undefined) { | ||
for (let value of values) { | ||
if (value != null && (value = +value) >= value) { | ||
yield value; | ||
} | ||
} | ||
} else { | ||
while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) numbers.push(a); | ||
let index = -1; | ||
for (let value of values) { | ||
if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) { | ||
yield value; | ||
} | ||
} | ||
} | ||
return numbers; | ||
} | ||
function number(x) { | ||
return x === null ? NaN : +x; | ||
} | ||
exports.random = Math.random; | ||
@@ -89,3 +89,3 @@ | ||
var values = numbers(array, f), | ||
var values = Float64Array.from(numbers(array, f)), | ||
n = values.length, | ||
@@ -109,3 +109,3 @@ m = samples, | ||
function quartiles(array, f) { | ||
var values = numbers(array, f); | ||
var values = Float64Array.from(numbers(array, f)); | ||
@@ -449,12 +449,474 @@ return [ | ||
// Ordinary Least Squares | ||
function ols(uX, uY, uXY, uX2) { | ||
const delta = uX2 - uX * uX, | ||
slope = Math.abs(delta) < 1e-24 ? 0 : (uXY - uX * uY) / delta, | ||
intercept = uY - slope * uX; | ||
return [intercept, slope]; | ||
} | ||
function points(data, x, y, sort) { | ||
data = data.filter(d => { | ||
let u = x(d), v = y(d); | ||
return u != null && (u = +u) >= u && v != null && (v = +v) >= v; | ||
}); | ||
if (sort) { | ||
data.sort((a, b) => x(a) - x(b)); | ||
} | ||
const X = new Float64Array(data.length), | ||
Y = new Float64Array(data.length); | ||
let i = 0; | ||
for (let d of data) { | ||
X[i] = x(d); | ||
Y[i] = y(d); | ||
++i; | ||
} | ||
return [X, Y]; | ||
} | ||
function visitPoints(data, x, y, callback) { | ||
let index = -1, i = -1, u, v; | ||
for (let d of data) { | ||
u = x(d, ++index, data); | ||
v = y(d, index, data); | ||
if (u != null && (u = +u) >= u && v != null && (v = +v) >= v) { | ||
callback(u, v, ++i); | ||
} | ||
} | ||
} | ||
// Adapted from d3-regression by Harry Stevens | ||
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE | ||
function rSquared(data, x, y, uY, predict) { | ||
let SSE = 0, SST = 0; | ||
visitPoints(data, x, y, (dx, dy) => { | ||
const sse = dy - predict(dx), | ||
sst = dy - uY; | ||
SSE += sse * sse; | ||
SST += sst * sst; | ||
}); | ||
return 1 - SSE / SST; | ||
} | ||
// Adapted from d3-regression by Harry Stevens | ||
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE | ||
function linear(data, x, y) { | ||
let X = 0, Y = 0, XY = 0, X2 = 0, n = 0; | ||
visitPoints(data, x, y, (dx, dy) => { | ||
X += dx; | ||
Y += dy; | ||
XY += dx * dy; | ||
X2 += dx * dx; | ||
++n; | ||
}); | ||
const coef = ols(X / n, Y / n, XY / n, X2 / n), | ||
predict = x => coef[0] + coef[1] * x; | ||
return { | ||
coef: coef, | ||
predict: predict, | ||
rSquared: rSquared(data, x, y, Y / n, predict) | ||
}; | ||
} | ||
// Adapted from d3-regression by Harry Stevens | ||
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE | ||
function log(data, x, y) { | ||
let X = 0, Y = 0, XY = 0, X2 = 0, n = 0; | ||
visitPoints(data, x, y, (dx, dy) => { | ||
dx = Math.log(dx); | ||
X += dx; | ||
Y += dy; | ||
XY += dx * dy; | ||
X2 += dx * dx; | ||
++n; | ||
}); | ||
const coef = ols(X / n, Y / n, XY / n, X2 / n), | ||
predict = x => coef[0] + coef[1] * Math.log(x); | ||
return { | ||
coef: coef, | ||
predict: predict, | ||
rSquared: rSquared(data, x, y, Y / n, predict) | ||
}; | ||
} | ||
function exp(data, x, y) { | ||
let Y = 0, YL = 0, XY = 0, XYL = 0, X2Y = 0, n = 0; | ||
visitPoints(data, x, y, (dx, dy) => { | ||
const ly = Math.log(dy), | ||
xy = dx * dy; | ||
Y += dy; | ||
XY += xy; | ||
X2Y += dx * xy; | ||
YL += dy * ly; | ||
XYL += xy * ly; | ||
++n; | ||
}); | ||
const coef = ols(XY / Y, YL / Y, XYL / Y, X2Y / Y), | ||
predict = x => coef[0] * Math.exp(coef[1] * x); | ||
coef[0] = Math.exp(coef[0]); | ||
return { | ||
coef: coef, | ||
predict: predict, | ||
rSquared: rSquared(data, x, y, Y / n, predict) | ||
}; | ||
} | ||
// Adapted from d3-regression by Harry Stevens | ||
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE | ||
function pow(data, x, y) { | ||
let X = 0, Y = 0, XY = 0, X2 = 0, YS = 0, n = 0; | ||
visitPoints(data, x, y, (dx, dy) => { | ||
const lx = Math.log(dx), | ||
ly = Math.log(dy); | ||
X += lx; | ||
Y += ly; | ||
XY += lx * ly; | ||
X2 += lx * lx; | ||
YS += dy; | ||
++n; | ||
}); | ||
const coef = ols(X / n, Y / n, XY / n, X2 / n), | ||
predict = x => coef[0] * Math.pow(x, coef[1]); | ||
coef[0] = Math.exp(coef[0]); | ||
return { | ||
coef: coef, | ||
predict: predict, | ||
rSquared: rSquared(data, x, y, YS / n, predict) | ||
}; | ||
} | ||
function quad(data, x, y) { | ||
let X = 0, Y = 0, X2 = 0, X3 = 0, X4 = 0, XY = 0, X2Y = 0, n = 0; | ||
visitPoints(data, x, y, (dx, dy) => { | ||
const x2 = dx * dx; | ||
X += dx; | ||
Y += dy; | ||
X2 += x2; | ||
X3 += x2 * dx; | ||
X4 += x2 * x2; | ||
XY += dx * dy; | ||
X2Y += x2 * dy; | ||
++n; | ||
}); | ||
Y = Y / n; | ||
XY = XY - X * Y; | ||
X2Y = X2Y - X2 * Y; | ||
const XX = X2 - X * X / n, | ||
XX2 = X3 - (X2 * X / n), | ||
X2X2 = X4 - (X2 * X2 / n), | ||
d = (XX * X2X2 - XX2 * XX2), | ||
a = (X2Y * XX - XY * XX2) / d, | ||
b = (XY * X2X2 - X2Y * XX2) / d, | ||
c = Y - (b * (X / n)) - (a * (X2 / n)), | ||
predict = x => a * x * x + b * x + c; | ||
return { | ||
coef: [c, b, a], | ||
predict: predict, | ||
rSquared: rSquared(data, x, y, Y, predict) | ||
}; | ||
} | ||
// Adapted from d3-regression by Harry Stevens | ||
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE | ||
// ... which was adapted from regression-js by Tom Alexander | ||
// Source: https://github.com/Tom-Alexander/regression-js/blob/master/src/regression.js#L246 | ||
// License: https://github.com/Tom-Alexander/regression-js/blob/master/LICENSE | ||
function poly(data, x, y, order) { | ||
// use more efficient methods for lower orders | ||
if (order === 1) return linear(data, x, y); | ||
if (order === 2) return quad(data, x, y); | ||
const [xv, yv] = points(data, x, y), | ||
n = xv.length, | ||
lhs = [], | ||
rhs = [], | ||
k = order + 1; | ||
let Y = 0, i, j, l, v, c; | ||
for (i = 0; i < n; ++i) { | ||
Y += yv[i]; | ||
} | ||
for (i = 0; i < k; ++i) { | ||
for (l = 0, v = 0; l < n; ++l) { | ||
v += Math.pow(xv[l], i) * yv[l]; | ||
} | ||
lhs.push(v); | ||
c = new Float64Array(k); | ||
for (j = 0; j < k; ++j) { | ||
for (l = 0, v = 0; l < n; ++l) { | ||
v += Math.pow(xv[l], i + j); | ||
} | ||
c[j] = v; | ||
} | ||
rhs.push(c); | ||
} | ||
rhs.push(lhs); | ||
const coef = gaussianElimination(rhs), | ||
predict = x => { | ||
let y = 0, i = 0, n = coef.length; | ||
for (; i < n; ++i) y += coef[i] * Math.pow(x, i); | ||
return y; | ||
}; | ||
return { | ||
coef: coef, | ||
predict: predict, | ||
rSquared: rSquared(data, x, y, Y / n, predict) | ||
}; | ||
} | ||
// Given an array for a two-dimensional matrix and the polynomial order, | ||
// solve A * x = b using Gaussian elimination. | ||
function gaussianElimination(matrix) { | ||
const n = matrix.length - 1, | ||
coef = []; | ||
let i, j, k, r, t; | ||
for (i = 0; i < n; ++i) { | ||
r = i; // max row | ||
for (j = i + 1; j < n; ++j) { | ||
if (Math.abs(matrix[i][j]) > Math.abs(matrix[i][r])) { | ||
r = j; | ||
} | ||
} | ||
for (k = i; k < n + 1; ++k) { | ||
t = matrix[k][i]; | ||
matrix[k][i] = matrix[k][r]; | ||
matrix[k][r] = t; | ||
} | ||
for (j = i + 1; j < n; ++j) { | ||
for (k = n; k >= i; k--) { | ||
matrix[k][j] -= (matrix[k][i] * matrix[i][j]) / matrix[i][i]; | ||
} | ||
} | ||
} | ||
for (j = n - 1; j >= 0; --j) { | ||
t = 0; | ||
for (k = j + 1; k < n; ++k) { | ||
t += matrix[k][j] * coef[k]; | ||
} | ||
coef[j] = (matrix[n][j] - t) / matrix[j][j]; | ||
} | ||
return coef; | ||
} | ||
const maxiters = 2, | ||
epsilon = 1e-12; | ||
// Adapted from science.js by Jason Davies | ||
// Source: https://github.com/jasondavies/science.js/blob/master/src/stats/loess.js | ||
// License: https://github.com/jasondavies/science.js/blob/master/LICENSE | ||
function loess(data, x, y, bandwidth) { | ||
const [xv, yv] = points(data, x, y, true), | ||
n = xv.length, | ||
bw = Math.max(2, ~~(bandwidth * n)), // # nearest neighbors | ||
yhat = new Float64Array(n), | ||
residuals = new Float64Array(n), | ||
robustWeights = new Float64Array(n).fill(1); | ||
for (let iter = -1; ++iter <= maxiters; ) { | ||
const interval = [0, bw - 1]; | ||
for (let i = 0; i < n; ++i) { | ||
const dx = xv[i], | ||
i0 = interval[0], | ||
i1 = interval[1], | ||
edge = (dx - xv[i0]) > (xv[i1] - dx) ? i0 : i1; | ||
let W = 0, X = 0, Y = 0, XY = 0, X2 = 0, | ||
denom = 1 / Math.abs(xv[edge] - dx || 1); // avoid singularity! | ||
for (let k = i0; k <= i1; ++k) { | ||
const xk = xv[k], | ||
yk = yv[k], | ||
w = tricube(Math.abs(dx - xk) * denom) * robustWeights[k], | ||
xkw = xk * w; | ||
W += w; | ||
X += xkw; | ||
Y += yk * w; | ||
XY += yk * xkw; | ||
X2 += xk * xkw; | ||
} | ||
// linear regression fit | ||
const [a, b] = ols(X / W, Y / W, XY / W, X2 / W); | ||
yhat[i] = a + b * dx; | ||
residuals[i] = Math.abs(yv[i] - yhat[i]); | ||
updateInterval(xv, i + 1, interval); | ||
} | ||
if (iter === maxiters) { | ||
break; | ||
} | ||
const medianResidual = d3Array.median(residuals); | ||
if (Math.abs(medianResidual) < epsilon) break; | ||
for (let i = 0, arg, w; i < n; ++i){ | ||
arg = residuals[i] / (6 * medianResidual); | ||
// default to epsilon (rather than zero) for large deviations | ||
// keeping weights tiny but non-zero prevents singularites | ||
robustWeights[i] = (arg >= 1) ? epsilon : ((w = 1 - arg * arg) * w); | ||
} | ||
} | ||
return output(xv, yhat); | ||
} | ||
// weighting kernel for local regression | ||
function tricube(x) { | ||
return (x = 1 - x * x * x) * x * x; | ||
} | ||
// advance sliding window interval of nearest neighbors | ||
function updateInterval(xv, i, interval) { | ||
let val = xv[i], | ||
left = interval[0], | ||
right = interval[1] + 1; | ||
if (right >= xv.length) return; | ||
// step right if distance to new right edge is <= distance to old left edge | ||
// step when distance is equal to ensure movement over duplicate x values | ||
while (i > left && (xv[right] - val) <= (val - xv[left])) { | ||
interval[0] = ++left; | ||
interval[1] = right; | ||
++right; | ||
} | ||
} | ||
// generate smoothed output points | ||
// average points with repeated x values | ||
function output(xv, yhat) { | ||
const n = xv.length, | ||
out = []; | ||
for (let i=0, cnt=0, prev=[], v; i<n; ++i) { | ||
v = xv[i]; | ||
if (prev[0] === v) { | ||
// average output values via online update | ||
prev[1] += (yhat[i] - prev[1]) / (++cnt); | ||
} else { | ||
// add new output point | ||
cnt = 0; | ||
prev = [v, yhat[i]]; | ||
out.push(prev); | ||
} | ||
} | ||
return out; | ||
} | ||
// subdivide up to accuracy of 0.1 degrees | ||
const MIN_RADIANS = 0.1 * Math.PI / 180; | ||
// Adaptively sample an interpolated function over a domain extent | ||
function sampleCurve(f, extent, minSteps, maxSteps) { | ||
minSteps = minSteps || 25; | ||
maxSteps = Math.max(minSteps, maxSteps || 200); | ||
const point = x => [x, f(x)], | ||
minX = extent[0], | ||
maxX = extent[1], | ||
span = maxX - minX, | ||
stop = span / maxSteps, | ||
prev = [point(minX)], | ||
next = []; | ||
if (minSteps === maxSteps) { | ||
// no adaptation, sample uniform grid directly and return | ||
for (let i = 1; i < maxSteps; ++i) { | ||
prev.push(point(minX + (i / minSteps) * span)); | ||
} | ||
prev.push(point(maxX)); | ||
return prev; | ||
} else { | ||
// sample minimum points on uniform grid | ||
// then move on to perform adaptive refinement | ||
next.push(point(maxX)); | ||
for (let i = minSteps; --i > 0;) { | ||
next.push(point(minX + (i / minSteps) * span)); | ||
} | ||
} | ||
let p0 = prev[0], | ||
p1 = next[next.length - 1]; | ||
while (p1) { | ||
const pm = point((p0[0] + p1[0]) / 2); | ||
if (pm[0] - p0[0] >= stop && angleDelta(p0, pm, p1) > MIN_RADIANS) { | ||
next.push(pm); | ||
} else { | ||
p0 = p1; | ||
prev.push(p1); | ||
next.pop(); | ||
} | ||
p1 = next[next.length - 1]; | ||
} | ||
return prev; | ||
} | ||
function angleDelta(p, q, r) { | ||
const a0 = Math.atan2(r[1] - p[1], r[0] - p[0]), | ||
a1 = Math.atan2(q[1] - p[1], q[0] - p[0]); | ||
return Math.abs(a0 - a1); | ||
} | ||
exports.bin = bin; | ||
exports.bootstrapCI = bootstrapCI; | ||
exports.quartiles = quartiles; | ||
exports.setRandom = setRandom; | ||
exports.randomLCG = lcg; | ||
exports.randomInteger = integer; | ||
exports.randomKDE = kde; | ||
exports.randomLCG = lcg; | ||
exports.randomMixture = mixture; | ||
exports.randomNormal = gaussian; | ||
exports.randomUniform = uniform; | ||
exports.regressionExp = exp; | ||
exports.regressionLinear = linear; | ||
exports.regressionLoess = loess; | ||
exports.regressionLog = log; | ||
exports.regressionPoly = poly; | ||
exports.regressionPow = pow; | ||
exports.regressionQuad = quad; | ||
exports.sampleCurve = sampleCurve; | ||
exports.setRandom = setRandom; | ||
@@ -461,0 +923,0 @@ Object.defineProperty(exports, '__esModule', { value: true }); |
@@ -1,1 +0,1 @@ | ||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("d3-array")):"function"==typeof define&&define.amd?define(["exports","d3-array"],t):t((n=n||self).vega={},n.d3)}(this,function(n,t){"use strict";function r(n,t){var r,a=[],o=n.length,u=-1;if(null==t)for(;++u<o;)isNaN(r=e(n[u]))||a.push(r);else for(;++u<o;)isNaN(r=e(t(n[u],u,n)))||a.push(r);return a}function e(n){return null===n?NaN:+n}function a(n,e){var a=r(n,e);return[t.quantile(a.sort(t.ascending),.25),t.quantile(a,.5),t.quantile(a,.75)]}function o(t,r){var e,a,o=NaN,u={mean:function(n){return arguments.length?(e=n||0,o=NaN,u):e},stdev:function(n){return arguments.length?(a=null==n?1:n,o=NaN,u):a},sample:function(){var t,r,u=0,i=0;if(o==o)return u=o,o=NaN,u;do{t=(u=2*n.random()-1)*u+(i=2*n.random()-1)*i}while(0===t||t>1);return r=Math.sqrt(-2*Math.log(t)/t),o=e+i*r*a,e+u*r*a},pdf:function(n){var t=Math.exp(Math.pow(n-e,2)/(-2*Math.pow(a,2)));return 1/(a*Math.sqrt(2*Math.PI))*t},cdf:function(n){var t,r=(n-e)/a,o=Math.abs(r);if(o>37)t=0;else{var u=Math.exp(-o*o/2);o<7.07106781186547?(t=u*((((((.0352624965998911*o+.700383064443688)*o+6.37396220353165)*o+33.912866078383)*o+112.079291497871)*o+221.213596169931)*o+220.206867912376),t/=((((((.0883883476483184*o+1.75566716318264)*o+16.064177579207)*o+86.7807322029461)*o+296.564248779674)*o+637.333633378831)*o+793.826512519948)*o+440.413735824752):t=u/(o+1/(o+2/(o+3/(o+4/(o+.65)))))/2.506628274631}return r>0?1-t:t},icdf:function(n){if(n<=0||n>=1)return NaN;var t=2*n-1,r=8*(Math.PI-3)/(3*Math.PI*(4-Math.PI)),o=2/(Math.PI*r)+Math.log(1-Math.pow(t,2))/2,u=Math.log(1-t*t)/r,i=(t>0?1:-1)*Math.sqrt(Math.sqrt(o*o-u)-o);return e+a*Math.SQRT2*i}};return u.mean(t).stdev(r)}n.random=Math.random,n.bin=function(n){var t,r,e,a,o,u,i,f,c=n.maxbins||20,d=n.base||10,h=Math.log(d),l=n.divide||[5,2],s=n.extent[0],p=n.extent[1],M=p-s||Math.abs(s)||1;if(n.step)t=n.step;else if(n.steps){for(o=M/c,u=0,i=n.steps.length;u<i&&n.steps[u]<o;++u);t=n.steps[Math.max(0,u-1)]}else{for(r=Math.ceil(Math.log(c)/h),e=n.minstep||0,t=Math.max(e,Math.pow(d,Math.round(Math.log(M)/h)-r));Math.ceil(M/t)>c;)t*=d;for(u=0,i=l.length;u<i;++u)(o=t/l[u])>=e&&M/o<=c&&(t=o)}return a=(o=Math.log(t))>=0?0:1+~~(-o/h),f=Math.pow(d,-a-1),(n.nice||void 0===n.nice)&&(s=s<(o=Math.floor(s/t+f)*t)?o-t:o,p=Math.ceil(p/t)*t),{start:s,stop:p===s?s+t:p,step:t}},n.bootstrapCI=function(e,a,o,u){if(!e.length)return[void 0,void 0];var i,f,c,d,h=r(e,u),l=h.length,s=a;for(c=0,d=Array(s);c<s;++c){for(i=0,f=0;f<l;++f)i+=h[~~(n.random()*l)];d[c]=i/l}return[t.quantile(d.sort(t.ascending),o/2),t.quantile(d,1-o/2)]},n.quartiles=a,n.setRandom=function(t){n.random=t},n.randomLCG=function(n){return function(){return(n=(1103515245*n+12345)%2147483647)/2147483647}},n.randomInteger=function(t,r){null==r&&(r=t,t=0);var e,a,o,u={};return u.min=function(n){return arguments.length?(o=a-(e=n||0),u):e},u.max=function(n){return arguments.length?(o=(a=n||0)-e,u):a},u.sample=function(){return e+Math.floor(o*n.random())},u.pdf=function(n){return n===Math.floor(n)&&n>=e&&n<a?1/o:0},u.cdf=function(n){var t=Math.floor(n);return t<e?0:t>=a?1:(t-e+1)/o},u.icdf=function(n){return n>=0&&n<=1?e-1+Math.floor(n*o):NaN},u.min(t).max(r)},n.randomKDE=function(r,e){var u=o(),i={},f=0;return i.data=function(n){return arguments.length?(r=n,f=n?n.length:0,i.bandwidth(e)):r},i.bandwidth=function(n){return arguments.length?(!(e=n)&&r&&(u=(o=r).length,f=a(o),c=(f[2]-f[0])/1.34,e=1.06*Math.min(Math.sqrt(t.variance(o)),c)*Math.pow(u,-.2)),i):e;var o,u,f,c},i.sample=function(){return r[~~(n.random()*f)]+e*u.sample()},i.pdf=function(n){for(var t=0,a=0;a<f;++a)t+=u.pdf((n-r[a])/e);return t/e/f},i.cdf=function(n){for(var t=0,a=0;a<f;++a)t+=u.cdf((n-r[a])/e);return t/f},i.icdf=function(){throw Error("KDE icdf not supported.")},i.data(r)},n.randomMixture=function(t,r){var e,a={},o=0;return a.weights=function(n){return arguments.length?(e=function(n){var t,r=[],e=0;for(t=0;t<o;++t)e+=r[t]=null==n[t]?1:+n[t];for(t=0;t<o;++t)r[t]/=e;return r}(r=n||[]),a):r},a.distributions=function(n){return arguments.length?(n?(o=n.length,t=n):(o=0,t=[]),a.weights(r)):t},a.sample=function(){for(var r=n.random(),a=t[o-1],u=e[0],i=0;i<o-1;u+=e[++i])if(r<u){a=t[i];break}return a.sample()},a.pdf=function(n){for(var r=0,a=0;a<o;++a)r+=e[a]*t[a].pdf(n);return r},a.cdf=function(n){for(var r=0,a=0;a<o;++a)r+=e[a]*t[a].cdf(n);return r},a.icdf=function(){throw Error("Mixture icdf not supported.")},a.distributions(t).weights(r)},n.randomNormal=o,n.randomUniform=function(t,r){null==r&&(r=null==t?1:t,t=0);var e,a,o,u={};return u.min=function(n){return arguments.length?(o=a-(e=n||0),u):e},u.max=function(n){return arguments.length?(o=(a=n||0)-e,u):a},u.sample=function(){return e+o*n.random()},u.pdf=function(n){return n>=e&&n<=a?1/o:0},u.cdf=function(n){return n<e?0:n>a?1:(n-e)/o},u.icdf=function(n){return n>=0&&n<=1?e+n*o:NaN},u.min(t).max(r)},Object.defineProperty(n,"__esModule",{value:!0})}); | ||
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("d3-array")):"function"==typeof define&&define.amd?define(["exports","d3-array"],n):n((t=t||self).vega={},t.d3)}(this,function(t,n){"use strict";function*r(t,n){if(void 0===n)for(let n of t)null!=n&&(n=+n)>=n&&(yield n);else{let r=-1;for(let e of t)null!=(e=n(e,++r,t))&&(e=+e)>=e&&(yield e)}}function e(t,e){var o=Float64Array.from(r(t,e));return[n.quantile(o.sort(n.ascending),.25),n.quantile(o,.5),n.quantile(o,.75)]}function o(n,r){var e,o,a=NaN,u={mean:function(t){return arguments.length?(e=t||0,a=NaN,u):e},stdev:function(t){return arguments.length?(o=null==t?1:t,a=NaN,u):o},sample:function(){var n,r,u=0,f=0;if(a==a)return u=a,a=NaN,u;do{n=(u=2*t.random()-1)*u+(f=2*t.random()-1)*f}while(0===n||n>1);return r=Math.sqrt(-2*Math.log(n)/n),a=e+f*r*o,e+u*r*o},pdf:function(t){var n=Math.exp(Math.pow(t-e,2)/(-2*Math.pow(o,2)));return 1/(o*Math.sqrt(2*Math.PI))*n},cdf:function(t){var n,r=(t-e)/o,a=Math.abs(r);if(a>37)n=0;else{var u=Math.exp(-a*a/2);a<7.07106781186547?(n=u*((((((.0352624965998911*a+.700383064443688)*a+6.37396220353165)*a+33.912866078383)*a+112.079291497871)*a+221.213596169931)*a+220.206867912376),n/=((((((.0883883476483184*a+1.75566716318264)*a+16.064177579207)*a+86.7807322029461)*a+296.564248779674)*a+637.333633378831)*a+793.826512519948)*a+440.413735824752):n=u/(a+1/(a+2/(a+3/(a+4/(a+.65)))))/2.506628274631}return r>0?1-n:n},icdf:function(t){if(t<=0||t>=1)return NaN;var n=2*t-1,r=8*(Math.PI-3)/(3*Math.PI*(4-Math.PI)),a=2/(Math.PI*r)+Math.log(1-Math.pow(n,2))/2,u=Math.log(1-n*n)/r,f=(n>0?1:-1)*Math.sqrt(Math.sqrt(a*a-u)-a);return e+o*Math.SQRT2*f}};return u.mean(n).stdev(r)}function a(t,n,r,e){const o=e-t*t,a=Math.abs(o)<1e-24?0:(r-t*n)/o;return[n-a*t,a]}function u(t,n,r,e){t=t.filter(t=>{let e=n(t),o=r(t);return null!=e&&(e=+e)>=e&&null!=o&&(o=+o)>=o}),e&&t.sort((t,r)=>n(t)-n(r));const o=new Float64Array(t.length),a=new Float64Array(t.length);let u=0;for(let e of t)o[u]=n(e),a[u]=r(e),++u;return[o,a]}function f(t,n,r,e){let o,a,u=-1,f=-1;for(let i of t)o=n(i,++u,t),a=r(i,u,t),null!=o&&(o=+o)>=o&&null!=a&&(a=+a)>=a&&e(o,a,++f)}function i(t,n,r,e,o){let a=0,u=0;return f(t,n,r,(t,n)=>{const r=n-o(t),f=n-e;a+=r*r,u+=f*f}),1-a/u}function l(t,n,r){let e=0,o=0,u=0,l=0,c=0;f(t,n,r,(t,n)=>{e+=t,o+=n,u+=t*n,l+=t*t,++c});const s=a(e/c,o/c,u/c,l/c),h=t=>s[0]+s[1]*t;return{coef:s,predict:h,rSquared:i(t,n,r,o/c,h)}}function c(t,n,r){let e=0,o=0,a=0,u=0,l=0,c=0,s=0,h=0;f(t,n,r,(t,n)=>{const r=t*t;e+=t,o+=n,a+=r,u+=r*t,l+=r*r,c+=t*n,s+=r*n,++h});const d=a-e*e/h,p=u-a*e/h,M=l-a*a/h,g=d*M-p*p,m=((s-=a*(o/=h))*d-(c-=e*o)*p)/g,v=(c*M-s*p)/g,w=o-v*(e/h)-m*(a/h),b=t=>m*t*t+v*t+w;return{coef:[w,v,m],predict:b,rSquared:i(t,n,r,o,b)}}t.random=Math.random;const s=2,h=1e-12;function d(t){return(t=1-t*t*t)*t*t}function p(t,n,r){let e=t[n],o=r[0],a=r[1]+1;if(!(a>=t.length))for(;n>o&&t[a]-e<=e-t[o];)r[0]=++o,r[1]=a,++a}const M=.1*Math.PI/180;function g(t,n,r){const e=Math.atan2(r[1]-t[1],r[0]-t[0]),o=Math.atan2(n[1]-t[1],n[0]-t[0]);return Math.abs(e-o)}t.bin=function(t){var n,r,e,o,a,u,f,i,l=t.maxbins||20,c=t.base||10,s=Math.log(c),h=t.divide||[5,2],d=t.extent[0],p=t.extent[1],M=p-d||Math.abs(d)||1;if(t.step)n=t.step;else if(t.steps){for(a=M/l,u=0,f=t.steps.length;u<f&&t.steps[u]<a;++u);n=t.steps[Math.max(0,u-1)]}else{for(r=Math.ceil(Math.log(l)/s),e=t.minstep||0,n=Math.max(e,Math.pow(c,Math.round(Math.log(M)/s)-r));Math.ceil(M/n)>l;)n*=c;for(u=0,f=h.length;u<f;++u)(a=n/h[u])>=e&&M/a<=l&&(n=a)}return o=(a=Math.log(n))>=0?0:1+~~(-a/s),i=Math.pow(c,-o-1),(t.nice||void 0===t.nice)&&(d=d<(a=Math.floor(d/n+i)*n)?a-n:a,p=Math.ceil(p/n)*n),{start:d,stop:p===d?d+n:p,step:n}},t.bootstrapCI=function(e,o,a,u){if(!e.length)return[void 0,void 0];var f,i,l,c,s=Float64Array.from(r(e,u)),h=s.length,d=o;for(l=0,c=Array(d);l<d;++l){for(f=0,i=0;i<h;++i)f+=s[~~(t.random()*h)];c[l]=f/h}return[n.quantile(c.sort(n.ascending),a/2),n.quantile(c,1-a/2)]},t.quartiles=e,t.randomInteger=function(n,r){null==r&&(r=n,n=0);var e,o,a,u={};return u.min=function(t){return arguments.length?(a=o-(e=t||0),u):e},u.max=function(t){return arguments.length?(a=(o=t||0)-e,u):o},u.sample=function(){return e+Math.floor(a*t.random())},u.pdf=function(t){return t===Math.floor(t)&&t>=e&&t<o?1/a:0},u.cdf=function(t){var n=Math.floor(t);return n<e?0:n>=o?1:(n-e+1)/a},u.icdf=function(t){return t>=0&&t<=1?e-1+Math.floor(t*a):NaN},u.min(n).max(r)},t.randomKDE=function(r,a){var u=o(),f={},i=0;return f.data=function(t){return arguments.length?(r=t,i=t?t.length:0,f.bandwidth(a)):r},f.bandwidth=function(t){return arguments.length?(!(a=t)&&r&&(u=(o=r).length,i=e(o),l=(i[2]-i[0])/1.34,a=1.06*Math.min(Math.sqrt(n.variance(o)),l)*Math.pow(u,-.2)),f):a;var o,u,i,l},f.sample=function(){return r[~~(t.random()*i)]+a*u.sample()},f.pdf=function(t){for(var n=0,e=0;e<i;++e)n+=u.pdf((t-r[e])/a);return n/a/i},f.cdf=function(t){for(var n=0,e=0;e<i;++e)n+=u.cdf((t-r[e])/a);return n/i},f.icdf=function(){throw Error("KDE icdf not supported.")},f.data(r)},t.randomLCG=function(t){return function(){return(t=(1103515245*t+12345)%2147483647)/2147483647}},t.randomMixture=function(n,r){var e,o={},a=0;return o.weights=function(t){return arguments.length?(e=function(t){var n,r=[],e=0;for(n=0;n<a;++n)e+=r[n]=null==t[n]?1:+t[n];for(n=0;n<a;++n)r[n]/=e;return r}(r=t||[]),o):r},o.distributions=function(t){return arguments.length?(t?(a=t.length,n=t):(a=0,n=[]),o.weights(r)):n},o.sample=function(){for(var r=t.random(),o=n[a-1],u=e[0],f=0;f<a-1;u+=e[++f])if(r<u){o=n[f];break}return o.sample()},o.pdf=function(t){for(var r=0,o=0;o<a;++o)r+=e[o]*n[o].pdf(t);return r},o.cdf=function(t){for(var r=0,o=0;o<a;++o)r+=e[o]*n[o].cdf(t);return r},o.icdf=function(){throw Error("Mixture icdf not supported.")},o.distributions(n).weights(r)},t.randomNormal=o,t.randomUniform=function(n,r){null==r&&(r=null==n?1:n,n=0);var e,o,a,u={};return u.min=function(t){return arguments.length?(a=o-(e=t||0),u):e},u.max=function(t){return arguments.length?(a=(o=t||0)-e,u):o},u.sample=function(){return e+a*t.random()},u.pdf=function(t){return t>=e&&t<=o?1/a:0},u.cdf=function(t){return t<e?0:t>o?1:(t-e)/a},u.icdf=function(t){return t>=0&&t<=1?e+t*a:NaN},u.min(n).max(r)},t.regressionExp=function(t,n,r){let e=0,o=0,u=0,l=0,c=0,s=0;f(t,n,r,(t,n)=>{const r=Math.log(n),a=t*n;e+=n,u+=a,c+=t*a,o+=n*r,l+=a*r,++s});const h=a(u/e,o/e,l/e,c/e),d=t=>h[0]*Math.exp(h[1]*t);return h[0]=Math.exp(h[0]),{coef:h,predict:d,rSquared:i(t,n,r,e/s,d)}},t.regressionLinear=l,t.regressionLoess=function(t,r,e,o){const[f,i]=u(t,r,e,!0),l=f.length,c=Math.max(2,~~(o*l)),M=new Float64Array(l),g=new Float64Array(l),m=new Float64Array(l).fill(1);for(let t=-1;++t<=s;){const r=[0,c-1];for(let t=0;t<l;++t){const n=f[t],e=r[0],o=r[1],u=n-f[e]>f[o]-n?e:o;let l=0,c=0,s=0,h=0,v=0,w=1/Math.abs(f[u]-n||1);for(let t=e;t<=o;++t){const r=f[t],e=i[t],o=d(Math.abs(n-r)*w)*m[t],a=r*o;l+=o,c+=a,s+=e*o,h+=e*a,v+=r*a}const[b,x]=a(c/l,s/l,h/l,v/l);M[t]=b+x*n,g[t]=Math.abs(i[t]-M[t]),p(f,t+1,r)}if(t===s)break;const e=n.median(g);if(Math.abs(e)<h)break;for(let t,n,r=0;r<l;++r)t=g[r]/(6*e),m[r]=t>=1?h:(n=1-t*t)*n}return function(t,n){const r=t.length,e=[];for(let o,a=0,u=0,f=[];a<r;++a)o=t[a],f[0]===o?f[1]+=(n[a]-f[1])/++u:(u=0,f=[o,n[a]],e.push(f));return e}(f,M)},t.regressionLog=function(t,n,r){let e=0,o=0,u=0,l=0,c=0;f(t,n,r,(t,n)=>{t=Math.log(t),e+=t,o+=n,u+=t*n,l+=t*t,++c});const s=a(e/c,o/c,u/c,l/c),h=t=>s[0]+s[1]*Math.log(t);return{coef:s,predict:h,rSquared:i(t,n,r,o/c,h)}},t.regressionPoly=function(t,n,r,e){if(1===e)return l(t,n,r);if(2===e)return c(t,n,r);const[o,a]=u(t,n,r),f=o.length,s=[],h=[],d=e+1;let p,M,g,m,v,w=0;for(p=0;p<f;++p)w+=a[p];for(p=0;p<d;++p){for(g=0,m=0;g<f;++g)m+=Math.pow(o[g],p)*a[g];for(s.push(m),v=new Float64Array(d),M=0;M<d;++M){for(g=0,m=0;g<f;++g)m+=Math.pow(o[g],p+M);v[M]=m}h.push(v)}h.push(s);const b=function(t){const n=t.length-1,r=[];let e,o,a,u,f;for(e=0;e<n;++e){for(u=e,o=e+1;o<n;++o)Math.abs(t[e][o])>Math.abs(t[e][u])&&(u=o);for(a=e;a<n+1;++a)f=t[a][e],t[a][e]=t[a][u],t[a][u]=f;for(o=e+1;o<n;++o)for(a=n;a>=e;a--)t[a][o]-=t[a][e]*t[e][o]/t[e][e]}for(o=n-1;o>=0;--o){for(f=0,a=o+1;a<n;++a)f+=t[a][o]*r[a];r[o]=(t[n][o]-f)/t[o][o]}return r}(h),x=t=>{let n=0,r=0,e=b.length;for(;r<e;++r)n+=b[r]*Math.pow(t,r);return n};return{coef:b,predict:x,rSquared:i(t,n,r,w/f,x)}},t.regressionPow=function(t,n,r){let e=0,o=0,u=0,l=0,c=0,s=0;f(t,n,r,(t,n)=>{const r=Math.log(t),a=Math.log(n);e+=r,o+=a,u+=r*a,l+=r*r,c+=n,++s});const h=a(e/s,o/s,u/s,l/s),d=t=>h[0]*Math.pow(t,h[1]);return h[0]=Math.exp(h[0]),{coef:h,predict:d,rSquared:i(t,n,r,c/s,d)}},t.regressionQuad=c,t.sampleCurve=function(t,n,r,e){r=r||25,e=Math.max(r,e||200);const o=n=>[n,t(n)],a=n[0],u=n[1],f=u-a,i=f/e,l=[o(a)],c=[];if(r===e){for(let t=1;t<e;++t)l.push(o(a+t/r*f));return l.push(o(u)),l}c.push(o(u));for(let t=r;--t>0;)c.push(o(a+t/r*f));let s=l[0],h=c[c.length-1];for(;h;){const t=o((s[0]+h[0])/2);t[0]-s[0]>=i&&g(s,t,h)>M?c.push(t):(s=h,l.push(h),c.pop()),h=c[c.length-1]}return l},t.setRandom=function(n){t.random=n},Object.defineProperty(t,"__esModule",{value:!0})}); |
@@ -11,1 +11,9 @@ export {default as bin} from './src/bin'; | ||
export {default as randomUniform} from './src/uniform'; | ||
export {default as regressionLinear} from './src/regression/linear'; | ||
export {default as regressionLog} from './src/regression/log'; | ||
export {default as regressionExp} from './src/regression/exp'; | ||
export {default as regressionPow} from './src/regression/pow'; | ||
export {default as regressionQuad} from './src/regression/quad'; | ||
export {default as regressionPoly} from './src/regression/poly'; | ||
export {default as regressionLoess} from './src/regression/loess'; | ||
export {default as sampleCurve} from './src/sampleCurve'; |
{ | ||
"name": "vega-statistics", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "Statistical routines and probability distributions.", | ||
@@ -29,3 +29,3 @@ "keywords": [ | ||
}, | ||
"gitHead": "8e012f8b7b5a520bb60a2b5ebb0764991048e16a" | ||
"gitHead": "d2576ca617d8165211ffe6c23582b9dc1b88db7d" | ||
} |
@@ -9,2 +9,3 @@ # vega-statistics | ||
- [Distributions](#distributions) | ||
- [Regression](#regression) | ||
- [Statistics](#statistics) | ||
@@ -83,2 +84,80 @@ | ||
### Regression | ||
Two-dimensional regression methods to predict one variable given another. | ||
<a name="regressionLinear" href="#regressionLinear">#</a> | ||
vega.<b>regressionLinear</b>(<i>data</i>, <i>x</i>, <i>y</i>) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/regression/linear.js "Source") | ||
Fit a linear regression model with functional form _y = a + b * x_ for the input *data* array and corresponding *x* and *y* accessor functions. Returns an object for the fit model parameters with the following properties: | ||
- _coef_: An array of fitted coefficients of the form _[a, b]_. | ||
- _predict_: A function that returns a regression prediction for an input _x_ value. | ||
- _rSquared_: The R<sup>2</sup> [coefficient of determination](https://en.wikipedia.org/wiki/Coefficient_of_determination), indicating the amount of total variance of _y_ accounted for by the model. | ||
<a name="regressionLog" href="#regressionLog">#</a> | ||
vega.<b>regressionLog</b>(<i>data</i>, <i>x</i>, <i>y</i>) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/regression/log.js "Source") | ||
Fit a logarithmic regression model with functional form _y = a + b * log(x)_ for the input input *data* array and corresponding *x* and *y* accessor functions. | ||
Returns an object for the fit model parameters with the following properties: | ||
- _coef_: An array of fitted coefficients of the form _[a, b]_. | ||
- _predict_: A function that returns a regression prediction for an input _x_ value. | ||
- _rSquared_: The R<sup>2</sup> [coefficient of determination](https://en.wikipedia.org/wiki/Coefficient_of_determination), indicating the amount of total variance of _y_ accounted for by the model. | ||
<a name="regressionExp" href="#regressionExp">#</a> | ||
vega.<b>regressionExp</b>(<i>data</i>, <i>x</i>, <i>y</i>) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/regression/exp.js "Source") | ||
Fit an exponential regression model with functional form _y = a + e<sup>b * x</sup>_ for the input *data* array and corresponding *x* and *y* accessor functions. Returns an object for the fit model parameters with the following properties: | ||
- _coef_: An array of fitted coefficients of the form _[a, b]_. | ||
- _predict_: A function that returns a regression prediction for an input _x_ value. | ||
- _rSquared_: The R<sup>2</sup> [coefficient of determination](https://en.wikipedia.org/wiki/Coefficient_of_determination), indicating the amount of total variance of _y_ accounted for by the model. | ||
<a name="regressionPow" href="#regressionPow">#</a> | ||
vega.<b>regressionPow</b>(<i>data</i>, <i>x</i>, <i>y</i>) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/regression/pow.js "Source") | ||
Fit a power law regression model with functional form _y = a * x<sup>b</sup>_ for the input *data* array and corresponding *x* and *y* accessor functions. Returns an object for the fit model parameters with the following properties: | ||
- _coef_: An array of fitted coefficients of the form _[a, b]_. | ||
- _predict_: A function that returns a regression prediction for an input _x_ value. | ||
- _rSquared_: The R<sup>2</sup> [coefficient of determination](https://en.wikipedia.org/wiki/Coefficient_of_determination), indicating the amount of total variance of _y_ accounted for by the model. | ||
<a name="regressionQuad" href="#regressionQuad">#</a> | ||
vega.<b>regressionLinear</b>(<i>data</i>, <i>x</i>, <i>y</i>) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/regression/quad.js "Source") | ||
Fit a quadratic regression model with functional form _y = a + b * x + c * x<sup>2</sup>_ for the input *data* array and corresponding *x* and *y* accessor functions. Returns an object for the fit model parameters with the following properties: | ||
- _coef_: An array of fitted coefficients of the form _[a, b, c]_, | ||
- _predict_: A function that returns a regression prediction for an input _x_ value. | ||
- _rSquared_: The R<sup>2</sup> [coefficient of determination](https://en.wikipedia.org/wiki/Coefficient_of_determination), indicating the amount of total variance of _y_ accounted for by the model. | ||
<a name="regressionPoly" href="#regressionPoly">#</a> | ||
vega.<b>regressionPoly</b>(<i>data</i>, <i>x</i>, <i>y</i>, <i>order</i>) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/regression/poly.js "Source") | ||
Fit a polynomial regression model of specified _order_ with functional form _y = a + b * x + ... + k * x<sup>order</sup>_ for the input *data* array and corresponding *x* and *y* accessor functions. Returns an object for the fit model parameters with the following properties: | ||
- _coef_: An _(order + 1)_-length array of polynomial coefficients of the form _[a, b, c, d, ...]_. | ||
- _predict_: A function that returns a regression prediction for an input _x_ value. | ||
- _rSquared_: The R<sup>2</sup> [coefficient of determination](https://en.wikipedia.org/wiki/Coefficient_of_determination), indicating the amount of total variance of _y_ accounted for by the model. | ||
<a name="regressionLoess" href="#regressionLoess">#</a> | ||
vega.<b>regressionLoess/b>(<i>data</i>, <i>x</i>, <i>y</i>, <i>bandwidth</i>) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/regression/loess.js "Source") | ||
Fit a smoothed, non-parametric trend line the input *data* array and corresponding *x* and *y* accessor functions using _loess_ (locally-estimated scatterplot smoothing). Loess performs a sequence of local weighted regressions over a sliding window of nearest-neighbor points. The _bandwidth_ argument determines the size of the sliding window, expressed as a [0, 1] fraction of the total number of data points included. | ||
<a name="sampleCurve" href="#sampleCurve">#</a> | ||
vega.<b>sampleCurve</b>(<i>f</i>, <i>extent</i>[, <i>minSteps</i>, <i>maxSteps</i>]) | ||
[<>](https://github.com/vega/vega/blob/master/packages/vega-statistics/src/sampleCurve.js "Source") | ||
Generate sample points from an interpolation function _f_ for the provided domain _extent_ and return an array of _[x, y]_ points. Performs adaptive subdivision to dynamically sample more points in regions of higher curvature. Subdivision stops when the difference in angles between the current samples and a proposed subdivision falls below one-quarter of a degree. The optional _minSteps_ argument (default 25), determines the minimal number of initial, uniformly-spaced sample points to draw. The optional _maxSteps_ argument (default 200), indicates the maximum resolution at which adaptive sampling will stop, defined relative to a uniform grid of size _maxSteps_. If _minSteps_ and _maxSteps_ are identical, no adaptive sampling will be performed and only the initial, uniformly-spaced samples will be returned. | ||
### Statistics | ||
@@ -85,0 +164,0 @@ |
@@ -8,3 +8,3 @@ import numbers from './numbers'; | ||
var values = numbers(array, f), | ||
var values = Float64Array.from(numbers(array, f)), | ||
n = values.length, | ||
@@ -11,0 +11,0 @@ m = samples, |
@@ -1,16 +0,16 @@ | ||
export default function(array, f) { | ||
var numbers = [], | ||
n = array.length, | ||
i = -1, a; | ||
if (f == null) { | ||
while (++i < n) if (!isNaN(a = number(array[i]))) numbers.push(a); | ||
export default function*(values, valueof) { | ||
if (valueof === undefined) { | ||
for (let value of values) { | ||
if (value != null && (value = +value) >= value) { | ||
yield value; | ||
} | ||
} | ||
} else { | ||
while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) numbers.push(a); | ||
let index = -1; | ||
for (let value of values) { | ||
if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) { | ||
yield value; | ||
} | ||
} | ||
} | ||
return numbers; | ||
} | ||
function number(x) { | ||
return x === null ? NaN : +x; | ||
} |
@@ -5,3 +5,3 @@ import numbers from './numbers'; | ||
export default function(array, f) { | ||
var values = numbers(array, f); | ||
var values = Float64Array.from(numbers(array, f)); | ||
@@ -8,0 +8,0 @@ return [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
74809
28
1582
199