@visactor/vutils 1.0.9 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/cjs/common/ecdf.d.ts +10 -0
  2. package/cjs/common/ecdf.js +52 -0
  3. package/cjs/common/ecdf.js.map +1 -0
  4. package/cjs/common/index.d.ts +5 -0
  5. package/cjs/common/index.js +4 -2
  6. package/cjs/common/index.js.map +1 -1
  7. package/cjs/common/interpolate.js +2 -1
  8. package/cjs/common/isPlainObject.js +1 -2
  9. package/cjs/common/isPrototype.js +2 -1
  10. package/cjs/common/isValidNumber.js +1 -1
  11. package/cjs/common/kde.d.ts +21 -0
  12. package/cjs/common/kde.js +126 -0
  13. package/cjs/common/kde.js.map +1 -0
  14. package/cjs/common/regression-linear.d.ts +31 -6
  15. package/cjs/common/regression-linear.js +97 -20
  16. package/cjs/common/regression-linear.js.map +1 -1
  17. package/cjs/common/regression-logistic.d.ts +20 -0
  18. package/cjs/common/regression-logistic.js +110 -0
  19. package/cjs/common/regression-logistic.js.map +1 -0
  20. package/cjs/common/regression-lowess.d.ts +21 -0
  21. package/cjs/common/regression-lowess.js +141 -0
  22. package/cjs/common/regression-lowess.js.map +1 -0
  23. package/cjs/common/regression-polynomial.d.ts +21 -0
  24. package/cjs/common/regression-polynomial.js +143 -0
  25. package/cjs/common/regression-polynomial.js.map +1 -0
  26. package/cjs/common/regression-utils.d.ts +20 -0
  27. package/cjs/common/regression-utils.js +76 -0
  28. package/cjs/common/regression-utils.js.map +1 -0
  29. package/dist/index.js +937 -36
  30. package/dist/index.min.js +1 -1
  31. package/es/common/ecdf.d.ts +10 -0
  32. package/es/common/ecdf.js +48 -0
  33. package/es/common/ecdf.js.map +1 -0
  34. package/es/common/index.d.ts +5 -0
  35. package/es/common/index.js +10 -1
  36. package/es/common/index.js.map +1 -1
  37. package/es/common/interpolate.js +2 -1
  38. package/es/common/isPlainObject.js +1 -2
  39. package/es/common/isPrototype.js +2 -1
  40. package/es/common/isValidNumber.js +1 -1
  41. package/es/common/kde.d.ts +21 -0
  42. package/es/common/kde.js +117 -0
  43. package/es/common/kde.js.map +1 -0
  44. package/es/common/regression-linear.d.ts +31 -6
  45. package/es/common/regression-linear.js +97 -18
  46. package/es/common/regression-linear.js.map +1 -1
  47. package/es/common/regression-logistic.d.ts +20 -0
  48. package/es/common/regression-logistic.js +105 -0
  49. package/es/common/regression-logistic.js.map +1 -0
  50. package/es/common/regression-lowess.d.ts +21 -0
  51. package/es/common/regression-lowess.js +136 -0
  52. package/es/common/regression-lowess.js.map +1 -0
  53. package/es/common/regression-polynomial.d.ts +21 -0
  54. package/es/common/regression-polynomial.js +134 -0
  55. package/es/common/regression-polynomial.js.map +1 -0
  56. package/es/common/regression-utils.d.ts +20 -0
  57. package/es/common/regression-utils.js +63 -0
  58. package/es/common/regression-utils.js.map +1 -0
  59. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1716,54 +1716,946 @@
1716
1716
  return [min, max];
1717
1717
  };
1718
1718
 
