d3-regression.js 21 KB

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