@visactor/vutils 1.0.19 → 1.0.21
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.
- package/cjs/common/regression-lowess.d.ts +1 -0
- package/cjs/common/regression-lowess.js +57 -39
- package/cjs/common/regression-lowess.js.map +1 -1
- package/dist/index.js +94 -70
- package/dist/index.min.js +1 -1
- package/es/common/regression-lowess.d.ts +1 -0
- package/es/common/regression-lowess.js +57 -39
- package/es/common/regression-lowess.js.map +1 -1
- package/package.json +2 -2
|
@@ -13,38 +13,60 @@ function tricube(u) {
|
|
|
13
13
|
return t * t * t;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function stratifiedSample(sortedData, maxSamples) {
|
|
17
|
+
const n = sortedData.length;
|
|
18
|
+
if (n <= maxSamples) return sortedData;
|
|
19
|
+
const sampled = [], step = n / maxSamples;
|
|
20
|
+
for (let i = 0; i < maxSamples; i++) {
|
|
21
|
+
const idx = Math.min(Math.floor(i * step), n - 1);
|
|
22
|
+
sampled.push(sortedData[idx]);
|
|
23
|
+
}
|
|
24
|
+
return sampled;
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
function regressionLowess(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
17
28
|
var _a;
|
|
18
|
-
const span = options.span || .3, degree = 0 === options.degree ? 0 : 1, alpha = null !== (_a =
|
|
29
|
+
const span = options.span || .3, degree = 0 === options.degree ? 0 : 1, alpha = null !== (_a = options.alpha) && void 0 !== _a ? _a : .05, iterations = null == options.iterations ? 2 : options.iterations, maxSamples = options.maxSamples || 1e3, rawPoints = [];
|
|
19
30
|
(0, regression_linear_1.visitPoints)(data, x, y, ((dx, dy) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
rawPoints.push({
|
|
32
|
+
x: dx,
|
|
33
|
+
y: dy
|
|
34
|
+
});
|
|
35
|
+
})), rawPoints.sort(((a, b) => a.x - b.x));
|
|
36
|
+
const sampledPoints = stratifiedSample(rawPoints, maxSamples), n = sampledPoints.length, ptsX = new Array(n), ptsY = new Array(n);
|
|
37
|
+
for (let i = 0; i < n; i++) ptsX[i] = sampledPoints[i].x, ptsY[i] = sampledPoints[i].y;
|
|
23
38
|
function predictSingle(x0, robustWeights) {
|
|
24
39
|
if (0 === n) return 0;
|
|
25
|
-
|
|
26
|
-
for (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
let left = 0, right = n;
|
|
41
|
+
for (;left < right; ) {
|
|
42
|
+
const mid = left + right >> 1;
|
|
43
|
+
ptsX[mid] < x0 ? left = mid + 1 : right = mid;
|
|
44
|
+
}
|
|
45
|
+
const m = Math.max(2, Math.min(n, Math.floor(span * n))), start = Math.max(0, left - Math.floor(m / 2)), end = Math.min(n, start + m), actualStart = Math.max(0, end - m);
|
|
46
|
+
let maxDist = 0;
|
|
47
|
+
const windowSize = end - actualStart, distances = new Array(windowSize);
|
|
48
|
+
for (let i = actualStart; i < end; i++) {
|
|
49
|
+
const dist = Math.abs(ptsX[i] - x0);
|
|
50
|
+
distances[i - actualStart] = dist, dist > maxDist && (maxDist = dist);
|
|
51
|
+
}
|
|
32
52
|
let sumw = 0;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
let wi = tricube(0 === maxDist ? 0 :
|
|
36
|
-
robustWeights && null != robustWeights[
|
|
37
|
-
sumw += wi;
|
|
53
|
+
const w = new Array(windowSize);
|
|
54
|
+
for (let i = 0; i < windowSize; i++) {
|
|
55
|
+
let wi = tricube(0 === maxDist ? 0 : distances[i] / maxDist);
|
|
56
|
+
robustWeights && null != robustWeights[actualStart + i] && (wi *= robustWeights[actualStart + i]),
|
|
57
|
+
w[i] = wi, sumw += wi;
|
|
58
|
+
}
|
|
59
|
+
if (0 === sumw) {
|
|
60
|
+
return ptsY[left < n ? left : n - 1];
|
|
38
61
|
}
|
|
39
|
-
if (0 === sumw) return ptsY[dists[0].idx];
|
|
40
62
|
if (0 === degree) {
|
|
41
63
|
let s = 0;
|
|
42
|
-
for (let i = 0; i <
|
|
64
|
+
for (let i = 0; i < w.length; i++) s += w[i] * ptsY[actualStart + i];
|
|
43
65
|
return s / sumw;
|
|
44
66
|
}
|
|
45
67
|
let sw = 0, sx = 0, sy = 0, sxx = 0, sxy = 0;
|
|
46
|
-
for (let i =
|
|
47
|
-
const idx =
|
|
68
|
+
for (let i = actualStart; i < end; i++) {
|
|
69
|
+
const idx = i - actualStart, xi = ptsX[i], yi = ptsY[i], wi = w[idx];
|
|
48
70
|
sw += wi, sx += wi * xi, sy += wi * yi, sxx += wi * xi * xi, sxy += wi * xi * yi;
|
|
49
71
|
}
|
|
50
72
|
const meanX = sx / sw, meanY = sy / sw, denom = sxx - sx * meanX, slope = Math.abs(denom) < 1e-12 ? 0 : (sxy - sx * meanY) / denom;
|
|
@@ -52,8 +74,8 @@ function regressionLowess(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
|
52
74
|
}
|
|
53
75
|
function predict(x0) {
|
|
54
76
|
if (Array.isArray(x0)) {
|
|
55
|
-
const out =
|
|
56
|
-
for (let i = 0; i <
|
|
77
|
+
const len = x0.length, out = new Array(len);
|
|
78
|
+
for (let i = 0; i < len; i++) out[i] = predictSingle(x0[i]);
|
|
57
79
|
return out;
|
|
58
80
|
}
|
|
59
81
|
return predictSingle(x0);
|
|
@@ -62,26 +84,23 @@ function regressionLowess(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
|
62
84
|
predict: predict,
|
|
63
85
|
evaluate: predict,
|
|
64
86
|
evaluateGrid: function(N) {
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
let min = 1 / 0, max = -1 / 0;
|
|
69
|
-
for (let i = 0; i < n; i++) ptsX[i] < min && (min = ptsX[i]), ptsX[i] > max && (max = ptsX[i]);
|
|
87
|
+
if (N <= 0) return [];
|
|
88
|
+
if (0 === n) return [];
|
|
89
|
+
const out = new Array(N), min = ptsX[0], max = ptsX[n - 1];
|
|
70
90
|
if (min === max) {
|
|
71
91
|
const v = predictSingle(min);
|
|
72
|
-
for (let i = 0; i < N; i++) out
|
|
92
|
+
for (let i = 0; i < N; i++) out[i] = {
|
|
73
93
|
x: min,
|
|
74
94
|
y: v
|
|
75
|
-
}
|
|
95
|
+
};
|
|
76
96
|
return out;
|
|
77
97
|
}
|
|
78
98
|
const step = (max - min) / (N - 1);
|
|
79
99
|
let robustWeights;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
for (let i = 0; i < n; i++) res.push(Math.abs(ptsY[i] - fits[i]));
|
|
100
|
+
const effectiveIterations = null != options.iterations ? iterations : n > 500 ? 0 : iterations;
|
|
101
|
+
if (effectiveIterations > 0) for (let iter = 0; iter < effectiveIterations; iter++) {
|
|
102
|
+
const fits = new Array(n), res = new Array(n);
|
|
103
|
+
for (let i = 0; i < n; i++) fits[i] = predictSingle(ptsX[i], robustWeights), res[i] = Math.abs(ptsY[i] - fits[i]);
|
|
85
104
|
const med = res.slice().sort(((a, b) => a - b))[Math.floor(n / 2)] || 0;
|
|
86
105
|
robustWeights = new Array(n);
|
|
87
106
|
for (let i = 0; i < n; i++) {
|
|
@@ -91,10 +110,10 @@ function regressionLowess(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
|
91
110
|
}
|
|
92
111
|
for (let i = 0; i < N; i++) {
|
|
93
112
|
const px = i === N - 1 ? max : min + step * i;
|
|
94
|
-
out
|
|
113
|
+
out[i] = {
|
|
95
114
|
x: px,
|
|
96
115
|
y: predictSingle(px, robustWeights)
|
|
97
|
-
}
|
|
116
|
+
};
|
|
98
117
|
}
|
|
99
118
|
return out;
|
|
100
119
|
},
|
|
@@ -102,9 +121,8 @@ function regressionLowess(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
|
102
121
|
const out = [];
|
|
103
122
|
if (N <= 0) return out;
|
|
104
123
|
if (0 === n) return out;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (min === 1 / 0 || max === -1 / 0) return out;
|
|
124
|
+
const min = ptsX[0], max = ptsX[n - 1];
|
|
125
|
+
if (void 0 === min || void 0 === max || min === 1 / 0 || max === -1 / 0) return out;
|
|
108
126
|
const comps = (0, regression_utils_1.computeLinearCIComponents)(data, x, y, (xx => predictSingle(xx)));
|
|
109
127
|
if (0 === comps.n) return out;
|
|
110
128
|
const z = Math.abs((0, regression_utils_1.invNorm)(1 - alpha / 2));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/common/regression-lowess.ts"],"names":[],"mappings":"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","file":"regression-lowess.js","sourcesContent":["import { visitPoints } from './regression-linear';\nimport { computeLinearCIComponents, invNorm, stdErrorsAt } from './regression-utils';\n\nfunction tricube(u: number) {\n const uu = Math.abs(u);\n if (uu >= 1) {\n return 0;\n }\n const t = 1 - uu * uu * uu;\n return t * t * t;\n}\n\n/**\n * Simple lowess implementation (univariate x)\n * options:\n * - span: fraction of points used in local regression (0,1]\n * - degree: 0 (constant) or 1 (linear)\n * - iterations: number of robustifying iterations\n */\nexport function regressionLowess(\n data: any[],\n x: (d: any) => number = d => d.x,\n y: (d: any) => number = d => d.y,\n options: { span?: number; degree?: 1 | 0; iterations?: number; alpha?: number } = {}\n) {\n const span = options.span || 0.3;\n const degree = options.degree === 0 ? 0 : 1;\n const alpha = options?.alpha ?? 0.05;\n const iterations = options.iterations == null ? 2 : options.iterations;\n\n const ptsX: number[] = [];\n const ptsY: number[] = [];\n visitPoints(data, x, y, (dx, dy) => {\n ptsX.push(dx);\n ptsY.push(dy);\n });\n\n const n = ptsX.length;\n function predictSingle(x0: number, robustWeights?: number[]) {\n if (n === 0) {\n return 0;\n }\n // compute distances and select nearest m points\n const dists: { idx: number; dist: number }[] = [];\n for (let i = 0; i < n; i++) {\n dists.push({ idx: i, dist: Math.abs(ptsX[i] - x0) });\n }\n dists.sort((a, b) => a.dist - b.dist);\n const m = Math.max(2, Math.min(n, Math.floor(span * n)));\n const maxDist = dists[m - 1].dist || 0;\n\n // compute weights\n const w: number[] = new Array(m);\n let sumw = 0;\n for (let i = 0; i < m; i++) {\n const idx = dists[i].idx;\n const u = maxDist === 0 ? 0 : dists[i].dist / maxDist;\n let wi = tricube(u);\n if (robustWeights && robustWeights[idx] != null) {\n wi *= robustWeights[idx];\n }\n w[i] = wi;\n sumw += wi;\n }\n\n if (sumw === 0) {\n // fallback to nearest y\n return ptsY[dists[0].idx];\n }\n\n if (degree === 0) {\n let s = 0;\n for (let i = 0; i < m; i++) {\n s += w[i] * ptsY[dists[i].idx];\n }\n return s / sumw;\n }\n\n // weighted linear regression on local points\n let sw = 0;\n let sx = 0;\n let sy = 0;\n let sxx = 0;\n let sxy = 0;\n for (let i = 0; i < m; i++) {\n const idx = dists[i].idx;\n const xi = ptsX[idx];\n const yi = ptsY[idx];\n const wi = w[i];\n sw += wi;\n sx += wi * xi;\n sy += wi * yi;\n sxx += wi * xi * xi;\n sxy += wi * xi * yi;\n }\n\n const meanX = sx / sw;\n const meanY = sy / sw;\n const denom = sxx - sx * meanX;\n const slope = Math.abs(denom) < 1e-12 ? 0 : (sxy - sx * meanY) / denom;\n const intercept = meanY - slope * meanX;\n return intercept + slope * x0;\n }\n\n function predict(x0: number | number[]) {\n if (Array.isArray(x0)) {\n const out: number[] = [];\n for (let i = 0; i < x0.length; i++) {\n out.push(predictSingle(x0[i]));\n }\n return out;\n }\n return predictSingle(x0 as number);\n }\n\n function evaluateGrid(N: number) {\n const out: { x: number; y: number }[] = [];\n if (N <= 0) {\n return out;\n }\n if (n === 0) {\n return out;\n }\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < n; i++) {\n if (ptsX[i] < min) {\n min = ptsX[i];\n }\n if (ptsX[i] > max) {\n max = ptsX[i];\n }\n }\n if (min === max) {\n const v = predictSingle(min);\n for (let i = 0; i < N; i++) {\n out.push({ x: min, y: v });\n }\n return out;\n }\n const step = (max - min) / (N - 1);\n\n // optionally add robust iterations\n let robustWeights: number[] | undefined;\n for (let iter = 0; iter < iterations; iter++) {\n // compute fits\n const fits: number[] = [];\n for (let i = 0; i < n; i++) {\n fits.push(predictSingle(ptsX[i], robustWeights));\n }\n // compute residuals\n const res: number[] = [];\n for (let i = 0; i < n; i++) {\n res.push(Math.abs(ptsY[i] - fits[i]));\n }\n // median absolute deviation\n const sortedRes = res.slice().sort((a, b) => a - b);\n const med = sortedRes[Math.floor(n / 2)] || 0;\n robustWeights = new Array(n);\n for (let i = 0; i < n; i++) {\n const u = med === 0 ? 0 : res[i] / (6 * med);\n const w = Math.abs(u) >= 1 ? 0 : (1 - u * u) * (1 - u * u);\n robustWeights[i] = w;\n }\n }\n\n for (let i = 0; i < N; i++) {\n const px = i === N - 1 ? max : min + step * i;\n out.push({ x: px, y: predictSingle(px, robustWeights) });\n }\n return out;\n }\n\n function confidenceInterval(N: number = 50) {\n const out: { x: number; mean: number; lower: number; upper: number; predLower: number; predUpper: number }[] = [];\n\n if (N <= 0) {\n return out;\n }\n if (n === 0) {\n return out;\n }\n\n // use data x-range\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < n; i++) {\n if (ptsX[i] < min) {\n min = ptsX[i];\n }\n if (ptsX[i] > max) {\n max = ptsX[i];\n }\n }\n if (min === Infinity || max === -Infinity) {\n return out;\n }\n\n const comps = computeLinearCIComponents(data, x, y, (xx: number) => predictSingle(xx));\n if (comps.n === 0) {\n return out;\n }\n\n const z = Math.abs(invNorm(1 - alpha / 2));\n if (comps.min === comps.max) {\n const v = predictSingle(comps.min);\n const errs = stdErrorsAt(comps.min, comps);\n for (let i = 0; i < N; i++) {\n out.push({\n x: comps.min,\n mean: v,\n lower: v - z * errs.seMean,\n upper: v + z * errs.seMean,\n predLower: v - z * errs.sePred,\n predUpper: v + z * errs.sePred\n });\n }\n return out;\n }\n\n const step = (max - min) / (N - 1);\n for (let i = 0; i < N; i++) {\n const px = i === N - 1 ? max : min + step * i;\n const yh = predictSingle(px);\n const errs = stdErrorsAt(px, comps);\n out.push({\n x: px,\n mean: yh,\n lower: yh - z * errs.seMean,\n upper: yh + z * errs.seMean,\n predLower: yh - z * errs.sePred,\n predUpper: yh + z * errs.sePred\n });\n }\n return out;\n }\n\n return {\n predict,\n evaluate: predict as any,\n evaluateGrid,\n confidenceInterval\n };\n}\n\nexport default regressionLowess;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/common/regression-lowess.ts"],"names":[],"mappings":"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","file":"regression-lowess.js","sourcesContent":["import { visitPoints } from './regression-linear';\nimport { computeLinearCIComponents, invNorm, stdErrorsAt } from './regression-utils';\n\nfunction tricube(u: number) {\n const uu = Math.abs(u);\n if (uu >= 1) {\n return 0;\n }\n const t = 1 - uu * uu * uu;\n return t * t * t;\n}\n\n/**\n * Stratified sampling to reduce data size while preserving distribution\n */\nfunction stratifiedSample(sortedData: { x: number; y: number }[], maxSamples: number) {\n const n = sortedData.length;\n if (n <= maxSamples) {\n return sortedData;\n }\n\n const sampled: { x: number; y: number }[] = [];\n\n // More aggressive sampling - use exact step size\n const step = n / maxSamples;\n\n for (let i = 0; i < maxSamples; i++) {\n const idx = Math.min(Math.floor(i * step), n - 1);\n sampled.push(sortedData[idx]);\n }\n\n return sampled;\n}\n\n/**\n * Simple lowess implementation (univariate x)\n * options:\n * - span: fraction of points used in local regression (0,1]\n * - degree: 0 (constant) or 1 (linear)\n * - iterations: number of robustifying iterations\n * - alpha: confidence level for CI\n * - maxSamples: maximum number of points to use (default: 1000 for fast processing)\n */\nexport function regressionLowess(\n data: any[],\n x: (d: any) => number = d => d.x,\n y: (d: any) => number = d => d.y,\n options: { span?: number; degree?: 1 | 0; iterations?: number; alpha?: number; maxSamples?: number } = {}\n) {\n const span = options.span || 0.3;\n const degree = options.degree === 0 ? 0 : 1;\n const alpha = options.alpha ?? 0.05;\n const iterations = options.iterations == null ? 2 : options.iterations;\n const maxSamples = options.maxSamples || 1000;\n\n // Collect and sort data by x\n const rawPoints: { x: number; y: number }[] = [];\n visitPoints(data, x, y, (dx, dy) => {\n rawPoints.push({ x: dx, y: dy });\n });\n\n rawPoints.sort((a, b) => a.x - b.x);\n\n // Apply sampling if needed\n const sampledPoints = stratifiedSample(rawPoints, maxSamples);\n\n const n = sampledPoints.length;\n const ptsX: number[] = new Array(n);\n const ptsY: number[] = new Array(n);\n\n for (let i = 0; i < n; i++) {\n ptsX[i] = sampledPoints[i].x;\n ptsY[i] = sampledPoints[i].y;\n }\n\n /**\n * Optimized predictSingle using binary search on pre-sorted data\n */\n function predictSingle(x0: number, robustWeights?: number[]) {\n if (n === 0) {\n return 0;\n }\n\n // Binary search to find insertion point\n let left = 0;\n let right = n;\n while (left < right) {\n const mid = (left + right) >> 1;\n if (ptsX[mid] < x0) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n const m = Math.max(2, Math.min(n, Math.floor(span * n)));\n\n // Calculate range around insertion point\n const start = Math.max(0, left - Math.floor(m / 2));\n const end = Math.min(n, start + m);\n const actualStart = Math.max(0, end - m);\n\n // Find max distance and compute weights in single pass\n let maxDist = 0;\n const windowSize = end - actualStart;\n const distances: number[] = new Array(windowSize);\n\n for (let i = actualStart; i < end; i++) {\n const dist = Math.abs(ptsX[i] - x0);\n distances[i - actualStart] = dist;\n if (dist > maxDist) {\n maxDist = dist;\n }\n }\n\n // Compute weights using pre-calculated distances\n let sumw = 0;\n const w: number[] = new Array(windowSize);\n for (let i = 0; i < windowSize; i++) {\n const u = maxDist === 0 ? 0 : distances[i] / maxDist;\n let wi = tricube(u);\n if (robustWeights && robustWeights[actualStart + i] != null) {\n wi *= robustWeights[actualStart + i];\n }\n w[i] = wi;\n sumw += wi;\n }\n\n if (sumw === 0) {\n // fallback to nearest y\n const nearestIdx = left < n ? left : n - 1;\n return ptsY[nearestIdx];\n }\n\n if (degree === 0) {\n let s = 0;\n for (let i = 0; i < w.length; i++) {\n s += w[i] * ptsY[actualStart + i];\n }\n return s / sumw;\n }\n\n // weighted linear regression on local points\n let sw = 0;\n let sx = 0;\n let sy = 0;\n let sxx = 0;\n let sxy = 0;\n for (let i = actualStart; i < end; i++) {\n const idx = i - actualStart;\n const xi = ptsX[i];\n const yi = ptsY[i];\n const wi = w[idx];\n sw += wi;\n sx += wi * xi;\n sy += wi * yi;\n sxx += wi * xi * xi;\n sxy += wi * xi * yi;\n }\n\n const meanX = sx / sw;\n const meanY = sy / sw;\n const denom = sxx - sx * meanX;\n const slope = Math.abs(denom) < 1e-12 ? 0 : (sxy - sx * meanY) / denom;\n const intercept = meanY - slope * meanX;\n return intercept + slope * x0;\n }\n\n function predict(x0: number | number[]) {\n if (Array.isArray(x0)) {\n const len = x0.length;\n const out: number[] = new Array(len);\n for (let i = 0; i < len; i++) {\n out[i] = predictSingle(x0[i]);\n }\n return out;\n }\n return predictSingle(x0 as number);\n }\n\n function evaluateGrid(N: number) {\n if (N <= 0) {\n return [];\n }\n if (n === 0) {\n return [];\n }\n\n const out: { x: number; y: number }[] = new Array(N);\n const min = ptsX[0];\n const max = ptsX[n - 1];\n\n if (min === max) {\n const v = predictSingle(min);\n for (let i = 0; i < N; i++) {\n out[i] = { x: min, y: v };\n }\n return out;\n }\n const step = (max - min) / (N - 1);\n\n // optionally add robust iterations\n let robustWeights: number[] | undefined;\n\n // Disable robustness iterations for large datasets to improve performance\n // Users can override by setting iterations explicitly\n const effectiveIterations = options.iterations != null ? iterations : n > 500 ? 0 : iterations;\n\n if (effectiveIterations > 0) {\n for (let iter = 0; iter < effectiveIterations; iter++) {\n // compute fits - pre-allocate arrays\n const fits: number[] = new Array(n);\n const res: number[] = new Array(n);\n\n for (let i = 0; i < n; i++) {\n fits[i] = predictSingle(ptsX[i], robustWeights);\n res[i] = Math.abs(ptsY[i] - fits[i]);\n }\n\n // median absolute deviation\n const sortedRes = res.slice().sort((a, b) => a - b);\n const med = sortedRes[Math.floor(n / 2)] || 0;\n robustWeights = new Array(n);\n for (let i = 0; i < n; i++) {\n const u = med === 0 ? 0 : res[i] / (6 * med);\n const w = Math.abs(u) >= 1 ? 0 : (1 - u * u) * (1 - u * u);\n robustWeights[i] = w;\n }\n }\n }\n\n for (let i = 0; i < N; i++) {\n const px = i === N - 1 ? max : min + step * i;\n out[i] = { x: px, y: predictSingle(px, robustWeights) };\n }\n return out;\n }\n\n function confidenceInterval(N: number = 50) {\n const out: { x: number; mean: number; lower: number; upper: number; predLower: number; predUpper: number }[] = [];\n\n if (N <= 0) {\n return out;\n }\n if (n === 0) {\n return out;\n }\n\n // use data x-range (already sorted)\n const min = ptsX[0];\n const max = ptsX[n - 1];\n\n if (min === undefined || max === undefined || min === Infinity || max === -Infinity) {\n return out;\n }\n\n const comps = computeLinearCIComponents(data, x, y, (xx: number) => predictSingle(xx));\n if (comps.n === 0) {\n return out;\n }\n\n const z = Math.abs(invNorm(1 - alpha / 2));\n if (comps.min === comps.max) {\n const v = predictSingle(comps.min);\n const errs = stdErrorsAt(comps.min, comps);\n for (let i = 0; i < N; i++) {\n out.push({\n x: comps.min,\n mean: v,\n lower: v - z * errs.seMean,\n upper: v + z * errs.seMean,\n predLower: v - z * errs.sePred,\n predUpper: v + z * errs.sePred\n });\n }\n return out;\n }\n\n const step = (max - min) / (N - 1);\n for (let i = 0; i < N; i++) {\n const px = i === N - 1 ? max : min + step * i;\n const yh = predictSingle(px);\n const errs = stdErrorsAt(px, comps);\n out.push({\n x: px,\n mean: yh,\n lower: yh - z * errs.seMean,\n upper: yh + z * errs.seMean,\n predLower: yh - z * errs.sePred,\n predUpper: yh + z * errs.sePred\n });\n }\n return out;\n }\n\n return {\n predict,\n evaluate: predict as any,\n evaluateGrid,\n confidenceInterval\n };\n}\n\nexport default regressionLowess;\n"]}
|
package/dist/index.js
CHANGED
|
@@ -2074,49 +2074,87 @@
|
|
|
2074
2074
|
const t = 1 - uu * uu * uu;
|
|
2075
2075
|
return t * t * t;
|
|
2076
2076
|
}
|
|
2077
|
+
function stratifiedSample(sortedData, maxSamples) {
|
|
2078
|
+
const n = sortedData.length;
|
|
2079
|
+
if (n <= maxSamples) {
|
|
2080
|
+
return sortedData;
|
|
2081
|
+
}
|
|
2082
|
+
const sampled = [];
|
|
2083
|
+
const step = n / maxSamples;
|
|
2084
|
+
for (let i = 0; i < maxSamples; i++) {
|
|
2085
|
+
const idx = Math.min(Math.floor(i * step), n - 1);
|
|
2086
|
+
sampled.push(sortedData[idx]);
|
|
2087
|
+
}
|
|
2088
|
+
return sampled;
|
|
2089
|
+
}
|
|
2077
2090
|
function regressionLowess(data, x = d => d.x, y = d => d.y, options = {}) {
|
|
2078
2091
|
var _a;
|
|
2079
2092
|
const span = options.span || 0.3;
|
|
2080
2093
|
const degree = options.degree === 0 ? 0 : 1;
|
|
2081
|
-
const alpha = (_a = options
|
|
2094
|
+
const alpha = (_a = options.alpha) !== null && _a !== void 0 ? _a : 0.05;
|
|
2082
2095
|
const iterations = options.iterations == null ? 2 : options.iterations;
|
|
2083
|
-
const
|
|
2084
|
-
const
|
|
2096
|
+
const maxSamples = options.maxSamples || 1000;
|
|
2097
|
+
const rawPoints = [];
|
|
2085
2098
|
visitPoints(data, x, y, (dx, dy) => {
|
|
2086
|
-
|
|
2087
|
-
ptsY.push(dy);
|
|
2099
|
+
rawPoints.push({ x: dx, y: dy });
|
|
2088
2100
|
});
|
|
2089
|
-
|
|
2101
|
+
rawPoints.sort((a, b) => a.x - b.x);
|
|
2102
|
+
const sampledPoints = stratifiedSample(rawPoints, maxSamples);
|
|
2103
|
+
const n = sampledPoints.length;
|
|
2104
|
+
const ptsX = new Array(n);
|
|
2105
|
+
const ptsY = new Array(n);
|
|
2106
|
+
for (let i = 0; i < n; i++) {
|
|
2107
|
+
ptsX[i] = sampledPoints[i].x;
|
|
2108
|
+
ptsY[i] = sampledPoints[i].y;
|
|
2109
|
+
}
|
|
2090
2110
|
function predictSingle(x0, robustWeights) {
|
|
2091
2111
|
if (n === 0) {
|
|
2092
2112
|
return 0;
|
|
2093
2113
|
}
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2114
|
+
let left = 0;
|
|
2115
|
+
let right = n;
|
|
2116
|
+
while (left < right) {
|
|
2117
|
+
const mid = (left + right) >> 1;
|
|
2118
|
+
if (ptsX[mid] < x0) {
|
|
2119
|
+
left = mid + 1;
|
|
2120
|
+
}
|
|
2121
|
+
else {
|
|
2122
|
+
right = mid;
|
|
2123
|
+
}
|
|
2097
2124
|
}
|
|
2098
|
-
dists.sort((a, b) => a.dist - b.dist);
|
|
2099
2125
|
const m = Math.max(2, Math.min(n, Math.floor(span * n)));
|
|
2100
|
-
const
|
|
2101
|
-
const
|
|
2126
|
+
const start = Math.max(0, left - Math.floor(m / 2));
|
|
2127
|
+
const end = Math.min(n, start + m);
|
|
2128
|
+
const actualStart = Math.max(0, end - m);
|
|
2129
|
+
let maxDist = 0;
|
|
2130
|
+
const windowSize = end - actualStart;
|
|
2131
|
+
const distances = new Array(windowSize);
|
|
2132
|
+
for (let i = actualStart; i < end; i++) {
|
|
2133
|
+
const dist = Math.abs(ptsX[i] - x0);
|
|
2134
|
+
distances[i - actualStart] = dist;
|
|
2135
|
+
if (dist > maxDist) {
|
|
2136
|
+
maxDist = dist;
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2102
2139
|
let sumw = 0;
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
const u = maxDist === 0 ? 0 :
|
|
2140
|
+
const w = new Array(windowSize);
|
|
2141
|
+
for (let i = 0; i < windowSize; i++) {
|
|
2142
|
+
const u = maxDist === 0 ? 0 : distances[i] / maxDist;
|
|
2106
2143
|
let wi = tricube(u);
|
|
2107
|
-
if (robustWeights && robustWeights[
|
|
2108
|
-
wi *= robustWeights[
|
|
2144
|
+
if (robustWeights && robustWeights[actualStart + i] != null) {
|
|
2145
|
+
wi *= robustWeights[actualStart + i];
|
|
2109
2146
|
}
|
|
2110
2147
|
w[i] = wi;
|
|
2111
2148
|
sumw += wi;
|
|
2112
2149
|
}
|
|
2113
2150
|
if (sumw === 0) {
|
|
2114
|
-
|
|
2151
|
+
const nearestIdx = left < n ? left : n - 1;
|
|
2152
|
+
return ptsY[nearestIdx];
|
|
2115
2153
|
}
|
|
2116
2154
|
if (degree === 0) {
|
|
2117
2155
|
let s = 0;
|
|
2118
|
-
for (let i = 0; i <
|
|
2119
|
-
s += w[i] * ptsY[
|
|
2156
|
+
for (let i = 0; i < w.length; i++) {
|
|
2157
|
+
s += w[i] * ptsY[actualStart + i];
|
|
2120
2158
|
}
|
|
2121
2159
|
return s / sumw;
|
|
2122
2160
|
}
|
|
@@ -2125,11 +2163,11 @@
|
|
|
2125
2163
|
let sy = 0;
|
|
2126
2164
|
let sxx = 0;
|
|
2127
2165
|
let sxy = 0;
|
|
2128
|
-
for (let i =
|
|
2129
|
-
const idx =
|
|
2130
|
-
const xi = ptsX[
|
|
2131
|
-
const yi = ptsY[
|
|
2132
|
-
const wi = w[
|
|
2166
|
+
for (let i = actualStart; i < end; i++) {
|
|
2167
|
+
const idx = i - actualStart;
|
|
2168
|
+
const xi = ptsX[i];
|
|
2169
|
+
const yi = ptsY[i];
|
|
2170
|
+
const wi = w[idx];
|
|
2133
2171
|
sw += wi;
|
|
2134
2172
|
sx += wi * xi;
|
|
2135
2173
|
sy += wi * yi;
|
|
@@ -2145,62 +2183,56 @@
|
|
|
2145
2183
|
}
|
|
2146
2184
|
function predict(x0) {
|
|
2147
2185
|
if (Array.isArray(x0)) {
|
|
2148
|
-
const
|
|
2149
|
-
|
|
2150
|
-
|
|
2186
|
+
const len = x0.length;
|
|
2187
|
+
const out = new Array(len);
|
|
2188
|
+
for (let i = 0; i < len; i++) {
|
|
2189
|
+
out[i] = predictSingle(x0[i]);
|
|
2151
2190
|
}
|
|
2152
2191
|
return out;
|
|
2153
2192
|
}
|
|
2154
2193
|
return predictSingle(x0);
|
|
2155
2194
|
}
|
|
2156
2195
|
function evaluateGrid(N) {
|
|
2157
|
-
const out = [];
|
|
2158
2196
|
if (N <= 0) {
|
|
2159
|
-
return
|
|
2197
|
+
return [];
|
|
2160
2198
|
}
|
|
2161
2199
|
if (n === 0) {
|
|
2162
|
-
return
|
|
2163
|
-
}
|
|
2164
|
-
let min = Infinity;
|
|
2165
|
-
let max = -Infinity;
|
|
2166
|
-
for (let i = 0; i < n; i++) {
|
|
2167
|
-
if (ptsX[i] < min) {
|
|
2168
|
-
min = ptsX[i];
|
|
2169
|
-
}
|
|
2170
|
-
if (ptsX[i] > max) {
|
|
2171
|
-
max = ptsX[i];
|
|
2172
|
-
}
|
|
2200
|
+
return [];
|
|
2173
2201
|
}
|
|
2202
|
+
const out = new Array(N);
|
|
2203
|
+
const min = ptsX[0];
|
|
2204
|
+
const max = ptsX[n - 1];
|
|
2174
2205
|
if (min === max) {
|
|
2175
2206
|
const v = predictSingle(min);
|
|
2176
2207
|
for (let i = 0; i < N; i++) {
|
|
2177
|
-
out
|
|
2208
|
+
out[i] = { x: min, y: v };
|
|
2178
2209
|
}
|
|
2179
2210
|
return out;
|
|
2180
2211
|
}
|
|
2181
2212
|
const step = (max - min) / (N - 1);
|
|
2182
2213
|
let robustWeights;
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
for (let
|
|
2186
|
-
fits
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2214
|
+
const effectiveIterations = options.iterations != null ? iterations : n > 500 ? 0 : iterations;
|
|
2215
|
+
if (effectiveIterations > 0) {
|
|
2216
|
+
for (let iter = 0; iter < effectiveIterations; iter++) {
|
|
2217
|
+
const fits = new Array(n);
|
|
2218
|
+
const res = new Array(n);
|
|
2219
|
+
for (let i = 0; i < n; i++) {
|
|
2220
|
+
fits[i] = predictSingle(ptsX[i], robustWeights);
|
|
2221
|
+
res[i] = Math.abs(ptsY[i] - fits[i]);
|
|
2222
|
+
}
|
|
2223
|
+
const sortedRes = res.slice().sort((a, b) => a - b);
|
|
2224
|
+
const med = sortedRes[Math.floor(n / 2)] || 0;
|
|
2225
|
+
robustWeights = new Array(n);
|
|
2226
|
+
for (let i = 0; i < n; i++) {
|
|
2227
|
+
const u = med === 0 ? 0 : res[i] / (6 * med);
|
|
2228
|
+
const w = Math.abs(u) >= 1 ? 0 : (1 - u * u) * (1 - u * u);
|
|
2229
|
+
robustWeights[i] = w;
|
|
2230
|
+
}
|
|
2199
2231
|
}
|
|
2200
2232
|
}
|
|
2201
2233
|
for (let i = 0; i < N; i++) {
|
|
2202
2234
|
const px = i === N - 1 ? max : min + step * i;
|
|
2203
|
-
out
|
|
2235
|
+
out[i] = { x: px, y: predictSingle(px, robustWeights) };
|
|
2204
2236
|
}
|
|
2205
2237
|
return out;
|
|
2206
2238
|
}
|
|
@@ -2212,17 +2244,9 @@
|
|
|
2212
2244
|
if (n === 0) {
|
|
2213
2245
|
return out;
|
|
2214
2246
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
if (ptsX[i] < min) {
|
|
2219
|
-
min = ptsX[i];
|
|
2220
|
-
}
|
|
2221
|
-
if (ptsX[i] > max) {
|
|
2222
|
-
max = ptsX[i];
|
|
2223
|
-
}
|
|
2224
|
-
}
|
|
2225
|
-
if (min === Infinity || max === -Infinity) {
|
|
2247
|
+
const min = ptsX[0];
|
|
2248
|
+
const max = ptsX[n - 1];
|
|
2249
|
+
if (min === undefined || max === undefined || min === Infinity || max === -Infinity) {
|
|
2226
2250
|
return out;
|
|
2227
2251
|
}
|
|
2228
2252
|
const comps = computeLinearCIComponents(data, x, y, (xx) => predictSingle(xx));
|