d3-regression.cjs.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. // https://github.com/HarryStevens/d3-regression#readme Version 1.3.10. Copyright 2022 Harry Stevens.
  2. 'use strict';
  3. Object.defineProperty(exports, '__esModule', { value: true });
  4. function _slicedToArray(arr, i) {
  5. return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
  6. }
  7. function _arrayWithHoles(arr) {
  8. if (Array.isArray(arr)) return arr;
  9. }
  10. function _iterableToArrayLimit(arr, i) {
  11. var _arr = [];
  12. var _n = true;
  13. var _d = false;
  14. var _e = undefined;
  15. try {
  16. for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
  17. _arr.push(_s.value);
  18. if (i && _arr.length === i) break;
  19. }
  20. } catch (err) {
  21. _d = true;
  22. _e = err;
  23. } finally {
  24. try {
  25. if (!_n && _i["return"] != null) _i["return"]();
  26. } finally {
  27. if (_d) throw _e;
  28. }
  29. }
  30. return _arr;
  31. }
  32. function _nonIterableRest() {
  33. throw new TypeError("Invalid attempt to destructure non-iterable instance");
  34. }
  35. // Adapted from vega-statistics by Jeffrey Heer
  36. // License: https://github.com/vega/vega/blob/f058b099decad9db78301405dd0d2e9d8ba3d51a/LICENSE
  37. // Source: https://github.com/vega/vega/blob/f058b099decad9db78301405dd0d2e9d8ba3d51a/packages/vega-statistics/src/regression/points.js
  38. function points(data, x, y, sort) {
  39. data = data.filter(function (d, i) {
  40. var u = x(d, i),
  41. v = y(d, i);
  42. return u != null && isFinite(u) && v != null && isFinite(v);
  43. });
  44. if (sort) {
  45. data.sort(function (a, b) {
  46. return x(a) - x(b);
  47. });
  48. }
  49. var n = data.length,
  50. X = new Float64Array(n),
  51. Y = new Float64Array(n); // extract values, calculate means
  52. var ux = 0,
  53. uy = 0,
  54. xv,
  55. yv,
  56. d;
  57. for (var i = 0; i < n;) {
  58. d = data[i];
  59. X[i] = xv = +x(d, i, data);
  60. Y[i] = yv = +y(d, i, data);
  61. ++i;
  62. ux += (xv - ux) / i;
  63. uy += (yv - uy) / i;
  64. } // mean center the data
  65. for (var _i = 0; _i < n; ++_i) {
  66. X[_i] -= ux;
  67. Y[_i] -= uy;
  68. }
  69. return [X, Y, ux, uy];
  70. }
  71. function visitPoints(data, x, y, cb) {
  72. var iterations = 0;
  73. for (var i = 0, n = data.length; i < n; i++) {
  74. var d = data[i],
  75. dx = +x(d, i, data),
  76. dy = +y(d, i, data);
  77. if (dx != null && isFinite(dx) && dy != null && isFinite(dy)) {
  78. cb(dx, dy, iterations++);
  79. }
  80. }
  81. }
  82. // return the coefficient of determination, or R squared.
  83. function determination(data, x, y, uY, predict) {
  84. var SSE = 0,
  85. SST = 0;
  86. visitPoints(data, x, y, function (dx, dy) {
  87. var sse = dy - predict(dx),
  88. sst = dy - uY;
  89. SSE += sse * sse;
  90. SST += sst * sst;
  91. });
  92. return 1 - SSE / SST;
  93. }
  94. // Returns the angle of a line in degrees.
  95. function angle(line) {
  96. return Math.atan2(line[1][1] - line[0][1], line[1][0] - line[0][0]) * 180 / Math.PI;
  97. } // Returns the midpoint of a line.
  98. function midpoint(line) {
  99. return [(line[0][0] + line[1][0]) / 2, (line[0][1] + line[1][1]) / 2];
  100. }
  101. // returns a smooth line.
  102. function interpose(xmin, xmax, predict) {
  103. var l = Math.log(xmax - xmin) * Math.LOG10E + 1 | 0;
  104. var precision = 1 * Math.pow(10, -l / 2 - 1),
  105. maxIter = 1e4;
  106. var points = [px(xmin), px(xmax)],
  107. iter = 0;
  108. while (find(points) && iter < maxIter) {
  109. }
  110. return points;
  111. function px(x) {
  112. return [x, predict(x)];
  113. }
  114. function find(points) {
  115. iter++;
  116. var n = points.length;
  117. var found = false;
  118. for (var i = 0; i < n - 1; i++) {
  119. var p0 = points[i],
  120. p1 = points[i + 1],
  121. m = midpoint([p0, p1]),
  122. mp = px(m[0]),
  123. a0 = angle([p0, m]),
  124. a1 = angle([p0, mp]),
  125. a = Math.abs(a0 - a1);
  126. if (a > precision) {
  127. points.splice(i + 1, 0, mp);
  128. found = true;
  129. }
  130. }
  131. return found;
  132. }
  133. }
  134. // Ordinary Least Squares from vega-statistics by Jeffrey Heer
  135. // License: https://github.com/vega/vega/blob/f058b099decad9db78301405dd0d2e9d8ba3d51a/LICENSE
  136. // Source: https://github.com/vega/vega/blob/f058b099decad9db78301405dd0d2e9d8ba3d51a/packages/vega-statistics/src/regression/ols.js
  137. function ols(uX, uY, uXY, uX2) {
  138. var delta = uX2 - uX * uX,
  139. slope = Math.abs(delta) < 1e-24 ? 0 : (uXY - uX * uY) / delta,
  140. intercept = uY - slope * uX;
  141. return [intercept, slope];
  142. }
  143. function exponential () {
  144. var x = function x(d) {
  145. return d[0];
  146. },
  147. y = function y(d) {
  148. return d[1];
  149. },
  150. domain;
  151. function exponential(data) {
  152. var n = 0,
  153. Y = 0,
  154. YL = 0,
  155. XY = 0,
  156. XYL = 0,
  157. X2Y = 0,
  158. xmin = domain ? +domain[0] : Infinity,
  159. xmax = domain ? +domain[1] : -Infinity;
  160. visitPoints(data, x, y, function (dx, dy) {
  161. var ly = Math.log(dy),
  162. xy = dx * dy;
  163. ++n;
  164. Y += (dy - Y) / n;
  165. XY += (xy - XY) / n;
  166. X2Y += (dx * xy - X2Y) / n;
  167. YL += (dy * ly - YL) / n;
  168. XYL += (xy * ly - XYL) / n;
  169. if (!domain) {
  170. if (dx < xmin) xmin = dx;
  171. if (dx > xmax) xmax = dx;
  172. }
  173. });
  174. var _ols = ols(XY / Y, YL / Y, XYL / Y, X2Y / Y),
  175. _ols2 = _slicedToArray(_ols, 2),
  176. a = _ols2[0],
  177. b = _ols2[1];
  178. a = Math.exp(a);
  179. var fn = function fn(x) {
  180. return a * Math.exp(b * x);
  181. },
  182. out = interpose(xmin, xmax, fn);
  183. out.a = a;
  184. out.b = b;
  185. out.predict = fn;
  186. out.rSquared = determination(data, x, y, Y, fn);
  187. return out;
  188. }
  189. exponential.domain = function (arr) {
  190. return arguments.length ? (domain = arr, exponential) : domain;
  191. };
  192. exponential.x = function (fn) {
  193. return arguments.length ? (x = fn, exponential) : x;
  194. };
  195. exponential.y = function (fn) {
  196. return arguments.length ? (y = fn, exponential) : y;
  197. };
  198. return exponential;
  199. }
  200. function linear () {
  201. var x = function x(d) {
  202. return d[0];
  203. },
  204. y = function y(d) {
  205. return d[1];
  206. },
  207. domain;
  208. function linear(data) {
  209. var n = 0,
  210. X = 0,
  211. // sum of x
  212. Y = 0,
  213. // sum of y
  214. XY = 0,
  215. // sum of x * y
  216. X2 = 0,
  217. // sum of x * x
  218. xmin = domain ? +domain[0] : Infinity,
  219. xmax = domain ? +domain[1] : -Infinity;
  220. visitPoints(data, x, y, function (dx, dy) {
  221. ++n;
  222. X += (dx - X) / n;
  223. Y += (dy - Y) / n;
  224. XY += (dx * dy - XY) / n;
  225. X2 += (dx * dx - X2) / n;
  226. if (!domain) {
  227. if (dx < xmin) xmin = dx;
  228. if (dx > xmax) xmax = dx;
  229. }
  230. });
  231. var _ols = ols(X, Y, XY, X2),
  232. _ols2 = _slicedToArray(_ols, 2),
  233. intercept = _ols2[0],
  234. slope = _ols2[1],
  235. fn = function fn(x) {
  236. return slope * x + intercept;
  237. },
  238. out = [[xmin, fn(xmin)], [xmax, fn(xmax)]];
  239. out.a = slope;
  240. out.b = intercept;
  241. out.predict = fn;
  242. out.rSquared = determination(data, x, y, Y, fn);
  243. return out;
  244. }
  245. linear.domain = function (arr) {
  246. return arguments.length ? (domain = arr, linear) : domain;
  247. };
  248. linear.x = function (fn) {
  249. return arguments.length ? (x = fn, linear) : x;
  250. };
  251. linear.y = function (fn) {
  252. return arguments.length ? (y = fn, linear) : y;
  253. };
  254. return linear;
  255. }
  256. // Returns the medium value of an array of numbers.
  257. function median(arr) {
  258. arr.sort(function (a, b) {
  259. return a - b;
  260. });
  261. var i = arr.length / 2;
  262. return i % 1 === 0 ? (arr[i - 1] + arr[i]) / 2 : arr[Math.floor(i)];
  263. }
  264. var maxiters = 2,
  265. epsilon = 1e-12;
  266. function loess () {
  267. var x = function x(d) {
  268. return d[0];
  269. },
  270. y = function y(d) {
  271. return d[1];
  272. },
  273. bandwidth = .3;
  274. function loess(data) {
  275. var _points = points(data, x, y, true),
  276. _points2 = _slicedToArray(_points, 4),
  277. xv = _points2[0],
  278. yv = _points2[1],
  279. ux = _points2[2],
  280. uy = _points2[3],
  281. n = xv.length,
  282. bw = Math.max(2, ~~(bandwidth * n)),
  283. yhat = new Float64Array(n),
  284. residuals = new Float64Array(n),
  285. robustWeights = new Float64Array(n).fill(1);
  286. for (var iter = -1; ++iter <= maxiters;) {
  287. var interval = [0, bw - 1];
  288. for (var i = 0; i < n; ++i) {
  289. var dx = xv[i],
  290. i0 = interval[0],
  291. i1 = interval[1],
  292. edge = dx - xv[i0] > xv[i1] - dx ? i0 : i1;
  293. var W = 0,
  294. X = 0,
  295. Y = 0,
  296. XY = 0,
  297. X2 = 0,
  298. denom = 1 / Math.abs(xv[edge] - dx || 1); // Avoid singularity
  299. for (var k = i0; k <= i1; ++k) {
  300. var xk = xv[k],
  301. yk = yv[k],
  302. w = tricube(Math.abs(dx - xk) * denom) * robustWeights[k],
  303. xkw = xk * w;
  304. W += w;
  305. X += xkw;
  306. Y += yk * w;
  307. XY += yk * xkw;
  308. X2 += xk * xkw;
  309. } // Linear regression fit
  310. var _ols = ols(X / W, Y / W, XY / W, X2 / W),
  311. _ols2 = _slicedToArray(_ols, 2),
  312. a = _ols2[0],
  313. b = _ols2[1];
  314. yhat[i] = a + b * dx;
  315. residuals[i] = Math.abs(yv[i] - yhat[i]);
  316. updateInterval(xv, i + 1, interval);
  317. }
  318. if (iter === maxiters) {
  319. break;
  320. }
  321. var medianResidual = median(residuals);
  322. if (Math.abs(medianResidual) < epsilon) break;
  323. for (var _i = 0, arg, _w; _i < n; ++_i) {
  324. arg = residuals[_i] / (6 * medianResidual); // Default to epsilon (rather than zero) for large deviations
  325. // Keeping weights tiny but non-zero prevents singularites
  326. robustWeights[_i] = arg >= 1 ? epsilon : (_w = 1 - arg * arg) * _w;
  327. }
  328. }
  329. return output(xv, yhat, ux, uy);
  330. }
  331. loess.bandwidth = function (bw) {
  332. return arguments.length ? (bandwidth = bw, loess) : bandwidth;
  333. };
  334. loess.x = function (fn) {
  335. return arguments.length ? (x = fn, loess) : x;
  336. };
  337. loess.y = function (fn) {
  338. return arguments.length ? (y = fn, loess) : y;
  339. };
  340. return loess;
  341. } // Weighting kernel for local regression
  342. function tricube(x) {
  343. return (x = 1 - x * x * x) * x * x;
  344. } // Advance sliding window interval of nearest neighbors
  345. function updateInterval(xv, i, interval) {
  346. var val = xv[i],
  347. left = interval[0],
  348. right = interval[1] + 1;
  349. if (right >= xv.length) return; // Step right if distance to new right edge is <= distance to old left edge
  350. // Step when distance is equal to ensure movement over duplicate x values
  351. while (i > left && xv[right] - val <= val - xv[left]) {
  352. interval[0] = ++left;
  353. interval[1] = right;
  354. ++right;
  355. }
  356. } // Generate smoothed output points
  357. // Average points with repeated x values
  358. function output(xv, yhat, ux, uy) {
  359. var n = xv.length,
  360. out = [];
  361. var i = 0,
  362. cnt = 0,
  363. prev = [],
  364. v;
  365. for (; i < n; ++i) {
  366. v = xv[i] + ux;
  367. if (prev[0] === v) {
  368. // Average output values via online update
  369. prev[1] += (yhat[i] - prev[1]) / ++cnt;
  370. } else {
  371. // Add new output point
  372. cnt = 0;
  373. prev[1] += uy;
  374. prev = [v, yhat[i]];
  375. out.push(prev);
  376. }
  377. }
  378. prev[1] += uy;
  379. return out;
  380. }
  381. function logarithmic () {
  382. var x = function x(d) {
  383. return d[0];
  384. },
  385. y = function y(d) {
  386. return d[1];
  387. },
  388. base = Math.E,
  389. domain;
  390. function logarithmic(data) {
  391. var n = 0,
  392. X = 0,
  393. Y = 0,
  394. XY = 0,
  395. X2 = 0,
  396. xmin = domain ? +domain[0] : Infinity,
  397. xmax = domain ? +domain[1] : -Infinity,
  398. lb = Math.log(base);
  399. visitPoints(data, x, y, function (dx, dy) {
  400. var lx = Math.log(dx) / lb;
  401. ++n;
  402. X += (lx - X) / n;
  403. Y += (dy - Y) / n;
  404. XY += (lx * dy - XY) / n;
  405. X2 += (lx * lx - X2) / n;
  406. if (!domain) {
  407. if (dx < xmin) xmin = dx;
  408. if (dx > xmax) xmax = dx;
  409. }
  410. });
  411. var _ols = ols(X, Y, XY, X2),
  412. _ols2 = _slicedToArray(_ols, 2),
  413. intercept = _ols2[0],
  414. slope = _ols2[1],
  415. fn = function fn(x) {
  416. return slope * Math.log(x) / lb + intercept;
  417. },
  418. out = interpose(xmin, xmax, fn);
  419. out.a = slope;
  420. out.b = intercept;
  421. out.predict = fn;
  422. out.rSquared = determination(data, x, y, Y, fn);
  423. return out;
  424. }
  425. logarithmic.domain = function (arr) {
  426. return arguments.length ? (domain = arr, logarithmic) : domain;
  427. };
  428. logarithmic.x = function (fn) {
  429. return arguments.length ? (x = fn, logarithmic) : x;
  430. };
  431. logarithmic.y = function (fn) {
  432. return arguments.length ? (y = fn, logarithmic) : y;
  433. };
  434. logarithmic.base = function (n) {
  435. return arguments.length ? (base = n, logarithmic) : base;
  436. };
  437. return logarithmic;
  438. }
  439. function quad () {
  440. var x = function x(d) {
  441. return d[0];
  442. },
  443. y = function y(d) {
  444. return d[1];
  445. },
  446. domain;
  447. function quadratic(data) {
  448. var _points = points(data, x, y),
  449. _points2 = _slicedToArray(_points, 4),
  450. xv = _points2[0],
  451. yv = _points2[1],
  452. ux = _points2[2],
  453. uy = _points2[3],
  454. n = xv.length;
  455. var X2 = 0,
  456. X3 = 0,
  457. X4 = 0,
  458. XY = 0,
  459. X2Y = 0,
  460. i,
  461. dx,
  462. dy,
  463. x2;
  464. for (i = 0; i < n;) {
  465. dx = xv[i];
  466. dy = yv[i++];
  467. x2 = dx * dx;
  468. X2 += (x2 - X2) / i;
  469. X3 += (x2 * dx - X3) / i;
  470. X4 += (x2 * x2 - X4) / i;
  471. XY += (dx * dy - XY) / i;
  472. X2Y += (x2 * dy - X2Y) / i;
  473. }
  474. var Y = 0,
  475. n0 = 0,
  476. xmin = domain ? +domain[0] : Infinity,
  477. xmax = domain ? +domain[1] : -Infinity;
  478. visitPoints(data, x, y, function (dx, dy) {
  479. n0++;
  480. Y += (dy - Y) / n0;
  481. if (!domain) {
  482. if (dx < xmin) xmin = dx;
  483. if (dx > xmax) xmax = dx;
  484. }
  485. });
  486. var X2X2 = X4 - X2 * X2,
  487. d = X2 * X2X2 - X3 * X3,
  488. a = (X2Y * X2 - XY * X3) / d,
  489. b = (XY * X2X2 - X2Y * X3) / d,
  490. c = -a * X2,
  491. fn = function fn(x) {
  492. x = x - ux;
  493. return a * x * x + b * x + c + uy;
  494. };
  495. var out = interpose(xmin, xmax, fn);
  496. out.a = a;
  497. out.b = b - 2 * a * ux;
  498. out.c = c - b * ux + a * ux * ux + uy;
  499. out.predict = fn;
  500. out.rSquared = determination(data, x, y, Y, fn);
  501. return out;
  502. }
  503. quadratic.domain = function (arr) {
  504. return arguments.length ? (domain = arr, quadratic) : domain;
  505. };
  506. quadratic.x = function (fn) {
  507. return arguments.length ? (x = fn, quadratic) : x;
  508. };
  509. quadratic.y = function (fn) {
  510. return arguments.length ? (y = fn, quadratic) : y;
  511. };
  512. return quadratic;
  513. }
  514. // Source: https://github.com/Tom-Alexander/regression-js/blob/master/src/regression.js#L246
  515. // License: https://github.com/Tom-Alexander/regression-js/blob/master/LICENSE
  516. // ...with ideas from vega-statistics by Jeffrey Heer
  517. // Source: https://github.com/vega/vega/blob/f21cb8792b4e0cbe2b1a3fd44b0f5db370dbaadb/packages/vega-statistics/src/regression/poly.js
  518. // License: https://github.com/vega/vega/blob/f058b099decad9db78301405dd0d2e9d8ba3d51a/LICENSE
  519. function polynomial () {
  520. var x = function x(d) {
  521. return d[0];
  522. },
  523. y = function y(d) {
  524. return d[1];
  525. },
  526. order = 3,
  527. domain;
  528. function polynomial(data) {
  529. // Use more efficient methods for lower orders
  530. if (order === 1) {
  531. var o = linear().x(x).y(y).domain(domain)(data);
  532. o.coefficients = [o.b, o.a];
  533. delete o.a;
  534. delete o.b;
  535. return o;
  536. }
  537. if (order === 2) {
  538. var _o = quad().x(x).y(y).domain(domain)(data);
  539. _o.coefficients = [_o.c, _o.b, _o.a];
  540. delete _o.a;
  541. delete _o.b;
  542. delete _o.c;
  543. return _o;
  544. }
  545. var _points = points(data, x, y),
  546. _points2 = _slicedToArray(_points, 4),
  547. xv = _points2[0],
  548. yv = _points2[1],
  549. ux = _points2[2],
  550. uy = _points2[3],
  551. n = xv.length,
  552. lhs = [],
  553. rhs = [],
  554. k = order + 1;
  555. var Y = 0,
  556. n0 = 0,
  557. xmin = domain ? +domain[0] : Infinity,
  558. xmax = domain ? +domain[1] : -Infinity;
  559. visitPoints(data, x, y, function (dx, dy) {
  560. ++n0;
  561. Y += (dy - Y) / n0;
  562. if (!domain) {
  563. if (dx < xmin) xmin = dx;
  564. if (dx > xmax) xmax = dx;
  565. }
  566. });
  567. var i, j, l, v, c;
  568. for (i = 0; i < k; ++i) {
  569. for (l = 0, v = 0; l < n; ++l) {
  570. v += Math.pow(xv[l], i) * yv[l];
  571. }
  572. lhs.push(v);
  573. c = new Float64Array(k);
  574. for (j = 0; j < k; ++j) {
  575. for (l = 0, v = 0; l < n; ++l) {
  576. v += Math.pow(xv[l], i + j);
  577. }
  578. c[j] = v;
  579. }
  580. rhs.push(c);
  581. }
  582. rhs.push(lhs);
  583. var coef = gaussianElimination(rhs),
  584. fn = function fn(x) {
  585. x -= ux;
  586. var y = uy + coef[0] + coef[1] * x + coef[2] * x * x;
  587. for (i = 3; i < k; ++i) {
  588. y += coef[i] * Math.pow(x, i);
  589. }
  590. return y;
  591. },
  592. out = interpose(xmin, xmax, fn);
  593. out.coefficients = uncenter(k, coef, -ux, uy);
  594. out.predict = fn;
  595. out.rSquared = determination(data, x, y, Y, fn);
  596. return out;
  597. }
  598. polynomial.domain = function (arr) {
  599. return arguments.length ? (domain = arr, polynomial) : domain;
  600. };
  601. polynomial.x = function (fn) {
  602. return arguments.length ? (x = fn, polynomial) : x;
  603. };
  604. polynomial.y = function (fn) {
  605. return arguments.length ? (y = fn, polynomial) : y;
  606. };
  607. polynomial.order = function (n) {
  608. return arguments.length ? (order = n, polynomial) : order;
  609. };
  610. return polynomial;
  611. }
  612. function uncenter(k, a, x, y) {
  613. var z = Array(k);
  614. var i, j, v, c; // initialize to zero
  615. for (i = 0; i < k; ++i) {
  616. z[i] = 0;
  617. } // polynomial expansion
  618. for (i = k - 1; i >= 0; --i) {
  619. v = a[i];
  620. c = 1;
  621. z[i] += v;
  622. for (j = 1; j <= i; ++j) {
  623. c *= (i + 1 - j) / j; // binomial coefficent
  624. z[i - j] += v * Math.pow(x, j) * c;
  625. }
  626. } // bias term
  627. z[0] += y;
  628. return z;
  629. } // Given an array for a two-dimensional matrix and the polynomial order,
  630. // solve A * x = b using Gaussian elimination.
  631. function gaussianElimination(matrix) {
  632. var n = matrix.length - 1,
  633. coef = [];
  634. var i, j, k, r, t;
  635. for (i = 0; i < n; ++i) {
  636. r = i; // max row
  637. for (j = i + 1; j < n; ++j) {
  638. if (Math.abs(matrix[i][j]) > Math.abs(matrix[i][r])) {
  639. r = j;
  640. }
  641. }
  642. for (k = i; k < n + 1; ++k) {
  643. t = matrix[k][i];
  644. matrix[k][i] = matrix[k][r];
  645. matrix[k][r] = t;
  646. }
  647. for (j = i + 1; j < n; ++j) {
  648. for (k = n; k >= i; k--) {
  649. matrix[k][j] -= matrix[k][i] * matrix[i][j] / matrix[i][i];
  650. }
  651. }
  652. }
  653. for (j = n - 1; j >= 0; --j) {
  654. t = 0;
  655. for (k = j + 1; k < n; ++k) {
  656. t += matrix[k][j] * coef[k];
  657. }
  658. coef[j] = (matrix[n][j] - t) / matrix[j][j];
  659. }
  660. return coef;
  661. }
  662. function power () {
  663. var x = function x(d) {
  664. return d[0];
  665. },
  666. y = function y(d) {
  667. return d[1];
  668. },
  669. domain;
  670. function power(data) {
  671. var n = 0,
  672. X = 0,
  673. Y = 0,
  674. XY = 0,
  675. X2 = 0,
  676. YS = 0,
  677. xmin = domain ? +domain[0] : Infinity,
  678. xmax = domain ? +domain[1] : -Infinity;
  679. visitPoints(data, x, y, function (dx, dy) {
  680. var lx = Math.log(dx),
  681. ly = Math.log(dy);
  682. ++n;
  683. X += (lx - X) / n;
  684. Y += (ly - Y) / n;
  685. XY += (lx * ly - XY) / n;
  686. X2 += (lx * lx - X2) / n;
  687. YS += (dy - YS) / n;
  688. if (!domain) {
  689. if (dx < xmin) xmin = dx;
  690. if (dx > xmax) xmax = dx;
  691. }
  692. });
  693. var _ols = ols(X, Y, XY, X2),
  694. _ols2 = _slicedToArray(_ols, 2),
  695. a = _ols2[0],
  696. b = _ols2[1];
  697. a = Math.exp(a);
  698. var fn = function fn(x) {
  699. return a * Math.pow(x, b);
  700. },
  701. out = interpose(xmin, xmax, fn);
  702. out.a = a;
  703. out.b = b;
  704. out.predict = fn;
  705. out.rSquared = determination(data, x, y, YS, fn);
  706. return out;
  707. }
  708. power.domain = function (arr) {
  709. return arguments.length ? (domain = arr, power) : domain;
  710. };
  711. power.x = function (fn) {
  712. return arguments.length ? (x = fn, power) : x;
  713. };
  714. power.y = function (fn) {
  715. return arguments.length ? (y = fn, power) : y;
  716. };
  717. return power;
  718. }
  719. exports.regressionExp = exponential;
  720. exports.regressionLinear = linear;
  721. exports.regressionLoess = loess;
  722. exports.regressionLog = logarithmic;
  723. exports.regressionPoly = polynomial;
  724. exports.regressionPow = power;
  725. exports.regressionQuad = quad;