1719
+ function invNorm(p) {
1720
+ if (p <= 0 || p >= 1) {
1721
+ return 0;
1722
+ }
1723
+ const a1 = -39.6968302866538;
1724
+ const a2 = 220.946098424521;
1725
+ const a3 = -275.928510446969;
1726
+ const a4 = 138.357751867269;
1727
+ const a5 = -30.6647980661472;
1728
+ const a6 = 2.50662827745924;
1729
+ const b1 = -54.4760987982241;
1730
+ const b2 = 161.585836858041;
1731
+ const b3 = -155.698979859887;
1732
+ const b4 = 66.8013118877197;
1733
+ const b5 = -13.2806815528857;
1734
+ const c1 = -0.00778489400243029;
1735
+ const c2 = -0.322396458041136;
1736
+ const c3 = -2.40075827716184;
1737
+ const c4 = -2.54973253934373;
1738
+ const c5 = 4.37466414146497;
1739
+ const c6 = 2.93816398269878;
1740
+ const d1 = 0.00778469570904146;
1741
+ const d2 = 0.32246712907004;
1742
+ const d3 = 2.445134137143;
1743
+ const d4 = 3.75440866190742;
1744
+ const pLow = 0.02425;
1745
+ const pHigh = 1 - pLow;
1746
+ let q;
1747
+ let r;
1748
+ if (p < pLow) {
1749
+ q = Math.sqrt(-2 * Math.log(p));
1750
+ return (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
1751
+ }
1752
+ if (p <= pHigh) {
1753
+ q = p - 0.5;
1754
+ r = q * q;
1755
+ return (((((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q) /
1756
+ (((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1));
1757
+ }
1758
+ q = Math.sqrt(-2 * Math.log(1 - p));
1759
+ return -((((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1));
1760
+ }
1761
+ function computeLinearCIComponents(data, x, y, predict) {
1762
+ let min = Infinity;
1763
+ let max = -Infinity;
1764
+ let n = 0;
1765
+ let sumX = 0;
1766
+ for (let i = 0; i < data.length; i++) {
1767
+ const d = data[i];
1768
+ let dx = x(d);
1769
+ let dy = y(d);
1770
+ if (!isNil(dx) && (dx = +dx) >= dx && !isNil(dy) && (dy = +dy) >= dy) {
1771
+ if (dx < min) {
1772
+ min = dx;
1773
+ }
1774
+ if (dx > max) {
1775
+ max = dx;
1776
+ }
1777
+ n++;
1778
+ sumX += dx;
1779
+ }
1780
+ }
1781
+ if (n === 0) {
1782
+ return { min, max, n, X: 0, SSE: 0, Sxx: 0 };
1783
+ }
1784
+ const X = sumX / n;
1785
+ let SSE = 0;
1786
+ let Sxx = 0;
1787
+ for (let i = 0; i < data.length; i++) {
1788
+ const d = data[i];
1789
+ let dx = x(d);
1790
+ let dy = y(d);
1791
+ if (!isNil(dx) && (dx = +dx) >= dx && !isNil(dy) && (dy = +dy) >= dy) {
1792
+ const r = dy - predict(dx);
1793
+ SSE += r * r;
1794
+ const dxc = dx - X;
1795
+ Sxx += dxc * dxc;
1796
+ }
1797
+ }
1798
+ return { min, max, n, X, SSE, Sxx };
1799
+ }
1800
+ function stdErrorsAt(px, comps) {
1801
+ const { n, X, Sxx, SSE } = comps;
1802
+ const s2 = n > 2 ? SSE / (n - 2) : 0;
1803
+ const seMean = Sxx > 0 ? Math.sqrt(s2 * (1 / n + ((px - X) * (px - X)) / Sxx)) : Math.sqrt(s2 / n);
1804
+ const sePred = Math.sqrt(s2 * (1 + 1 / n + (Sxx > 0 ? ((px - X) * (px - X)) / Sxx : 0)));
1805
+ return { seMean, sePred };
1806
+ }
1807
+
1719
1808
  function ordinaryLeastSquares(uX, uY, uXY, uX2) {
1720
- const delta = uX2 - uX * uX;
1721
- const slope = Math.abs(delta) < 1e-24 ? 0 : (uXY - uX * uY) / delta;
1722
- const intercept = uY - slope * uX;
1723
- return [intercept, slope];
1809
+ const denom = uX2 - uX * uX;
1810
+ if (Math.abs(denom) < Number.EPSILON) {
1811
+ return { a: uY, b: 0 };
1812
+ }
1813
+ const b = (uXY - uX * uY) / denom;
1814
+ const a = uY - b * uX;
1815
+ return { a, b };
1724
1816
  }
1725
1817
  function visitPoints(data, x, y, callback) {
1726
- let i = -1;
1727
- let u;
1728
- let v;
1729
- data.forEach(d => {
1730
- u = x(d);
1731
- v = y(d);
1732
- if (!isNil(u) && (u = +u) >= u && !isNil(v) && (v = +v) >= v) {
1733
- callback(u, v, ++i);
1818
+ for (let i = 0; i < data.length; i++) {
1819
+ const d = data[i];
1820
+ let xi = x(d);
1821
+ let yi = y(d);
1822
+ if (!isNil(xi) && (xi = +xi) >= xi && !isNil(yi) && (yi = +yi) >= yi) {
1823
+ callback(xi, yi, i);
1734
1824
  }
1735
- });
1825
+ }
1736
1826
  }
1737
1827
  function rSquared(data, x, y, uY, predict) {
1738
- let SSE = 0;
1739
- let SST = 0;
1828
+ let ssr = 0;
1829
+ let sst = 0;
1830
+ for (let i = 0; i < data.length; i++) {
1831
+ const d = data[i];
1832
+ let yi = y(d);
1833
+ if (!isNil(yi) && (yi = +yi) >= yi) {
1834
+ const p = predict(x(d));
1835
+ const r = yi - p;
1836
+ ssr += r * r;
1837
+ const t = yi - uY;
1838
+ sst += t * t;
1839
+ }
1840
+ }
1841
+ return sst === 0 ? 0 : 1 - ssr / sst;
1842
+ }
1843
+ function regressionLinear(data, x = d => d.x, y = d => d.y) {
1844
+ let n = 0;
1845
+ let meanX = 0;
1846
+ let meanY = 0;
1847
+ let meanXY = 0;
1848
+ let meanX2 = 0;
1849
+ visitPoints(data, x, y, (xi, yi) => {
1850
+ n++;
1851
+ meanX += (xi - meanX) / n;
1852
+ meanY += (yi - meanY) / n;
1853
+ meanXY += (xi * yi - meanXY) / n;
1854
+ meanX2 += (xi * xi - meanX2) / n;
1855
+ });
1856
+ const { a, b } = ordinaryLeastSquares(meanX, meanY, meanXY, meanX2);
1857
+ const predict = (xx) => a + b * xx;
1858
+ const comps = computeLinearCIComponents(data, x, y, predict);
1859
+ function evaluateGrid(N) {
1860
+ const out = [];
1861
+ if (comps.n === 0 || N <= 0) {
1862
+ return out;
1863
+ }
1864
+ if (comps.min === comps.max) {
1865
+ for (let i = 0; i < N; i++) {
1866
+ out.push({ x: comps.min, y: predict(comps.min) });
1867
+ }
1868
+ return out;
1869
+ }
1870
+ const step = (comps.max - comps.min) / (N - 1);
1871
+ for (let i = 0; i < N; i++) {
1872
+ const px = i === N - 1 ? comps.max : comps.min + step * i;
1873
+ out.push({ x: px, y: predict(px) });
1874
+ }
1875
+ return out;
1876
+ }
1877
+ function confidenceInterval(N = 50, alpha = 0.05) {
1878
+ const out = [];
1879
+ if (comps.n === 0 || N <= 0) {
1880
+ return out;
1881
+ }
1882
+ const z = invNorm(1 - alpha / 2);
1883
+ if (comps.min === comps.max) {
1884
+ const m = predict(comps.min);
1885
+ const errs = stdErrorsAt(comps.min, comps);
1886
+ for (let i = 0; i < N; i++) {
1887
+ out.push({
1888
+ x: comps.min,
1889
+ mean: m,
1890
+ lower: m - z * errs.seMean,
1891
+ upper: m + z * errs.seMean,
1892
+ predLower: m - z * errs.sePred,
1893
+ predUpper: m + z * errs.sePred
1894
+ });
1895
+ }
1896
+ return out;
1897
+ }
1898
+ const step = (comps.max - comps.min) / (N - 1);
1899
+ for (let i = 0; i < N; i++) {
1900
+ const px = i === N - 1 ? comps.max : comps.min + step * i;
1901
+ const m = predict(px);
1902
+ const errs = stdErrorsAt(px, comps);
1903
+ out.push({
1904
+ x: px,
1905
+ mean: m,
1906
+ lower: m - z * errs.seMean,
1907
+ upper: m + z * errs.seMean,
1908
+ predLower: m - z * errs.sePred,
1909
+ predUpper: m + z * errs.sePred
1910
+ });
1911
+ }
1912
+ return out;
1913
+ }
1914
+ return {
1915
+ coef: { a, b },
1916
+ predict,
1917
+ rSquared: rSquared(data, x, y, meanY, predict),
1918
+ evaluateGrid,
1919
+ confidenceInterval
1920
+ };
1921
+ }
1922
+
1923
+ function regressionLogistic(data, x = d => d.x, y = d => d.y, options) {
1924
+ var _a, _b;
1925
+ const maxIter = (_a = options === null || options === void 0 ? void 0 : options.maxIteration) !== null && _a !== void 0 ? _a : 25;
1926
+ const tol = (_b = options === null || options === void 0 ? void 0 : options.tol) !== null && _b !== void 0 ? _b : 1e-6;
1927
+ const xs = [];
1928
+ const ys = [];
1929
+ visitPoints(data, x, y, (dx, dy) => {
1930
+ xs.push(dx);
1931
+ ys.push(dy ? 1 : 0);
1932
+ });
1933
+ const n = xs.length;
1934
+ if (n === 0) {
1935
+ return {
1936
+ coef: [0, 0],
1937
+ predict: (_x) => 0,
1938
+ evaluateGrid: (N) => [],
1939
+ confidenceInterval: (N = 50) => []
1940
+ };
1941
+ }
1942
+ let intercept = 0;
1943
+ let beta = 0;
1944
+ for (let iter = 0; iter < maxIter; iter++) {
1945
+ const p = new Array(n);
1946
+ let converged = true;
1947
+ for (let i = 0; i < n; i++) {
1948
+ const z = intercept + beta * xs[i];
1949
+ const pi = 1 / (1 + Math.exp(-z));
1950
+ p[i] = pi;
1951
+ }
1952
+ let g0 = 0;
1953
+ let g1 = 0;
1954
+ let h00 = 0;
1955
+ let h01 = 0;
1956
+ let h11 = 0;
1957
+ for (let i = 0; i < n; i++) {
1958
+ const wi = p[i] * (1 - p[i]);
1959
+ const diff = ys[i] - p[i];
1960
+ g0 += diff;
1961
+ g1 += diff * xs[i];
1962
+ h00 += wi;
1963
+ h01 += wi * xs[i];
1964
+ h11 += wi * xs[i] * xs[i];
1965
+ }
1966
+ const det = h00 * h11 - h01 * h01;
1967
+ if (Math.abs(det) < 1e-12) {
1968
+ break;
1969
+ }
1970
+ const delta0 = (h11 * g0 - h01 * g1) / det;
1971
+ const delta1 = (-h01 * g0 + h00 * g1) / det;
1972
+ intercept += delta0;
1973
+ beta += delta1;
1974
+ if (Math.abs(delta0) > tol || Math.abs(delta1) > tol) {
1975
+ converged = false;
1976
+ }
1977
+ if (converged) {
1978
+ break;
1979
+ }
1980
+ }
1981
+ const predict = (xx) => {
1982
+ const z = intercept + beta * xx;
1983
+ return 1 / (1 + Math.exp(-z));
1984
+ };
1985
+ function evaluateGrid(N) {
1986
+ const out = [];
1987
+ if (N <= 0) {
1988
+ return out;
1989
+ }
1990
+ let min = Infinity;
1991
+ let max = -Infinity;
1992
+ visitPoints(data, x, y, dx => {
1993
+ if (dx < min) {
1994
+ min = dx;
1995
+ }
1996
+ if (dx > max) {
1997
+ max = dx;
1998
+ }
1999
+ });
2000
+ if (min === Infinity || max === -Infinity) {
2001
+ return out;
2002
+ }
2003
+ if (min === max) {
2004
+ const v = predict(min);
2005
+ for (let i = 0; i < N; i++) {
2006
+ out.push({ x: min, y: v });
2007
+ }
2008
+ return out;
2009
+ }
2010
+ const step = (max - min) / (N - 1);
2011
+ for (let i = 0; i < N; i++) {
2012
+ const px = i === N - 1 ? max : min + step * i;
2013
+ out.push({ x: px, y: predict(px) });
2014
+ }
2015
+ return out;
2016
+ }
2017
+ function confidenceInterval(N = 50, alpha = 0.05) {
2018
+ const out = [];
2019
+ if (N <= 0) {
2020
+ return out;
2021
+ }
2022
+ const comps = computeLinearCIComponents(data, x, y, predict);
2023
+ if (comps.n === 0) {
2024
+ return out;
2025
+ }
2026
+ const z = Math.abs(invNorm(1 - alpha / 2));
2027
+ if (comps.min === comps.max) {
2028
+ const v = predict(comps.min);
2029
+ const errs = stdErrorsAt(comps.min, comps);
2030
+ for (let i = 0; i < N; i++) {
2031
+ out.push({
2032
+ x: comps.min,
2033
+ mean: v,
2034
+ lower: v - z * errs.seMean,
2035
+ upper: v + z * errs.seMean,
2036
+ predLower: v - z * errs.sePred,
2037
+ predUpper: v + z * errs.sePred
2038
+ });
2039
+ }
2040
+ return out;
2041
+ }
2042
+ const step = (comps.max - comps.min) / (N - 1);
2043
+ for (let i = 0; i < N; i++) {
2044
+ const px = i === N - 1 ? comps.max : comps.min + step * i;
2045
+ const yh = predict(px);
2046
+ const errs = stdErrorsAt(px, comps);
2047
+ out.push({
2048
+ x: px,
2049
+ mean: yh,
2050
+ lower: yh - z * errs.seMean,
2051
+ upper: yh + z * errs.seMean,
2052
+ predLower: yh - z * errs.sePred,
2053
+ predUpper: yh + z * errs.sePred
2054
+ });
2055
+ }
2056
+ return out;
2057
+ }
2058
+ return {
2059
+ coef: [intercept, beta],
2060
+ predict,
2061
+ evaluateGrid,
2062
+ confidenceInterval
2063
+ };
2064
+ }
2065
+
2066
+ function tricube(u) {
2067
+ const uu = Math.abs(u);
2068
+ if (uu >= 1) {
2069
+ return 0;
2070
+ }
2071
+ const t = 1 - uu * uu * uu;
2072
+ return t * t * t;
2073
+ }
2074
+ function regressionLowess(data, x = d => d.x, y = d => d.y, options = {}) {
2075
+ const span = options.span || 0.3;
2076
+ const degree = options.degree === 0 ? 0 : 1;
2077
+ const iterations = options.iterations == null ? 2 : options.iterations;
2078
+ const ptsX = [];
2079
+ const ptsY = [];
1740
2080
  visitPoints(data, x, y, (dx, dy) => {
1741
- const sse = dy - predict(dx);
1742
- const sst = dy - uY;
1743
- SSE += sse * sse;
1744
- SST += sst * sst;
2081
+ ptsX.push(dx);
2082
+ ptsY.push(dy);
1745
2083
  });
1746
- return 1 - SSE / SST;
2084
+ const n = ptsX.length;
2085
+ function predictSingle(x0, robustWeights) {
2086
+ if (n === 0) {
2087
+ return 0;
2088
+ }
2089
+ const dists = [];
2090
+ for (let i = 0; i < n; i++) {
2091
+ dists.push({ idx: i, dist: Math.abs(ptsX[i] - x0) });
2092
+ }
2093
+ dists.sort((a, b) => a.dist - b.dist);
2094
+ const m = Math.max(2, Math.min(n, Math.floor(span * n)));
2095
+ const maxDist = dists[m - 1].dist || 0;
2096
+ const w = new Array(m);
2097
+ let sumw = 0;
2098
+ for (let i = 0; i < m; i++) {
2099
+ const idx = dists[i].idx;
2100
+ const u = maxDist === 0 ? 0 : dists[i].dist / maxDist;
2101
+ let wi = tricube(u);
2102
+ if (robustWeights && robustWeights[idx] != null) {
2103
+ wi *= robustWeights[idx];
2104
+ }
2105
+ w[i] = wi;
2106
+ sumw += wi;
2107
+ }
2108
+ if (sumw === 0) {
2109
+ return ptsY[dists[0].idx];
2110
+ }
2111
+ if (degree === 0) {
2112
+ let s = 0;
2113
+ for (let i = 0; i < m; i++) {
2114
+ s += w[i] * ptsY[dists[i].idx];
2115
+ }
2116
+ return s / sumw;
2117
+ }
2118
+ let sw = 0;
2119
+ let sx = 0;
2120
+ let sy = 0;
2121
+ let sxx = 0;
2122
+ let sxy = 0;
2123
+ for (let i = 0; i < m; i++) {
2124
+ const idx = dists[i].idx;
2125
+ const xi = ptsX[idx];
2126
+ const yi = ptsY[idx];
2127
+ const wi = w[i];
2128
+ sw += wi;
2129
+ sx += wi * xi;
2130
+ sy += wi * yi;
2131
+ sxx += wi * xi * xi;
2132
+ sxy += wi * xi * yi;
2133
+ }
2134
+ const meanX = sx / sw;
2135
+ const meanY = sy / sw;
2136
+ const denom = sxx - sx * meanX;
2137
+ const slope = Math.abs(denom) < 1e-12 ? 0 : (sxy - sx * meanY) / denom;
2138
+ const intercept = meanY - slope * meanX;
2139
+ return intercept + slope * x0;
2140
+ }
2141
+ function predict(x0) {
2142
+ if (Array.isArray(x0)) {
2143
+ const out = [];
2144
+ for (let i = 0; i < x0.length; i++) {
2145
+ out.push(predictSingle(x0[i]));
2146
+ }
2147
+ return out;
2148
+ }
2149
+ return predictSingle(x0);
2150
+ }
2151
+ function evaluateGrid(N) {
2152
+ const out = [];
2153
+ if (N <= 0) {
2154
+ return out;
2155
+ }
2156
+ if (n === 0) {
2157
+ return out;
2158
+ }
2159
+ let min = Infinity;
2160
+ let max = -Infinity;
2161
+ for (let i = 0; i < n; i++) {
2162
+ if (ptsX[i] < min) {
2163
+ min = ptsX[i];
2164
+ }
2165
+ if (ptsX[i] > max) {
2166
+ max = ptsX[i];
2167
+ }
2168
+ }
2169
+ if (min === max) {
2170
+ const v = predictSingle(min);
2171
+ for (let i = 0; i < N; i++) {
2172
+ out.push({ x: min, y: v });
2173
+ }
2174
+ return out;
2175
+ }
2176
+ const step = (max - min) / (N - 1);
2177
+ let robustWeights;
2178
+ for (let iter = 0; iter < iterations; iter++) {
2179
+ const fits = [];
2180
+ for (let i = 0; i < n; i++) {
2181
+ fits.push(predictSingle(ptsX[i], robustWeights));
2182
+ }
2183
+ const res = [];
2184
+ for (let i = 0; i < n; i++) {
2185
+ res.push(Math.abs(ptsY[i] - fits[i]));
2186
+ }
2187
+ const sortedRes = res.slice().sort((a, b) => a - b);
2188
+ const med = sortedRes[Math.floor(n / 2)] || 0;
2189
+ robustWeights = new Array(n);
2190
+ for (let i = 0; i < n; i++) {
2191
+ const u = med === 0 ? 0 : res[i] / (6 * med);
2192
+ const w = Math.abs(u) >= 1 ? 0 : (1 - u * u) * (1 - u * u);
2193
+ robustWeights[i] = w;
2194
+ }
2195
+ }
2196
+ for (let i = 0; i < N; i++) {
2197
+ const px = i === N - 1 ? max : min + step * i;
2198
+ out.push({ x: px, y: predictSingle(px, robustWeights) });
2199
+ }
2200
+ return out;
2201
+ }
2202
+ function confidenceInterval(N = 50, alpha = 0.05) {
2203
+ const out = [];
2204
+ if (N <= 0) {
2205
+ return out;
2206
+ }
2207
+ if (n === 0) {
2208
+ return out;
2209
+ }
2210
+ let min = Infinity;
2211
+ let max = -Infinity;
2212
+ for (let i = 0; i < n; i++) {
2213
+ if (ptsX[i] < min) {
2214
+ min = ptsX[i];
2215
+ }
2216
+ if (ptsX[i] > max) {
2217
+ max = ptsX[i];
2218
+ }
2219
+ }
2220
+ if (min === Infinity || max === -Infinity) {
2221
+ return out;
2222
+ }
2223
+ const comps = computeLinearCIComponents(data, x, y, (xx) => predictSingle(xx));
2224
+ if (comps.n === 0) {
2225
+ return out;
2226
+ }
2227
+ const z = Math.abs(invNorm(1 - alpha / 2));
2228
+ if (comps.min === comps.max) {
2229
+ const v = predictSingle(comps.min);
2230
+ const errs = stdErrorsAt(comps.min, comps);
2231
+ for (let i = 0; i < N; i++) {
2232
+ out.push({
2233
+ x: comps.min,
2234
+ mean: v,
2235
+ lower: v - z * errs.seMean,
2236
+ upper: v + z * errs.seMean,
2237
+ predLower: v - z * errs.sePred,
2238
+ predUpper: v + z * errs.sePred
2239
+ });
2240
+ }
2241
+ return out;
2242
+ }
2243
+ const step = (max - min) / (N - 1);
2244
+ for (let i = 0; i < N; i++) {
2245
+ const px = i === N - 1 ? max : min + step * i;
2246
+ const yh = predictSingle(px);
2247
+ const errs = stdErrorsAt(px, comps);
2248
+ out.push({
2249
+ x: px,
2250
+ mean: yh,
2251
+ lower: yh - z * errs.seMean,
2252
+ upper: yh + z * errs.seMean,
2253
+ predLower: yh - z * errs.sePred,
2254
+ predUpper: yh + z * errs.sePred
2255
+ });
2256
+ }
2257
+ return out;
2258
+ }
2259
+ return {
2260
+ predict,
2261
+ evaluate: predict,
2262
+ evaluateGrid,
2263
+ confidenceInterval
2264
+ };
1747
2265
  }
1748
- function regressionLinear(data, x = datum => datum.x, y = datum => datum.y) {
1749
- let X = 0;
1750
- let Y = 0;
1751
- let XY = 0;
1752
- let X2 = 0;
1753
- let n = 0;
2266
+
2267
+ function solveLinearSystem(A, b) {
2268
+ const n = b.length;
2269
+ const M = new Array(n);
2270
+ for (let i = 0; i < n; i++) {
2271
+ M[i] = A[i].slice();
2272
+ M[i].push(b[i]);
2273
+ }
2274
+ for (let k = 0; k < n; k++) {
2275
+ let maxRow = k;
2276
+ let maxVal = Math.abs(M[k][k]);
2277
+ for (let i = k + 1; i < n; i++) {
2278
+ const v = Math.abs(M[i][k]);
2279
+ if (v > maxVal) {
2280
+ maxVal = v;
2281
+ maxRow = i;
2282
+ }
2283
+ }
2284
+ if (maxRow !== k) {
2285
+ const tmp = M[k];
2286
+ M[k] = M[maxRow];
2287
+ M[maxRow] = tmp;
2288
+ }
2289
+ if (Math.abs(M[k][k]) < 1e-12) {
2290
+ const res = new Array(n).fill(0);
2291
+ return res;
2292
+ }
2293
+ for (let j = k + 1; j <= n; j++) {
2294
+ M[k][j] = M[k][j] / M[k][k];
2295
+ }
2296
+ M[k][k] = 1;
2297
+ for (let i = 0; i < n; i++) {
2298
+ if (i === k) {
2299
+ continue;
2300
+ }
2301
+ const factor = M[i][k];
2302
+ if (factor === 0) {
2303
+ continue;
2304
+ }
2305
+ for (let j = k + 1; j <= n; j++) {
2306
+ M[i][j] -= factor * M[k][j];
2307
+ }
2308
+ M[i][k] = 0;
2309
+ }
2310
+ }
2311
+ const x = new Array(n);
2312
+ for (let i = 0; i < n; i++) {
2313
+ x[i] = M[i][n];
2314
+ }
2315
+ return x;
2316
+ }
2317
+ function regressionPolynomial(data, x = d => d.x, y = d => d.y, options = {}) {
2318
+ var _a;
2319
+ let degree = (_a = options.degree) !== null && _a !== void 0 ? _a : 0;
2320
+ if (degree < 0) {
2321
+ degree = 0;
2322
+ }
2323
+ const m = degree + 1;
2324
+ const sums = new Array(2 * degree + 1).fill(0);
1754
2325
  visitPoints(data, x, y, (dx, dy) => {
1755
- ++n;
1756
- X += (dx - X) / n;
1757
- Y += (dy - Y) / n;
1758
- XY += (dx * dy - XY) / n;
1759
- X2 += (dx * dx - X2) / n;
2326
+ let xp = 1;
2327
+ for (let k = 0; k < sums.length; k++) {
2328
+ sums[k] += xp;
2329
+ xp *= dx;
2330
+ }
1760
2331
  });
1761
- const coef = ordinaryLeastSquares(X, Y, XY, X2);
1762
- const predict = (x) => coef[0] + coef[1] * x;
2332
+ const A = new Array(m);
2333
+ for (let i = 0; i < m; i++) {
2334
+ A[i] = new Array(m).fill(0);
2335
+ for (let j = 0; j < m; j++) {
2336
+ A[i][j] = sums[i + j];
2337
+ }
2338
+ }
2339
+ const B = new Array(m).fill(0);
2340
+ visitPoints(data, x, y, (dx, dy) => {
2341
+ let xp = 1;
2342
+ for (let k = 0; k < m; k++) {
2343
+ B[k] += dy * xp;
2344
+ xp *= dx;
2345
+ }
2346
+ });
2347
+ const coef = solveLinearSystem(A, B);
2348
+ const predict = (xx) => {
2349
+ let xp = 1;
2350
+ let v = 0;
2351
+ for (let k = 0; k < coef.length; k++) {
2352
+ v += coef[k] * xp;
2353
+ xp *= xx;
2354
+ }
2355
+ return v;
2356
+ };
2357
+ return {
2358
+ degree,
2359
+ coef,
2360
+ predict,
2361
+ rSquared: rSquared(data, x, y, (() => {
2362
+ let sum = 0;
2363
+ let cnt = 0;
2364
+ visitPoints(data, x, y, (_dx, dy) => {
2365
+ sum += dy;
2366
+ cnt++;
2367
+ });
2368
+ return cnt === 0 ? 0 : sum / cnt;
2369
+ })(), predict),
2370
+ evaluateGrid(N) {
2371
+ const out = [];
2372
+ if (N <= 0) {
2373
+ return out;
2374
+ }
2375
+ let min = Infinity;
2376
+ let max = -Infinity;
2377
+ visitPoints(data, x, y, dx => {
2378
+ if (!isNil(dx)) {
2379
+ if (dx < min) {
2380
+ min = dx;
2381
+ }
2382
+ if (dx > max) {
2383
+ max = dx;
2384
+ }
2385
+ }
2386
+ });
2387
+ if (min === Infinity || max === -Infinity) {
2388
+ return out;
2389
+ }
2390
+ if (min === max) {
2391
+ const v = predict(min);
2392
+ for (let i = 0; i < N; i++) {
2393
+ out.push({ x: min, y: v });
2394
+ }
2395
+ return out;
2396
+ }
2397
+ const step = (max - min) / (N - 1);
2398
+ for (let i = 0; i < N; i++) {
2399
+ const px = i === N - 1 ? max : min + step * i;
2400
+ out.push({ x: px, y: predict(px) });
2401
+ }
2402
+ return out;
2403
+ },
2404
+ confidenceInterval(N = 50, alpha = 0.05) {
2405
+ const out = [];
2406
+ if (N <= 0) {
2407
+ return out;
2408
+ }
2409
+ const comps = computeLinearCIComponents(data, x, y, predict);
2410
+ if (comps.n === 0) {
2411
+ return out;
2412
+ }
2413
+ const z = Math.abs(invNorm(1 - alpha / 2));
2414
+ if (comps.min === comps.max) {
2415
+ const v = predict(comps.min);
2416
+ const errs = stdErrorsAt(comps.min, comps);
2417
+ for (let i = 0; i < N; i++) {
2418
+ out.push({
2419
+ x: comps.min,
2420
+ mean: v,
2421
+ lower: v - z * errs.seMean,
2422
+ upper: v + z * errs.seMean,
2423
+ predLower: v - z * errs.sePred,
2424
+ predUpper: v + z * errs.sePred
2425
+ });
2426
+ }
2427
+ return out;
2428
+ }
2429
+ const step = (comps.max - comps.min) / (N - 1);
2430
+ for (let i = 0; i < N; i++) {
2431
+ const px = i === N - 1 ? comps.max : comps.min + step * i;
2432
+ const yh = predict(px);
2433
+ const errs = stdErrorsAt(px, comps);
2434
+ out.push({
2435
+ x: px,
2436
+ mean: yh,
2437
+ lower: yh - z * errs.seMean,
2438
+ upper: yh + z * errs.seMean,
2439
+ predLower: yh - z * errs.sePred,
2440
+ predUpper: yh + z * errs.sePred
2441
+ });
2442
+ }
2443
+ return out;
2444
+ }
2445
+ };
2446
+ }
2447
+
2448
+ const gaussian = (u) => {
2449
+ const invSqrt2Pi = 1 / Math.sqrt(2 * Math.PI);
2450
+ return invSqrt2Pi * Math.exp(-0.5 * u * u);
2451
+ };
2452
+ const epanechnikov = (u) => {
2453
+ const absu = Math.abs(u);
2454
+ return absu <= 1 ? 0.75 * (1 - u * u) : 0;
2455
+ };
2456
+ function scott(n, std, dim = 1) {
2457
+ if (n <= 0 || std === 0) {
2458
+ return 0;
2459
+ }
2460
+ return std * Math.pow(n, -1 / (dim + 4));
2461
+ }
2462
+ function silverman(n, std, dim = 1) {
2463
+ if (n <= 0 || std === 0) {
2464
+ return 0;
2465
+ }
2466
+ const factor = Math.pow(4 / (dim + 2), 1 / (dim + 4));
2467
+ return factor * std * Math.pow(n, -1 / (dim + 4));
2468
+ }
2469
+ function std(values) {
2470
+ const n = values.length;
2471
+ if (n === 0) {
2472
+ return 0;
2473
+ }
2474
+ let mean = 0;
2475
+ for (let i = 0; i < n; i++) {
2476
+ mean += values[i];
2477
+ }
2478
+ mean /= n;
2479
+ let s = 0;
2480
+ for (let i = 0; i < n; i++) {
2481
+ const d = values[i] - mean;
2482
+ s += d * d;
2483
+ }
2484
+ return Math.sqrt(s / n);
2485
+ }
2486
+ function kde(data, options = {}) {
2487
+ const n = data.length;
2488
+ const kernel = options.kernel || gaussian;
2489
+ let h = options.bandwidth;
2490
+ if (!h || h <= 0) {
2491
+ const sd = std(data) || 0;
2492
+ const method = options.bandwidthMethod || 'scott';
2493
+ if (method === 'silverman') {
2494
+ h = silverman(n, sd, 1);
2495
+ }
2496
+ else {
2497
+ h = scott(n, sd, 1);
2498
+ }
2499
+ }
2500
+ if (!h || h <= 0) {
2501
+ const zerosEval = (x) => {
2502
+ if (Array.isArray(x)) {
2503
+ const out = [];
2504
+ for (let i = 0; i < x.length; i++) {
2505
+ out.push(0);
2506
+ }
2507
+ return out;
2508
+ }
2509
+ return 0;
2510
+ };
2511
+ const zerosGrid = (N) => {
2512
+ const out = [];
2513
+ if (N <= 0) {
2514
+ return out;
2515
+ }
2516
+ let min = Infinity;
2517
+ let max = -Infinity;
2518
+ for (let j = 0; j < n; j++) {
2519
+ const v = data[j];
2520
+ if (v < min) {
2521
+ min = v;
2522
+ }
2523
+ if (v > max) {
2524
+ max = v;
2525
+ }
2526
+ }
2527
+ if (min === Infinity || max === -Infinity) {
2528
+ for (let i = 0; i < N; i++) {
2529
+ out.push({ x: 0, y: 0 });
2530
+ }
2531
+ return out;
2532
+ }
2533
+ for (let i = 0; i < N; i++) {
2534
+ out.push({ x: min, y: 0 });
2535
+ }
2536
+ return out;
2537
+ };
2538
+ return {
2539
+ bandwidth: 0,
2540
+ kernel,
2541
+ evaluate: zerosEval,
2542
+ evaluateGrid: zerosGrid
2543
+ };
2544
+ }
2545
+ const invNh = 1 / (n * h);
2546
+ function evalPoint(x) {
2547
+ let sum = 0;
2548
+ for (let j = 0; j < n; j++) {
2549
+ sum += kernel((x - data[j]) / h);
2550
+ }
2551
+ return sum * invNh;
2552
+ }
2553
+ function evaluate(x) {
2554
+ if (Array.isArray(x)) {
2555
+ const out = [];
2556
+ for (let i = 0; i < x.length; i++) {
2557
+ out.push(evalPoint(x[i]));
2558
+ }
2559
+ return out;
2560
+ }
2561
+ return evalPoint(x);
2562
+ }
2563
+ return {
2564
+ bandwidth: h,
2565
+ kernel,
2566
+ evaluate: evaluate,
2567
+ evaluateGrid(N) {
2568
+ const out = [];
2569
+ if (N <= 0) {
2570
+ return out;
2571
+ }
2572
+ let min = Infinity;
2573
+ let max = -Infinity;
2574
+ for (let i = 0; i < n; i++) {
2575
+ const v = data[i];
2576
+ if (v < min) {
2577
+ min = v;
2578
+ }
2579
+ if (v > max) {
2580
+ max = v;
2581
+ }
2582
+ }
2583
+ if (min === Infinity || max === -Infinity) {
2584
+ return out;
2585
+ }
2586
+ if (min === max) {
2587
+ for (let i = 0; i < N; i++) {
2588
+ out.push({ x: min, y: evalPoint(min) });
2589
+ }
2590
+ return out;
2591
+ }
2592
+ const step = (max - min) / (N - 1);
2593
+ for (let i = 0; i < N; i++) {
2594
+ const x = i === N - 1 ? max : min + step * i;
2595
+ out.push({ x, y: evalPoint(x) });
2596
+ }
2597
+ return out;
2598
+ }
2599
+ };
2600
+ }
2601
+
2602
+ function ecdf(data) {
2603
+ const n = data.length;
2604
+ const sorted = data.slice().sort((a, b) => a - b);
2605
+ function evaluateSingle(x) {
2606
+ if (n === 0) {
2607
+ return 0;
2608
+ }
2609
+ let lo = 0;
2610
+ let hi = n;
2611
+ while (lo < hi) {
2612
+ const mid = (lo + hi) >>> 1;
2613
+ if (sorted[mid] <= x) {
2614
+ lo = mid + 1;
2615
+ }
2616
+ else {
2617
+ hi = mid;
2618
+ }
2619
+ }
2620
+ return lo / n;
2621
+ }
2622
+ function evaluate(x) {
2623
+ if (Array.isArray(x)) {
2624
+ const out = [];
2625
+ for (let i = 0; i < x.length; i++) {
2626
+ out.push(evaluateSingle(x[i]));
2627
+ }
2628
+ return out;
2629
+ }
2630
+ return evaluateSingle(x);
2631
+ }
2632
+ function evaluateGrid(N) {
2633
+ const out = [];
2634
+ if (N <= 0) {
2635
+ return out;
2636
+ }
2637
+ if (n === 0) {
2638
+ return out;
2639
+ }
2640
+ const min = sorted[0];
2641
+ const max = sorted[n - 1];
2642
+ if (min === max) {
2643
+ for (let i = 0; i < N; i++) {
2644
+ out.push({ x: min, y: 1 });
2645
+ }
2646
+ return out;
2647
+ }
2648
+ const step = (max - min) / (N - 1);
2649
+ for (let i = 0; i < N; i++) {
2650
+ const x = i === N - 1 ? max : min + step * i;
2651
+ out.push({ x, y: evaluateSingle(x) });
2652
+ }
2653
+ return out;
2654
+ }
1763
2655
  return {
1764
- coef: coef,
1765
- predict: predict,
1766
- rSquared: rSquared(data, x, y, Y, predict)
2656
+ evaluate: evaluate,
2657
+ evaluateGrid,
2658
+ n
1767
2659
  };
1768
2660
  }
1769
2661
 
@@ -6384,6 +7276,8 @@
6384
7276
  exports.deviation = deviation;
6385
7277
  exports.dotProduct = dotProduct;
6386
7278
  exports.eastAsianCharacterInfo = eastAsianCharacterInfo;
7279
+ exports.ecdf = ecdf;
7280
+ exports.epanechnikov = epanechnikov;
6387
7281
  exports.epsilon = epsilon;
6388
7282
  exports.exponent = exponent;
6389
7283
  exports.extent = extent;
@@ -6400,6 +7294,7 @@
6400
7294
  exports.fullYearSetterName = fullYearSetterName;
6401
7295
  exports.fuzzyEqualNumber = fuzzyEqualNumber;
6402
7296
  exports.fuzzyEqualVec = fuzzyEqualVec;
7297
+ exports.gaussian = gaussian;
6403
7298
  exports.gemv = gemv;
6404
7299
  exports.generateCeil = generateCeil;
6405
7300
  exports.generateCount = generateCount;
@@ -6474,6 +7369,7 @@
6474
7369
  exports.isValid = isValid;
6475
7370
  exports.isValidNumber = isValidNumber;
6476
7371
  exports.isValidUrl = isValidUrl;
7372
+ exports.kde = kde;
6477
7373
  exports.keys = keys;
6478
7374
  exports.last = last;
6479
7375
  exports.lengthFromPointToLine = lengthFromPointToLine;
@@ -6539,10 +7435,14 @@
6539
7435
  exports.range = range;
6540
7436
  exports.rectInsideAnotherRect = rectInsideAnotherRect;
6541
7437
  exports.regressionLinear = regressionLinear;
7438
+ exports.regressionLogistic = regressionLogistic;
7439
+ exports.regressionLowess = regressionLowess;
7440
+ exports.regressionPolynomial = regressionPolynomial;
6542
7441
  exports.rgbToHex = rgbToHex;
6543
7442
  exports.rgbToHsl = rgbToHsl;
6544
7443
  exports.rotatePoint = rotatePoint;
6545
7444
  exports.scale = scale;
7445
+ exports.scott = scott;
6546
7446
  exports.secondCount = secondCount;
6547
7447
  exports.secondField = secondField;
6548
7448
  exports.secondFloor = secondFloor;
@@ -6551,6 +7451,7 @@
6551
7451
  exports.secondsSetterName = secondsSetterName;
6552
7452
  exports.seedRandom = seedRandom;
6553
7453
  exports.shuffleArray = shuffleArray;
7454
+ exports.silverman = silverman;
6554
7455
  exports.simpleField = simpleField;
6555
7456
  exports.sin = sin;
6556
7457
  exports.span = span;