@visactor/vutils 1.0.25 → 1.0.26
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/REGRESSION.md +36 -0
- package/cjs/common/ascending.js +2 -1
- package/cjs/common/deviation.js +1 -2
- package/cjs/common/getType.js +2 -1
- package/cjs/common/index.d.ts +1 -0
- package/cjs/common/index.js +2 -1
- package/cjs/common/index.js.map +1 -1
- package/cjs/common/isFunction.js +1 -2
- package/cjs/common/isObject.js +2 -1
- package/cjs/common/isPrototype.js +1 -1
- package/cjs/common/isRegExp.js +1 -1
- package/cjs/common/isShallowEqual.js +1 -1
- package/cjs/common/isString.js +1 -1
- package/cjs/common/isType.js +1 -1
- package/cjs/common/regression-bootstrap.d.ts +14 -0
- package/cjs/common/regression-bootstrap.js +37 -0
- package/cjs/common/regression-bootstrap.js.map +1 -0
- package/cjs/common/regression-linear.d.ts +1 -0
- package/cjs/common/regression-linear.js +11 -29
- package/cjs/common/regression-linear.js.map +1 -1
- package/cjs/common/regression-lowess.d.ts +9 -8
- package/cjs/common/regression-lowess.js +109 -130
- package/cjs/common/regression-lowess.js.map +1 -1
- package/cjs/common/regression-polynomial.d.ts +1 -0
- package/cjs/common/regression-polynomial.js +11 -92
- package/cjs/common/regression-polynomial.js.map +1 -1
- package/cjs/common/regression-solver.d.ts +26 -0
- package/cjs/common/regression-solver.js +180 -0
- package/cjs/common/regression-solver.js.map +1 -0
- package/cjs/data-structure/bounds.js +1 -1
- package/cjs/data-structure/hashTable.js +1 -2
- package/cjs/data-structure/index.js +1 -1
- package/cjs/data-structure/matrix.js +1 -1
- package/cjs/data-structure/point.js +1 -1
- package/dist/index.js +471 -340
- package/dist/index.min.js +16 -16
- package/es/common/ascending.js +2 -1
- package/es/common/deviation.js +1 -2
- package/es/common/getType.js +2 -1
- package/es/common/index.d.ts +1 -0
- package/es/common/index.js +2 -0
- package/es/common/index.js.map +1 -1
- package/es/common/isFunction.js +1 -2
- package/es/common/isObject.js +2 -1
- package/es/common/isPrototype.js +1 -1
- package/es/common/isRegExp.js +1 -1
- package/es/common/isShallowEqual.js +1 -1
- package/es/common/isString.js +1 -1
- package/es/common/isType.js +1 -1
- package/es/common/regression-bootstrap.d.ts +14 -0
- package/es/common/regression-bootstrap.js +31 -0
- package/es/common/regression-bootstrap.js.map +1 -0
- package/es/common/regression-linear.d.ts +1 -0
- package/es/common/regression-linear.js +9 -27
- package/es/common/regression-linear.js.map +1 -1
- package/es/common/regression-lowess.d.ts +9 -8
- package/es/common/regression-lowess.js +106 -130
- package/es/common/regression-lowess.js.map +1 -1
- package/es/common/regression-polynomial.d.ts +1 -0
- package/es/common/regression-polynomial.js +9 -86
- package/es/common/regression-polynomial.js.map +1 -1
- package/es/common/regression-solver.d.ts +26 -0
- package/es/common/regression-solver.js +168 -0
- package/es/common/regression-solver.js.map +1 -0
- package/es/data-structure/bounds.js +1 -1
- package/es/data-structure/hashTable.js +1 -2
- package/es/data-structure/index.js +1 -1
- package/es/data-structure/matrix.js +1 -1
- package/es/data-structure/point.js +1 -1
- package/package.json +5 -4
|
@@ -4,153 +4,127 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: !0
|
|
5
5
|
}), exports.regressionLowess = void 0;
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
function tricube(u) {
|
|
10
|
-
const uu = Math.abs(u);
|
|
11
|
-
if (uu >= 1) return 0;
|
|
12
|
-
const t = 1 - uu * uu * uu;
|
|
13
|
-
return t * t * t;
|
|
14
|
-
}
|
|
7
|
+
const regression_solver_1 = require("./regression-solver"), median_1 = require("./median"), regression_utils_1 = require("./regression-utils");
|
|
15
8
|
|
|
16
9
|
/**
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
10
|
+
* 局部线性 LOWESS。默认全量观测、span=2/3、三次稳健重加权。
|
|
11
|
+
* delta 显式插值加速;maxSamples 仅保留显式选择的历史抽样用途。
|
|
12
|
+
* predict 与 evaluateGrid 查询构建时固定的同一模型,不触发再拟合。
|
|
13
|
+
*/
|
|
14
|
+
function regressionLowess(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
15
|
+
var _a, _b, _c, _d, _e;
|
|
16
|
+
const span = null !== (_a = options.span) && void 0 !== _a ? _a : 2 / 3, degree = null !== (_b = options.degree) && void 0 !== _b ? _b : 1, iterations = null !== (_c = options.iterations) && void 0 !== _c ? _c : 3, delta = null !== (_d = options.delta) && void 0 !== _d ? _d : 0, alpha = null !== (_e = options.alpha) && void 0 !== _e ? _e : .05;
|
|
17
|
+
if (!(span > 0 && span <= 1) || !Number.isInteger(iterations) || iterations < 0 || !Number.isFinite(delta) || delta < 0 || 0 !== degree && 1 !== degree || null != options.maxSamples && (!Number.isInteger(options.maxSamples) || options.maxSamples < 2)) throw new RangeError("Invalid LOWESS span, degree, iterations, delta or maxSamples");
|
|
18
|
+
let pts = (0, regression_solver_1.regressionPoints)(data, x, y).sort(((a, b) => a.x - b.x || a.y - b.y));
|
|
19
|
+
if (null != options.maxSamples && pts.length > options.maxSamples) {
|
|
20
|
+
const full = pts, count = options.maxSamples;
|
|
21
|
+
pts = Array.from({
|
|
22
|
+
length: count
|
|
23
|
+
}, ((_, i) => full[Math.floor(i * (full.length - 1) / (count - 1))]));
|
|
26
24
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* - alpha: confidence level for CI
|
|
37
|
-
* - maxSamples: maximum number of points to use (default: 1000 for fast processing)
|
|
38
|
-
*/ function regressionLowess(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
39
|
-
var _a;
|
|
40
|
-
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 = [];
|
|
41
|
-
(0, regression_linear_1.visitPoints)(data, x, y, ((dx, dy, index) => {
|
|
42
|
-
rawPoints.push({
|
|
43
|
-
x: dx,
|
|
44
|
-
y: dy,
|
|
45
|
-
index: index
|
|
46
|
-
});
|
|
47
|
-
})), rawPoints.sort(((a, b) => a.x - b.x));
|
|
48
|
-
// Apply sampling if needed
|
|
49
|
-
const sampledPoints = stratifiedSample(rawPoints, maxSamples), n = sampledPoints.length, ptsX = new Array(n), ptsY = new Array(n);
|
|
50
|
-
for (let i = 0; i < n; i++) ptsX[i] = sampledPoints[i].x, ptsY[i] = sampledPoints[i].y;
|
|
51
|
-
/**
|
|
52
|
-
* Optimized predictSingle using binary search on pre-sorted data
|
|
53
|
-
*/ function predictSingle(x0, robustWeights) {
|
|
54
|
-
if (0 === n) return 0;
|
|
55
|
-
// Binary search to find insertion point
|
|
56
|
-
let left = 0, right = n;
|
|
25
|
+
const n = pts.length, ptsX = pts.map((p => p.x)), ptsY = pts.map((p => p.y)), basis = (0,
|
|
26
|
+
regression_solver_1.regressionBasis)(pts), normalizedX = ptsX.map((v => (0, regression_solver_1.normalizeRegression)(v, basis.xCenter, basis.xScale))), normalizedY = ptsY.map((v => (0,
|
|
27
|
+
regression_solver_1.normalizeRegression)(v, basis.yCenter, basis.yScale))), count = Math.min(n, Math.max(2, Math.floor(span * n + 1e-10)));
|
|
28
|
+
let robustWeights;
|
|
29
|
+
function exact(x0) {
|
|
30
|
+
if (!n) return 0;
|
|
31
|
+
const query = (0, regression_solver_1.normalizeRegression)(x0, basis.xCenter, basis.xScale);
|
|
32
|
+
// 找到连续的最近邻窗口;相等距离选择较小的 x(ties 的 y 已排序)。
|
|
33
|
+
let left = 0, right = n - count;
|
|
57
34
|
for (;left < right; ) {
|
|
58
|
-
const mid = left + right
|
|
59
|
-
|
|
35
|
+
const mid = left + right >>> 1, lowerDistance = x0 - ptsX[mid], upperDistance = ptsX[mid + count] - x0;
|
|
36
|
+
(Number.isFinite(lowerDistance) && Number.isFinite(upperDistance) ? lowerDistance > upperDistance : query - normalizedX[mid] > normalizedX[mid + count] - query) ? left = mid + 1 : right = mid;
|
|
60
37
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const actualStart = lo + 1, end = hi;
|
|
66
|
-
// Find max distance and compute weights in single pass
|
|
67
|
-
let maxDist = 0;
|
|
68
|
-
const windowSize = end - actualStart, distances = new Array(windowSize);
|
|
69
|
-
for (let i = actualStart; i < end; i++) {
|
|
70
|
-
const dist = Math.abs(ptsX[i] - x0);
|
|
71
|
-
distances[i - actualStart] = dist, dist > maxDist && (maxDist = dist);
|
|
38
|
+
let start = left, end = left + count;
|
|
39
|
+
if (ptsX[start] === ptsX[end - 1]) {
|
|
40
|
+
for (;start > 0 && ptsX[start - 1] === ptsX[start]; ) start--;
|
|
41
|
+
for (;end < n && ptsX[end] === ptsX[start]; ) end++;
|
|
72
42
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
for (let i =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
43
|
+
const rawRadius = Math.max(Math.abs(ptsX[start] - x0), Math.abs(ptsX[end - 1] - x0)), scaled = !Number.isFinite(rawRadius), radius = scaled ? Math.max(Math.abs(normalizedX[start] - query), Math.abs(normalizedX[end - 1] - query)) : rawRadius;
|
|
44
|
+
// 局部响应坐标不能由远处、未参与该邻域的观测决定精度。
|
|
45
|
+
let yMin = 1 / 0, yMax = -1 / 0;
|
|
46
|
+
for (let i = start; i < end; i++) yMin = Math.min(yMin, ptsY[i]), yMax = Math.max(yMax, ptsY[i]);
|
|
47
|
+
const yCenter = yMin / 2 + yMax / 2, yScale = Math.max(Math.abs(yMin - yCenter), Math.abs(yMax - yCenter)) || 1;
|
|
48
|
+
let sw = 0, sx = 0, sy = 0, sxx = 0, sxy = 0;
|
|
49
|
+
for (let i = start; i < end; i++) {
|
|
50
|
+
const z = 0 === radius ? 0 : (scaled ? normalizedX[i] - query : ptsX[i] - x0) / radius, u = Math.abs(z), t = u >= 1 ? 0 : 1 - u * u * u, w = t * t * t * (robustWeights ? robustWeights[i] : 1);
|
|
51
|
+
sw += w, sx += w * z;
|
|
52
|
+
const response = (0, regression_solver_1.normalizeRegression)(ptsY[i], yCenter, yScale);
|
|
53
|
+
sy += w * response, sxx += w * z * z, sxy += w * z * response;
|
|
80
54
|
}
|
|
81
|
-
if (0 ===
|
|
82
|
-
//
|
|
83
|
-
let
|
|
84
|
-
for (let i =
|
|
85
|
-
const
|
|
86
|
-
(
|
|
87
|
-
|
|
55
|
+
if (0 === sw) {
|
|
56
|
+
// 核边界零权重时使用最近有效观测的加权常数;等距离取均值。
|
|
57
|
+
let distance = 1 / 0, weight = 0, value = 0;
|
|
58
|
+
for (let i = 0; i < n; i++) {
|
|
59
|
+
const w = robustWeights ? robustWeights[i] : 1;
|
|
60
|
+
if (0 === w) continue;
|
|
61
|
+
const d = Math.abs(scaled ? normalizedX[i] - query : ptsX[i] - x0);
|
|
62
|
+
d < distance ? (distance = d, weight = w, value = ptsY[i]) : d === distance && (value = value * (weight / (weight + w)) + ptsY[i] * (w / (weight + w)),
|
|
63
|
+
weight += w);
|
|
88
64
|
}
|
|
89
|
-
|
|
65
|
+
if (0 === weight) throw new RangeError("LOWESS has no effective local observations");
|
|
66
|
+
return value;
|
|
90
67
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
68
|
+
const mx = sx / sw, my = sy / sw, variance = sxx / sw - mx * mx;
|
|
69
|
+
return yCenter + yScale * (my - (0 === degree || variance <= 32 * Number.EPSILON ? 0 : (sxy / sw - mx * my) / variance) * mx);
|
|
70
|
+
}
|
|
71
|
+
// delta 不删除观测。只减少局部回归求值位置,全部残差参与重加权。
|
|
72
|
+
const anchors = [];
|
|
73
|
+
for (let i = 0; i < n && (anchors.push(i), i !== n - 1); ) {
|
|
74
|
+
let next = i + 1;
|
|
75
|
+
if (delta > 0) for (;next + 1 < n && ptsX[next + 1] - ptsX[i] <= delta; ) next++;
|
|
76
|
+
// 重复 x 一起使用同一预测;端点不能丢失。
|
|
77
|
+
for (;next + 1 < n && ptsX[next + 1] === ptsX[next]; ) next++;
|
|
78
|
+
i = next;
|
|
79
|
+
}
|
|
80
|
+
let fits = new Array(n);
|
|
81
|
+
function fitObservations() {
|
|
82
|
+
const out = new Array(n);
|
|
83
|
+
for (let a = 0; a < anchors.length; a++) {
|
|
84
|
+
const index = anchors[a];
|
|
85
|
+
if (out[index] = exact(ptsX[index]), 0 === a) continue;
|
|
86
|
+
const previous = anchors[a - 1], rawWidth = ptsX[index] - ptsX[previous], width = Number.isFinite(rawWidth) ? rawWidth : normalizedX[index] - normalizedX[previous];
|
|
87
|
+
for (let i = previous + 1; i < index; i++) {
|
|
88
|
+
const t = 0 === width ? 0 : (Number.isFinite(rawWidth) ? ptsX[i] - ptsX[previous] : normalizedX[i] - normalizedX[previous]) / width;
|
|
89
|
+
out[i] = out[previous] * (1 - t) + out[index] * t;
|
|
90
|
+
}
|
|
95
91
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
for (let iteration = 0; iteration <= iterations && (fits = fitObservations(), iteration !== iterations); iteration++) {
|
|
95
|
+
const residuals = fits.map(((v, i) => {
|
|
96
|
+
const residual = ptsY[i] - v;
|
|
97
|
+
return Number.isFinite(residual) ? Math.abs(residual / basis.yScale) : Math.abs(normalizedY[i] - (0,
|
|
98
|
+
regression_solver_1.normalizeRegression)(v, basis.yCenter, basis.yScale));
|
|
99
|
+
})), med = (0, median_1.median)(residuals.slice()), currentFits = fits;
|
|
100
|
+
robustWeights = residuals.map(((r, i) => {
|
|
101
|
+
if (0 === med) {
|
|
102
|
+
return r <= 64 * Number.EPSILON * (Math.max(Math.abs(ptsY[i]), Math.abs(currentFits[i])) / basis.yScale) ? 1 : 0;
|
|
103
|
+
}
|
|
104
|
+
const u = r / (6 * med);
|
|
105
|
+
return u >= 1 ? 0 : (1 - u * u) ** 2;
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
function predictSingle(x0) {
|
|
109
|
+
if (0 === delta || n < 2 || x0 < ptsX[0] || x0 > ptsX[n - 1]) return exact(x0);
|
|
110
|
+
let lo = 0, hi = n - 1;
|
|
111
|
+
for (;hi - lo > 1; ) {
|
|
112
|
+
const mid = lo + hi >>> 1;
|
|
113
|
+
ptsX[mid] <= x0 ? lo = mid : hi = mid;
|
|
101
114
|
}
|
|
102
|
-
|
|
103
|
-
|
|
115
|
+
if (ptsX[hi] === ptsX[lo]) return fits[lo];
|
|
116
|
+
const width = ptsX[hi] - ptsX[lo], t = Number.isFinite(width) ? (x0 - ptsX[lo]) / width : ((0,
|
|
117
|
+
regression_solver_1.normalizeRegression)(x0, basis.xCenter, basis.xScale) - normalizedX[lo]) / (normalizedX[hi] - normalizedX[lo]);
|
|
118
|
+
return fits[lo] * (1 - t) + fits[hi] * t;
|
|
104
119
|
}
|
|
105
120
|
function predict(x0) {
|
|
106
|
-
|
|
107
|
-
const len = x0.length, out = new Array(len);
|
|
108
|
-
for (let i = 0; i < len; i++) out[i] = predictSingle(x0[i]);
|
|
109
|
-
return out;
|
|
110
|
-
}
|
|
111
|
-
return predictSingle(x0);
|
|
121
|
+
return Array.isArray(x0) ? x0.map(predictSingle) : predictSingle(x0);
|
|
112
122
|
}
|
|
113
123
|
return {
|
|
114
124
|
predict: predict,
|
|
115
125
|
evaluate: predict,
|
|
116
126
|
evaluateGrid: function(N) {
|
|
117
|
-
|
|
118
|
-
if (0 === n) return [];
|
|
119
|
-
const out = new Array(N), min = ptsX[0], max = ptsX[n - 1];
|
|
120
|
-
if (min === max) {
|
|
121
|
-
const v = predictSingle(min);
|
|
122
|
-
for (let i = 0; i < N; i++) out[i] = {
|
|
123
|
-
x: min,
|
|
124
|
-
y: v
|
|
125
|
-
};
|
|
126
|
-
return out;
|
|
127
|
-
}
|
|
128
|
-
const step = (max - min) / (N - 1);
|
|
129
|
-
// optionally add robust iterations
|
|
130
|
-
let robustWeights;
|
|
131
|
-
// Disable robustness iterations for large datasets to improve performance
|
|
132
|
-
// Users can override by setting iterations explicitly
|
|
133
|
-
const effectiveIterations = null != options.iterations ? iterations : n > 500 ? 0 : iterations;
|
|
134
|
-
if (effectiveIterations > 0) for (let iter = 0; iter < effectiveIterations; iter++) {
|
|
135
|
-
// compute fits - pre-allocate arrays
|
|
136
|
-
const fits = new Array(n), res = new Array(n);
|
|
137
|
-
for (let i = 0; i < n; i++) fits[i] = predictSingle(ptsX[i], robustWeights), res[i] = Math.abs(ptsY[i] - fits[i]);
|
|
138
|
-
// median absolute deviation
|
|
139
|
-
const med = res.slice().sort(((a, b) => a - b))[Math.floor(n / 2)] || 0;
|
|
140
|
-
robustWeights = new Array(n);
|
|
141
|
-
for (let i = 0; i < n; i++) {
|
|
142
|
-
const u = 0 === med ? 0 : res[i] / (6 * med), w = Math.abs(u) >= 1 ? 0 : (1 - u * u) * (1 - u * u);
|
|
143
|
-
robustWeights[i] = w;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
for (let i = 0; i < N; i++) {
|
|
147
|
-
const px = i === N - 1 ? max : min + step * i;
|
|
148
|
-
out[i] = {
|
|
149
|
-
x: px,
|
|
150
|
-
y: predictSingle(px, robustWeights)
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
return out;
|
|
127
|
+
return (0, regression_solver_1.regressionGrid)(ptsX[0], ptsX[n - 1], N, predictSingle);
|
|
154
128
|
},
|
|
155
129
|
confidenceInterval: function(N = 50) {
|
|
156
130
|
const out = [];
|
|
@@ -190,7 +164,12 @@ function tricube(u) {
|
|
|
190
164
|
});
|
|
191
165
|
}
|
|
192
166
|
return out;
|
|
193
|
-
}
|
|
167
|
+
},
|
|
168
|
+
// 节点值按 x 排序,重复观测仍保持其统计权重。
|
|
169
|
+
fitted: pts.map(((p, i) => ({
|
|
170
|
+
x: p.x,
|
|
171
|
+
y: fits[i]
|
|
172
|
+
})))
|
|
194
173
|
};
|
|
195
174
|
}
|
|
196
175
|
|
|
@@ -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 {\n computeLinearCIComponents,\n confidenceCriticalValue,\n confidenceHalfWidth,\n stdErrorsAt\n} from './regression-utils';\n\ninterface LowessPoint {\n x: number;\n y: number;\n index: number;\n}\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: LowessPoint[], maxSamples: number) {\n const n = sortedData.length;\n if (n <= maxSamples) {\n return sortedData;\n }\n\n const sampled: LowessPoint[] = [];\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: LowessPoint[] = [];\n visitPoints(data, x, y, (dx, dy, index) => {\n rawPoints.push({ x: dx, y: dy, index });\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.min(n, Math.max(2, Math.floor(span * n)));\n\n // Expand by distance: equal numbers on either side need not be the nearest points.\n let lo = left - 1;\n let hi = left;\n for (let count = 0; count < m; count++) {\n if (lo >= 0 && (hi >= n || x0 - ptsX[lo] <= ptsX[hi] - x0)) {\n lo--;\n } else {\n hi++;\n }\n }\n const actualStart = lo + 1;\n const end = hi;\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 // Fall back to the nearest y, preserving input order for equal distances.\n let nearestIdx = 0;\n let nearestDistance = Math.abs(ptsX[0] - x0);\n for (let i = 1; i < n; i++) {\n const distance = Math.abs(ptsX[i] - x0);\n if (\n distance < nearestDistance ||\n (distance === nearestDistance && sampledPoints[i].index < sampledPoints[nearestIdx].index)\n ) {\n nearestIdx = i;\n nearestDistance = distance;\n }\n }\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 = confidenceCriticalValue(alpha);\n if (comps.min === comps.max) {\n const v = predictSingle(comps.min);\n const errs = stdErrorsAt(comps.min, comps);\n const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n for (let i = 0; i < N; i++) {\n out.push({\n x: comps.min,\n mean: v,\n lower: v - meanHalfWidth,\n upper: v + meanHalfWidth,\n predLower: v - predHalfWidth,\n predUpper: v + predHalfWidth\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 const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n out.push({\n x: px,\n mean: yh,\n lower: yh - meanHalfWidth,\n upper: yh + meanHalfWidth,\n predLower: yh - predHalfWidth,\n predUpper: yh + predHalfWidth\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":";;;AAAA,2DAA6G;AAC7G,qCAAkC;AAClC,yDAK4B;AAE5B;;;;GAIG;AACH,SAAgB,gBAAgB,CAC9B,IAAW,EACX,IAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAChC,IAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAChC,UAOI,EAAE;;IAEN,MAAM,IAAI,GAAG,MAAA,OAAO,CAAC,IAAI,mCAAI,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAA,OAAO,CAAC,MAAM,mCAAI,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,MAAA,OAAO,CAAC,UAAU,mCAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAA,OAAO,CAAC,KAAK,mCAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,MAAA,OAAO,CAAC,KAAK,mCAAI,IAAI,CAAC;IACpC,IACE,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;QACxB,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;QAC7B,UAAU,GAAG,CAAC;QACd,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACvB,KAAK,GAAG,CAAC;QACT,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC;QAC9B,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EACjG;QACA,MAAM,IAAI,UAAU,CAAC,8DAA8D,CAAC,CAAC;KACtF;IACD,IAAI,GAAG,GAAG,IAAA,oCAAgB,EAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE;QACjE,MAAM,IAAI,GAAG,GAAG,CAAC;QACjB,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;QACjC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACxG;IACD,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;IACrB,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAA,mCAAe,EAAC,GAAG,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAA,uCAAmB,EAAC,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACvF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAA,uCAAmB,EAAC,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,aAAmC,CAAC;IAExC,SAAS,KAAK,CAAC,EAAU;QACvB,IAAI,CAAC,CAAC,EAAE;YACN,OAAO,CAAC,CAAC;SACV;QACD,MAAM,KAAK,GAAG,IAAA,uCAAmB,EAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACnE,wCAAwC;QACxC,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,OAAO,IAAI,GAAG,KAAK,EAAE;YACnB,MAAM,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,aAAa,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;YAC7C,IACE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAC9D,CAAC,CAAC,aAAa,GAAG,aAAa;gBAC/B,CAAC,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,KAAK,EAC/D;gBACA,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC;aAChB;iBAAM;gBACL,KAAK,GAAG,GAAG,CAAC;aACb;SACF;QACD,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,IAAI,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC;QACvB,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE;YACjC,OAAO,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE;gBACnD,KAAK,EAAE,CAAC;aACT;YACD,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE;gBAC3C,GAAG,EAAE,CAAC;aACP;SACF;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM;YACnB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;YACxF,CAAC,CAAC,SAAS,CAAC;QACd,6BAA6B;QAC7B,IAAI,IAAI,GAAG,QAAQ,CAAC;QACpB,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC;QACrB,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;YAChC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;SAChC;QACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;QACjF,IAAI,EAAE,GAAG,CAAC,CAAC;QACX,IAAI,EAAE,GAAG,CAAC,CAAC;QACX,IAAI,EAAE,GAAG,CAAC,CAAC;QACX,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;YAChC,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC;YACvF,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7D,EAAE,IAAI,CAAC,CAAC;YACR,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YACZ,MAAM,QAAQ,GAAG,IAAA,uCAAmB,EAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/D,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC;YACnB,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;SACzB;QACD,IAAI,EAAE,KAAK,CAAC,EAAE;YACZ,+BAA+B;YAC/B,IAAI,QAAQ,GAAG,QAAQ,CAAC;YACxB,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;gBAC1B,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC/C,IAAI,CAAC,KAAK,CAAC,EAAE;oBACX,SAAS;iBACV;gBACD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;gBACnE,IAAI,CAAC,GAAG,QAAQ,EAAE;oBAChB,QAAQ,GAAG,CAAC,CAAC;oBACb,MAAM,GAAG,CAAC,CAAC;oBACX,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;iBACjB;qBAAM,IAAI,CAAC,KAAK,QAAQ,EAAE;oBACzB,KAAK,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;oBACvE,MAAM,IAAI,CAAC,CAAC;iBACb;aACF;YACD,IAAI,MAAM,KAAK,CAAC,EAAE;gBAChB,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;aACpE;YACD,OAAO,KAAK,CAAC;SACd;QACD,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QACnB,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,QAAQ,IAAI,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC;QACpG,OAAO,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,qCAAqC;IACrC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAI;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YACf,MAAM;SACP;QACD,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,IAAI,KAAK,GAAG,CAAC,EAAE;YACb,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE;gBACxD,IAAI,EAAE,CAAC;aACR;SACF;QACD,wBAAwB;QACxB,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE;YACpD,IAAI,EAAE,CAAC;SACR;QACD,CAAC,GAAG,IAAI,CAAC;KACV;IACD,IAAI,IAAI,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;IAChC,SAAS,eAAe;QACtB,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACvC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,EAAE;gBACX,SAAS;aACV;YACD,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;YAChG,KAAK,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;gBACzC,MAAM,CAAC,GACL,KAAK,KAAK,CAAC;oBACT,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,KAAK,CAAC;gBAC9G,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;aACnD;SACF;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,IAAI,UAAU,EAAE,SAAS,EAAE,EAAE;QAC5D,IAAI,GAAG,eAAe,EAAE,CAAC;QACzB,IAAI,SAAS,KAAK,UAAU,EAAE;YAC5B,MAAM;SACP;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAC9B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;gBACnC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,uCAAmB,EAAC,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,eAAM,EAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,IAAI,CAAC;QACzB,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACrC,IAAI,GAAG,KAAK,CAAC,EAAE;gBACb,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC/G,OAAO,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC/B;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;KACJ;IACD,SAAS,aAAa,CAAC,EAAU;QAC/B,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;YAC5D,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC;SAClB;QACD,IAAI,EAAE,GAAG,CAAC,CAAC;QACX,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QACf,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE;YAClB,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE;gBACnB,EAAE,GAAG,GAAG,CAAC;aACV;iBAAM;gBACL,EAAE,GAAG,GAAG,CAAC;aACV;SACF;QACD,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC,EAAE;YACzB,OAAO,IAAI,CAAC,EAAE,CAAC,CAAC;SACjB;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC9B,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK;YACzB,CAAC,CAAC,CAAC,IAAA,uCAAmB,EAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;QACnH,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IACD,SAAS,OAAO,CAAC,EAAqB;QACpC,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,SAAS,YAAY,CAAC,CAAS;QAC7B,OAAO,IAAA,kCAAc,EAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC;IAChE,CAAC;IAED,SAAS,kBAAkB,CAAC,IAAY,EAAE;QACxC,MAAM,GAAG,GAAsG,EAAE,CAAC;QAElH,IAAI,CAAC,IAAI,CAAC,EAAE;YACV,OAAO,GAAG,CAAC;SACZ;QACD,IAAI,CAAC,KAAK,CAAC,EAAE;YACX,OAAO,GAAG,CAAC;SACZ;QAED,oCAAoC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAExB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE;YACnF,OAAO,GAAG,CAAC;SACZ;QAED,MAAM,KAAK,GAAG,IAAA,4CAAyB,EAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;QACvF,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE;YACjB,OAAO,GAAG,CAAC;SACZ;QAED,MAAM,CAAC,GAAG,IAAA,0CAAuB,EAAC,KAAK,CAAC,CAAC;QACzC,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnC,MAAM,IAAI,GAAG,IAAA,8BAAW,EAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC3C,MAAM,aAAa,GAAG,IAAA,sCAAmB,EAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1D,MAAM,aAAa,GAAG,IAAA,sCAAmB,EAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;gBAC1B,GAAG,CAAC,IAAI,CAAC;oBACP,CAAC,EAAE,KAAK,CAAC,GAAG;oBACZ,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE,CAAC,GAAG,aAAa;oBACxB,KAAK,EAAE,CAAC,GAAG,aAAa;oBACxB,SAAS,EAAE,CAAC,GAAG,aAAa;oBAC5B,SAAS,EAAE,CAAC,GAAG,aAAa;iBAC7B,CAAC,CAAC;aACJ;YACD,OAAO,GAAG,CAAC;SACZ;QAED,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC;YAC9C,MAAM,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAA,8BAAW,EAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACpC,MAAM,aAAa,GAAG,IAAA,sCAAmB,EAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1D,MAAM,aAAa,GAAG,IAAA,sCAAmB,EAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1D,GAAG,CAAC,IAAI,CAAC;gBACP,CAAC,EAAE,EAAE;gBACL,IAAI,EAAE,EAAE;gBACR,KAAK,EAAE,EAAE,GAAG,aAAa;gBACzB,KAAK,EAAE,EAAE,GAAG,aAAa;gBACzB,SAAS,EAAE,EAAE,GAAG,aAAa;gBAC7B,SAAS,EAAE,EAAE,GAAG,aAAa;aAC9B,CAAC,CAAC;SACJ;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO;QACL,OAAO;QACP,QAAQ,EAAE,OAAO;QACjB,YAAY;QACZ,kBAAkB;QAClB,0BAA0B;QAC1B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;KACpD,CAAC;AACJ,CAAC;AA7SD,4CA6SC;AACD,kBAAe,gBAAgB,CAAC","file":"regression-lowess.js","sourcesContent":["import { regressionPoints, regressionGrid, regressionBasis, normalizeRegression } from './regression-solver';\nimport { median } from './median';\nimport {\n computeLinearCIComponents,\n confidenceCriticalValue,\n confidenceHalfWidth,\n stdErrorsAt\n} from './regression-utils';\n\n/**\n * 局部线性 LOWESS。默认全量观测、span=2/3、三次稳健重加权。\n * delta 显式插值加速;maxSamples 仅保留显式选择的历史抽样用途。\n * predict 与 evaluateGrid 查询构建时固定的同一模型,不触发再拟合。\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: {\n span?: number;\n degree?: 1 | 0;\n iterations?: number;\n alpha?: number;\n maxSamples?: number;\n delta?: number;\n } = {}\n) {\n const span = options.span ?? 2 / 3;\n const degree = options.degree ?? 1;\n const iterations = options.iterations ?? 3;\n const delta = options.delta ?? 0;\n const alpha = options.alpha ?? 0.05;\n if (\n !(span > 0 && span <= 1) ||\n !Number.isInteger(iterations) ||\n iterations < 0 ||\n !Number.isFinite(delta) ||\n delta < 0 ||\n (degree !== 0 && degree !== 1) ||\n (options.maxSamples != null && (!Number.isInteger(options.maxSamples) || options.maxSamples < 2))\n ) {\n throw new RangeError('Invalid LOWESS span, degree, iterations, delta or maxSamples');\n }\n let pts = regressionPoints(data, x, y).sort((a, b) => a.x - b.x || a.y - b.y);\n if (options.maxSamples != null && pts.length > options.maxSamples) {\n const full = pts;\n const count = options.maxSamples;\n pts = Array.from({ length: count }, (_, i) => full[Math.floor((i * (full.length - 1)) / (count - 1))]);\n }\n const n = pts.length;\n const ptsX = pts.map(p => p.x);\n const ptsY = pts.map(p => p.y);\n const basis = regressionBasis(pts);\n const normalizedX = ptsX.map(v => normalizeRegression(v, basis.xCenter, basis.xScale));\n const normalizedY = ptsY.map(v => normalizeRegression(v, basis.yCenter, basis.yScale));\n const count = Math.min(n, Math.max(2, Math.floor(span * n + 1e-10)));\n let robustWeights: number[] | undefined;\n\n function exact(x0: number) {\n if (!n) {\n return 0;\n }\n const query = normalizeRegression(x0, basis.xCenter, basis.xScale);\n // 找到连续的最近邻窗口;相等距离选择较小的 x(ties 的 y 已排序)。\n let left = 0;\n let right = n - count;\n while (left < right) {\n const mid = (left + right) >>> 1;\n const lowerDistance = x0 - ptsX[mid];\n const upperDistance = ptsX[mid + count] - x0;\n if (\n Number.isFinite(lowerDistance) && Number.isFinite(upperDistance)\n ? lowerDistance > upperDistance\n : query - normalizedX[mid] > normalizedX[mid + count] - query\n ) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n let start = left;\n let end = left + count;\n if (ptsX[start] === ptsX[end - 1]) {\n while (start > 0 && ptsX[start - 1] === ptsX[start]) {\n start--;\n }\n while (end < n && ptsX[end] === ptsX[start]) {\n end++;\n }\n }\n const rawRadius = Math.max(Math.abs(ptsX[start] - x0), Math.abs(ptsX[end - 1] - x0));\n const scaled = !Number.isFinite(rawRadius);\n const radius = scaled\n ? Math.max(Math.abs(normalizedX[start] - query), Math.abs(normalizedX[end - 1] - query))\n : rawRadius;\n // 局部响应坐标不能由远处、未参与该邻域的观测决定精度。\n let yMin = Infinity;\n let yMax = -Infinity;\n for (let i = start; i < end; i++) {\n yMin = Math.min(yMin, ptsY[i]);\n yMax = Math.max(yMax, ptsY[i]);\n }\n const yCenter = yMin / 2 + yMax / 2;\n const yScale = Math.max(Math.abs(yMin - yCenter), Math.abs(yMax - yCenter)) || 1;\n let sw = 0;\n let sx = 0;\n let sy = 0;\n let sxx = 0;\n let sxy = 0;\n for (let i = start; i < end; i++) {\n const z = radius === 0 ? 0 : (scaled ? normalizedX[i] - query : ptsX[i] - x0) / radius;\n const u = Math.abs(z);\n const t = u >= 1 ? 0 : 1 - u * u * u;\n const w = t * t * t * (robustWeights ? robustWeights[i] : 1);\n sw += w;\n sx += w * z;\n const response = normalizeRegression(ptsY[i], yCenter, yScale);\n sy += w * response;\n sxx += w * z * z;\n sxy += w * z * response;\n }\n if (sw === 0) {\n // 核边界零权重时使用最近有效观测的加权常数;等距离取均值。\n let distance = Infinity;\n let weight = 0;\n let value = 0;\n for (let i = 0; i < n; i++) {\n const w = robustWeights ? robustWeights[i] : 1;\n if (w === 0) {\n continue;\n }\n const d = Math.abs(scaled ? normalizedX[i] - query : ptsX[i] - x0);\n if (d < distance) {\n distance = d;\n weight = w;\n value = ptsY[i];\n } else if (d === distance) {\n value = value * (weight / (weight + w)) + ptsY[i] * (w / (weight + w));\n weight += w;\n }\n }\n if (weight === 0) {\n throw new RangeError('LOWESS has no effective local observations');\n }\n return value;\n }\n const mx = sx / sw;\n const my = sy / sw;\n const variance = sxx / sw - mx * mx;\n const slope = degree === 0 || variance <= Number.EPSILON * 32 ? 0 : (sxy / sw - mx * my) / variance;\n return yCenter + yScale * (my - slope * mx);\n }\n\n // delta 不删除观测。只减少局部回归求值位置,全部残差参与重加权。\n const anchors: number[] = [];\n for (let i = 0; i < n; ) {\n anchors.push(i);\n if (i === n - 1) {\n break;\n }\n let next = i + 1;\n if (delta > 0) {\n while (next + 1 < n && ptsX[next + 1] - ptsX[i] <= delta) {\n next++;\n }\n }\n // 重复 x 一起使用同一预测;端点不能丢失。\n while (next + 1 < n && ptsX[next + 1] === ptsX[next]) {\n next++;\n }\n i = next;\n }\n let fits = new Array<number>(n);\n function fitObservations() {\n const out = new Array<number>(n);\n for (let a = 0; a < anchors.length; a++) {\n const index = anchors[a];\n out[index] = exact(ptsX[index]);\n if (a === 0) {\n continue;\n }\n const previous = anchors[a - 1];\n const rawWidth = ptsX[index] - ptsX[previous];\n const width = Number.isFinite(rawWidth) ? rawWidth : normalizedX[index] - normalizedX[previous];\n for (let i = previous + 1; i < index; i++) {\n const t =\n width === 0\n ? 0\n : (Number.isFinite(rawWidth) ? ptsX[i] - ptsX[previous] : normalizedX[i] - normalizedX[previous]) / width;\n out[i] = out[previous] * (1 - t) + out[index] * t;\n }\n }\n return out;\n }\n for (let iteration = 0; iteration <= iterations; iteration++) {\n fits = fitObservations();\n if (iteration === iterations) {\n break;\n }\n const residuals = fits.map((v, i) => {\n const residual = ptsY[i] - v;\n return Number.isFinite(residual)\n ? Math.abs(residual / basis.yScale)\n : Math.abs(normalizedY[i] - normalizeRegression(v, basis.yCenter, basis.yScale));\n });\n const med = median(residuals.slice());\n const currentFits = fits;\n robustWeights = residuals.map((r, i) => {\n if (med === 0) {\n const tolerance = Number.EPSILON * 64 * (Math.max(Math.abs(ptsY[i]), Math.abs(currentFits[i])) / basis.yScale);\n return r <= tolerance ? 1 : 0;\n }\n const u = r / (6 * med);\n return u >= 1 ? 0 : (1 - u * u) ** 2;\n });\n }\n function predictSingle(x0: number): number {\n if (delta === 0 || n < 2 || x0 < ptsX[0] || x0 > ptsX[n - 1]) {\n return exact(x0);\n }\n let lo = 0;\n let hi = n - 1;\n while (hi - lo > 1) {\n const mid = (lo + hi) >>> 1;\n if (ptsX[mid] <= x0) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n if (ptsX[hi] === ptsX[lo]) {\n return fits[lo];\n }\n const width = ptsX[hi] - ptsX[lo];\n const t = Number.isFinite(width)\n ? (x0 - ptsX[lo]) / width\n : (normalizeRegression(x0, basis.xCenter, basis.xScale) - normalizedX[lo]) / (normalizedX[hi] - normalizedX[lo]);\n return fits[lo] * (1 - t) + fits[hi] * t;\n }\n function predict(x0: number | number[]) {\n return Array.isArray(x0) ? x0.map(predictSingle) : predictSingle(x0);\n }\n function evaluateGrid(N: number) {\n return regressionGrid(ptsX[0], ptsX[n - 1], N, predictSingle);\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 = confidenceCriticalValue(alpha);\n if (comps.min === comps.max) {\n const v = predictSingle(comps.min);\n const errs = stdErrorsAt(comps.min, comps);\n const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n for (let i = 0; i < N; i++) {\n out.push({\n x: comps.min,\n mean: v,\n lower: v - meanHalfWidth,\n upper: v + meanHalfWidth,\n predLower: v - predHalfWidth,\n predUpper: v + predHalfWidth\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 const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n out.push({\n x: px,\n mean: yh,\n lower: yh - meanHalfWidth,\n upper: yh + meanHalfWidth,\n predLower: yh - predHalfWidth,\n predUpper: yh + predHalfWidth\n });\n }\n return out;\n }\n\n return {\n predict,\n evaluate: predict,\n evaluateGrid,\n confidenceInterval,\n // 节点值按 x 排序,重复观测仍保持其统计权重。\n fitted: pts.map((p, i) => ({ x: p.x, y: fits[i] }))\n };\n}\nexport default regressionLowess;\n"]}
|
|
@@ -1,82 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var __importDefault = this && this.__importDefault || function(mod) {
|
|
4
|
-
return mod && mod.__esModule ? mod : {
|
|
5
|
-
default: mod
|
|
6
|
-
};
|
|
7
|
-
};
|
|
8
|
-
|
|
9
3
|
Object.defineProperty(exports, "__esModule", {
|
|
10
4
|
value: !0
|
|
11
5
|
}), exports.regressionPolynomial = void 0;
|
|
12
6
|
|
|
13
|
-
const regression_linear_1 = require("./regression-linear"),
|
|
14
|
-
|
|
15
|
-
function solveLinearSystem(A, b) {
|
|
16
|
-
// Gaussian elimination with partial pivoting
|
|
17
|
-
const n = b.length, M = new Array(n);
|
|
18
|
-
// clone
|
|
19
|
-
for (let i = 0; i < n; i++) M[i] = A[i].slice(), M[i].push(b[i]);
|
|
20
|
-
for (let k = 0; k < n; k++) {
|
|
21
|
-
// find pivot
|
|
22
|
-
let maxRow = k, maxVal = Math.abs(M[k][k]);
|
|
23
|
-
for (let i = k + 1; i < n; i++) {
|
|
24
|
-
const v = Math.abs(M[i][k]);
|
|
25
|
-
v > maxVal && (maxVal = v, maxRow = i);
|
|
26
|
-
}
|
|
27
|
-
if (maxRow !== k) {
|
|
28
|
-
const tmp = M[k];
|
|
29
|
-
M[k] = M[maxRow], M[maxRow] = tmp;
|
|
30
|
-
}
|
|
31
|
-
// singular check
|
|
32
|
-
if (Math.abs(M[k][k]) < 1e-12) {
|
|
33
|
-
return new Array(n).fill(0);
|
|
34
|
-
}
|
|
35
|
-
// normalize row
|
|
36
|
-
for (let j = k + 1; j <= n; j++) M[k][j] = M[k][j] / M[k][k];
|
|
37
|
-
M[k][k] = 1;
|
|
38
|
-
// eliminate
|
|
39
|
-
for (let i = 0; i < n; i++) {
|
|
40
|
-
if (i === k) continue;
|
|
41
|
-
const factor = M[i][k];
|
|
42
|
-
if (0 !== factor) {
|
|
43
|
-
for (let j = k + 1; j <= n; j++) M[i][j] -= factor * M[k][j];
|
|
44
|
-
M[i][k] = 0;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
const x = new Array(n);
|
|
49
|
-
for (let i = 0; i < n; i++) x[i] = M[i][n];
|
|
50
|
-
return x;
|
|
51
|
-
}
|
|
7
|
+
const regression_linear_1 = require("./regression-linear"), regression_solver_1 = require("./regression-solver"), regression_utils_1 = require("./regression-utils");
|
|
52
8
|
|
|
53
9
|
function regressionPolynomial(data, x = (d => d.x), y = (d => d.y), options = {}) {
|
|
54
10
|
var _a, _b;
|
|
55
|
-
|
|
56
|
-
degree < 0
|
|
57
|
-
const alpha = null !== (_b = options.alpha) && void 0 !== _b ? _b : .05,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
for (let k = 0; k < sums.length; k++) sums[k] += xp, xp *= dx;
|
|
61
|
-
}));
|
|
62
|
-
// build normal matrix
|
|
63
|
-
const A = new Array(m);
|
|
64
|
-
for (let i = 0; i < m; i++) {
|
|
65
|
-
A[i] = new Array(m).fill(0);
|
|
66
|
-
for (let j = 0; j < m; j++) A[i][j] = sums[i + j];
|
|
67
|
-
}
|
|
68
|
-
const B = new Array(m).fill(0);
|
|
69
|
-
(0, regression_linear_1.visitPoints)(data, x, y, ((dx, dy) => {
|
|
70
|
-
let xp = 1;
|
|
71
|
-
for (let k = 0; k < m; k++) B[k] += dy * xp, xp *= dx;
|
|
72
|
-
}));
|
|
73
|
-
const coef = solveLinearSystem(A, B), predict = xx => {
|
|
74
|
-
let xp = 1, v = 0;
|
|
75
|
-
for (let k = 0; k < coef.length; k++) v += coef[k] * xp, xp *= xx;
|
|
76
|
-
return v;
|
|
77
|
-
};
|
|
11
|
+
const degree = null !== (_a = options.degree) && void 0 !== _a ? _a : 0;
|
|
12
|
+
if (!Number.isInteger(degree) || degree < 0) throw new RangeError("Polynomial degree must be an nonnegative integer");
|
|
13
|
+
const alpha = null !== (_b = options.alpha) && void 0 !== _b ? _b : .05, points = (0,
|
|
14
|
+
regression_solver_1.regressionPoints)(data, x, y), model = (0, regression_solver_1.fitRegression)(points, degree), coef = (0,
|
|
15
|
+
regression_solver_1.regressionCoefficients)(model), predict = xx => (0, regression_solver_1.regressionPrediction)(model, xx);
|
|
78
16
|
return {
|
|
79
17
|
degree: degree,
|
|
18
|
+
rank: model.rank,
|
|
80
19
|
coef: coef,
|
|
81
20
|
predict: predict,
|
|
82
21
|
rSquared: (0, regression_linear_1.rSquared)(data, x, y, (() => {
|
|
@@ -87,30 +26,10 @@ function regressionPolynomial(data, x = (d => d.x), y = (d => d.y), options = {}
|
|
|
87
26
|
})), 0 === cnt ? 0 : sum / cnt;
|
|
88
27
|
})(), predict),
|
|
89
28
|
evaluateGrid(N) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if ((0, regression_linear_1.visitPoints)(data, x, y, (dx => {
|
|
95
|
-
(0, isNil_1.default)(dx) || (dx < min && (min = dx), dx > max && (max = dx));
|
|
96
|
-
})), min === 1 / 0 || max === -1 / 0) return out;
|
|
97
|
-
if (min === max) {
|
|
98
|
-
const v = predict(min);
|
|
99
|
-
for (let i = 0; i < N; i++) out.push({
|
|
100
|
-
x: min,
|
|
101
|
-
y: v
|
|
102
|
-
});
|
|
103
|
-
return out;
|
|
104
|
-
}
|
|
105
|
-
const step = (max - min) / (N - 1);
|
|
106
|
-
for (let i = 0; i < N; i++) {
|
|
107
|
-
const px = i === N - 1 ? max : min + step * i;
|
|
108
|
-
out.push({
|
|
109
|
-
x: px,
|
|
110
|
-
y: predict(px)
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
return out;
|
|
29
|
+
let min = 1 / 0, max = -1 / 0;
|
|
30
|
+
return points.forEach((p => {
|
|
31
|
+
min = Math.min(min, p.x), max = Math.max(max, p.x);
|
|
32
|
+
})), (0, regression_solver_1.regressionGrid)(min, max, N, predict);
|
|
114
33
|
},
|
|
115
34
|
confidenceInterval(N = 50) {
|
|
116
35
|
const out = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/common/regression-polynomial.ts"],"names":[],"mappings":"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","file":"regression-polynomial.js","sourcesContent":["import { visitPoints, rSquared } from './regression-linear';\nimport isNil from './isNil';\nimport {\n computeLinearCIComponents,\n confidenceCriticalValue,\n confidenceHalfWidth,\n stdErrorsAt\n} from './regression-utils';\n\nfunction solveLinearSystem(A: number[][], b: number[]): number[] {\n // Gaussian elimination with partial pivoting\n const n = b.length;\n // clone\n const M: number[][] = new Array(n);\n for (let i = 0; i < n; i++) {\n M[i] = A[i].slice();\n M[i].push(b[i]);\n }\n\n for (let k = 0; k < n; k++) {\n // find pivot\n let maxRow = k;\n let maxVal = Math.abs(M[k][k]);\n for (let i = k + 1; i < n; i++) {\n const v = Math.abs(M[i][k]);\n if (v > maxVal) {\n maxVal = v;\n maxRow = i;\n }\n }\n if (maxRow !== k) {\n const tmp = M[k];\n M[k] = M[maxRow];\n M[maxRow] = tmp;\n }\n\n // singular check\n if (Math.abs(M[k][k]) < 1e-12) {\n // return least squares fallback zeros\n const res: number[] = new Array(n).fill(0);\n return res;\n }\n\n // normalize row\n for (let j = k + 1; j <= n; j++) {\n M[k][j] = M[k][j] / M[k][k];\n }\n M[k][k] = 1;\n\n // eliminate\n for (let i = 0; i < n; i++) {\n if (i === k) {\n continue;\n }\n const factor = M[i][k];\n if (factor === 0) {\n continue;\n }\n for (let j = k + 1; j <= n; j++) {\n M[i][j] -= factor * M[k][j];\n }\n M[i][k] = 0;\n }\n }\n\n const x: number[] = new Array(n);\n for (let i = 0; i < n; i++) {\n x[i] = M[i][n];\n }\n return x;\n}\n\nexport function regressionPolynomial(\n data: any[],\n x: (d: any) => number = d => d.x,\n y: (d: any) => number = d => d.y,\n options: { degree?: number; alpha?: number } = {}\n) {\n let degree = options.degree ?? 0;\n if (degree < 0) {\n degree = 0;\n }\n const alpha = options.alpha ?? 0.05;\n const m = degree + 1;\n const sums: number[] = new Array(2 * degree + 1).fill(0);\n\n visitPoints(data, x, y, (dx, dy) => {\n let xp = 1;\n for (let k = 0; k < sums.length; k++) {\n sums[k] += xp;\n xp *= dx;\n }\n });\n\n // build normal matrix\n const A: number[][] = new Array(m);\n for (let i = 0; i < m; i++) {\n A[i] = new Array(m).fill(0);\n for (let j = 0; j < m; j++) {\n A[i][j] = sums[i + j];\n }\n }\n\n const B: number[] = new Array(m).fill(0);\n visitPoints(data, x, y, (dx, dy) => {\n let xp = 1;\n for (let k = 0; k < m; k++) {\n B[k] += dy * xp;\n xp *= dx;\n }\n });\n\n const coef = solveLinearSystem(A, B);\n\n const predict = (xx: number) => {\n let xp = 1;\n let v = 0;\n for (let k = 0; k < coef.length; k++) {\n v += coef[k] * xp;\n xp *= xx;\n }\n return v;\n };\n\n return {\n degree,\n coef,\n predict,\n rSquared: rSquared(\n data,\n x,\n y,\n (() => {\n // compute mean y\n let sum = 0;\n let cnt = 0;\n visitPoints(data, x, y, (_dx, dy) => {\n sum += dy;\n cnt++;\n });\n return cnt === 0 ? 0 : sum / cnt;\n })(),\n predict\n ),\n evaluateGrid(N: number) {\n const out: { x: number; y: number }[] = [];\n if (N <= 0) {\n return out;\n }\n // compute range\n let min = Infinity;\n let max = -Infinity;\n visitPoints(data, x, y, dx => {\n if (!isNil(dx)) {\n if (dx < min) {\n min = dx;\n }\n if (dx > max) {\n max = dx;\n }\n }\n });\n if (min === Infinity || max === -Infinity) {\n return out;\n }\n if (min === max) {\n const v = predict(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 for (let i = 0; i < N; i++) {\n const px = i === N - 1 ? max : min + step * i;\n out.push({ x: px, y: predict(px) });\n }\n return out;\n },\n 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\n const comps = computeLinearCIComponents(data, x, y, predict);\n if (comps.n === 0) {\n return out;\n }\n\n const z = confidenceCriticalValue(alpha);\n if (comps.min === comps.max) {\n const v = predict(comps.min);\n const errs = stdErrorsAt(comps.min, comps);\n const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n for (let i = 0; i < N; i++) {\n out.push({\n x: comps.min,\n mean: v,\n lower: v - meanHalfWidth,\n upper: v + meanHalfWidth,\n predLower: v - predHalfWidth,\n predUpper: v + predHalfWidth\n });\n }\n return out;\n }\n\n const step = (comps.max - comps.min) / (N - 1);\n for (let i = 0; i < N; i++) {\n const px = i === N - 1 ? comps.max : comps.min + step * i;\n const yh = predict(px);\n const errs = stdErrorsAt(px, comps);\n const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n out.push({\n x: px,\n mean: yh,\n lower: yh - meanHalfWidth,\n upper: yh + meanHalfWidth,\n predLower: yh - predHalfWidth,\n predUpper: yh + predHalfWidth\n });\n }\n return out;\n }\n };\n}\n\nexport default regressionPolynomial;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/common/regression-polynomial.ts"],"names":[],"mappings":"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","file":"regression-polynomial.js","sourcesContent":["import { visitPoints, rSquared } from './regression-linear';\nimport {\n regressionPoints,\n fitRegression,\n regressionPrediction,\n regressionCoefficients,\n regressionGrid\n} from './regression-solver';\nimport {\n computeLinearCIComponents,\n confidenceCriticalValue,\n confidenceHalfWidth,\n stdErrorsAt\n} from './regression-utils';\n\nexport function regressionPolynomial(\n data: any[],\n x: (d: any) => number = d => d.x,\n y: (d: any) => number = d => d.y,\n options: { degree?: number; alpha?: number } = {}\n) {\n const degree = options.degree ?? 0;\n if (!Number.isInteger(degree) || degree < 0) {\n throw new RangeError('Polynomial degree must be an nonnegative integer');\n }\n const alpha = options.alpha ?? 0.05;\n const points = regressionPoints(data, x, y);\n const model = fitRegression(points, degree);\n const coef = regressionCoefficients(model);\n const predict = (xx: number) => regressionPrediction(model, xx);\n\n return {\n degree,\n rank: model.rank,\n coef,\n predict,\n rSquared: rSquared(\n data,\n x,\n y,\n (() => {\n // compute mean y\n let sum = 0;\n let cnt = 0;\n visitPoints(data, x, y, (_dx, dy) => {\n sum += dy;\n cnt++;\n });\n return cnt === 0 ? 0 : sum / cnt;\n })(),\n predict\n ),\n evaluateGrid(N: number) {\n let min = Infinity;\n let max = -Infinity;\n points.forEach(p => {\n min = Math.min(min, p.x);\n max = Math.max(max, p.x);\n });\n return regressionGrid(min, max, N, predict);\n },\n 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\n const comps = computeLinearCIComponents(data, x, y, predict);\n if (comps.n === 0) {\n return out;\n }\n\n const z = confidenceCriticalValue(alpha);\n if (comps.min === comps.max) {\n const v = predict(comps.min);\n const errs = stdErrorsAt(comps.min, comps);\n const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n for (let i = 0; i < N; i++) {\n out.push({\n x: comps.min,\n mean: v,\n lower: v - meanHalfWidth,\n upper: v + meanHalfWidth,\n predLower: v - predHalfWidth,\n predUpper: v + predHalfWidth\n });\n }\n return out;\n }\n\n const step = (comps.max - comps.min) / (N - 1);\n for (let i = 0; i < N; i++) {\n const px = i === N - 1 ? comps.max : comps.min + step * i;\n const yh = predict(px);\n const errs = stdErrorsAt(px, comps);\n const meanHalfWidth = confidenceHalfWidth(z, errs.seMean);\n const predHalfWidth = confidenceHalfWidth(z, errs.sePred);\n out.push({\n x: px,\n mean: yh,\n lower: yh - meanHalfWidth,\n upper: yh + meanHalfWidth,\n predLower: yh - predHalfWidth,\n predUpper: yh + predHalfWidth\n });\n }\n return out;\n }\n };\n}\n\nexport default regressionPolynomial;\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** 回归共用的稳定坐标与小型最小二乘求解器;不构造 XᵀX。 */
|
|
2
|
+
export interface RegressionPoint {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
}
|
|
6
|
+
export interface RegressionBasis {
|
|
7
|
+
xCenter: number;
|
|
8
|
+
xScale: number;
|
|
9
|
+
yCenter: number;
|
|
10
|
+
yScale: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function regressionPoints(data: readonly any[], x: (d: any) => number, y: (d: any) => number): RegressionPoint[];
|
|
13
|
+
export declare function normalizeRegression(value: number, center: number, scale: number): number;
|
|
14
|
+
export declare function regressionBasis(points: readonly RegressionPoint[]): RegressionBasis;
|
|
15
|
+
export declare function fitRegression(points: readonly RegressionPoint[], degree: number, basis?: RegressionBasis): {
|
|
16
|
+
coef: number[];
|
|
17
|
+
rank: number;
|
|
18
|
+
basis: RegressionBasis;
|
|
19
|
+
};
|
|
20
|
+
export declare function regressionPrediction(model: ReturnType<typeof fitRegression>, x: number): number;
|
|
21
|
+
/** 保留公开的升幂 coef;预测始终使用稳定基底。 */
|
|
22
|
+
export declare function regressionCoefficients(model: ReturnType<typeof fitRegression>): number[];
|
|
23
|
+
export declare function regressionGrid(min: number, max: number, count: number, predict: (x: number) => number): {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
}[];
|