@visactor/vutils 1.0.26 → 1.0.27
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/ascending.js +1 -2
- package/cjs/common/deviation.js +2 -1
- package/cjs/common/getType.js +1 -2
- package/cjs/common/isFunction.js +2 -1
- package/cjs/common/isObject.js +1 -2
- 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/kde.d.ts +4 -0
- package/cjs/common/kde.js +25 -14
- package/cjs/common/kde.js.map +1 -1
- package/cjs/data-structure/bounds.js +1 -1
- package/cjs/data-structure/hashTable.js +2 -1
- 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 +65 -38
- package/dist/index.min.js +15 -15
- package/es/common/ascending.js +1 -2
- package/es/common/deviation.js +2 -1
- package/es/common/getType.js +1 -2
- package/es/common/isFunction.js +2 -1
- package/es/common/isObject.js +1 -2
- 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/kde.d.ts +4 -0
- package/es/common/kde.js +29 -14
- package/es/common/kde.js.map +1 -1
- package/es/data-structure/bounds.js +1 -1
- package/es/data-structure/hashTable.js +2 -1
- 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 +4 -5
- package/REGRESSION.md +0 -36
package/cjs/common/ascending.js
CHANGED
package/cjs/common/deviation.js
CHANGED
package/cjs/common/getType.js
CHANGED
package/cjs/common/isFunction.js
CHANGED
|
@@ -32,4 +32,5 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
32
32
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
33
33
|
const isFunction = value => "function" == typeof value;
|
|
34
34
|
|
|
35
|
-
exports.default = isFunction;
|
|
35
|
+
exports.default = isFunction;
|
|
36
|
+
//# sourceMappingURL=isFunction.js.map
|
package/cjs/common/isObject.js
CHANGED
package/cjs/common/isRegExp.js
CHANGED
|
@@ -13,4 +13,4 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
13
13
|
const isType_1 = __importDefault(require("./isType")), isRegExp = value => (0, isType_1.default)(value, "RegExp");
|
|
14
14
|
|
|
15
15
|
exports.default = isRegExp;
|
|
16
|
-
//# sourceMappingURL=isRegExp.js.map
|
|
16
|
+
//# sourceMappingURL=isRegExp.js.map
|
package/cjs/common/isString.js
CHANGED
package/cjs/common/isType.js
CHANGED
package/cjs/common/kde.d.ts
CHANGED
|
@@ -22,6 +22,10 @@ export interface KDEOptions {
|
|
|
22
22
|
kernel?: Kernel;
|
|
23
23
|
bandwidth?: number;
|
|
24
24
|
bandwidthMethod?: 'scott' | 'silverman';
|
|
25
|
+
/** Automatic bandwidth uses population deviation by default, preserving existing behavior. */
|
|
26
|
+
standardDeviation?: 'sample' | 'population';
|
|
27
|
+
/** Positive multiplier applied once to either fixed or automatic bandwidth. */
|
|
28
|
+
bandwidthAdjust?: number;
|
|
25
29
|
}
|
|
26
30
|
export interface KDEEvaluator {
|
|
27
31
|
bandwidth: number;
|
package/cjs/common/kde.js
CHANGED
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
value: !0
|
|
12
12
|
}), exports.kde = exports.silverman = exports.scott = exports.epanechnikov = exports.gaussian = void 0;
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
const gaussian = u => 1 / Math.sqrt(2 * Math.PI) * Math.exp(-.5 * u * u);
|
|
14
|
+
const mean_1 = require("./mean"), variance_1 = require("./variance"), gaussian = u => 1 / Math.sqrt(2 * Math.PI) * Math.exp(-.5 * u * u);
|
|
16
15
|
|
|
17
16
|
exports.gaussian = gaussian;
|
|
18
17
|
|
|
@@ -36,32 +35,44 @@ function silverman(n, std, dim = 1) {
|
|
|
36
35
|
/**
|
|
37
36
|
* Compute standard deviation for numeric array
|
|
38
37
|
*/
|
|
39
|
-
function std(values) {
|
|
38
|
+
function std(values, convention) {
|
|
40
39
|
const n = values.length;
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
mean /= n;
|
|
45
|
-
let s = 0;
|
|
40
|
+
if (n < 2) return 0;
|
|
41
|
+
const center = (0, mean_1.mean)(values), differences = [];
|
|
42
|
+
let scale = 0, sourceScale = 1;
|
|
46
43
|
for (let i = 0; i < n; i++) {
|
|
47
|
-
const
|
|
48
|
-
|
|
44
|
+
const difference = values[i] - center;
|
|
45
|
+
differences.push(difference), scale = Math.max(scale, Math.abs(difference));
|
|
49
46
|
}
|
|
50
|
-
|
|
47
|
+
// Finite values of opposite signs can overflow subtraction although population deviation is representable.
|
|
48
|
+
if (scale === 1 / 0) {
|
|
49
|
+
sourceScale = Math.abs(center);
|
|
50
|
+
for (const value of values) sourceScale = Math.max(sourceScale, Math.abs(value));
|
|
51
|
+
scale = 0;
|
|
52
|
+
for (let i = 0; i < n; i++) differences[i] = values[i] / sourceScale - center / sourceScale,
|
|
53
|
+
scale = Math.max(scale, Math.abs(differences[i]));
|
|
54
|
+
}
|
|
55
|
+
if (0 === scale) return 0;
|
|
56
|
+
for (let i = 0; i < n; i++) differences[i] /= scale;
|
|
57
|
+
const correction = "population" === convention ? (n - 1) / n : 1;
|
|
58
|
+
return Math.sqrt((0, variance_1.variance)(differences) * correction) * scale * sourceScale;
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
/**
|
|
54
62
|
* Factory: create a KDE evaluator for given data and options.
|
|
55
63
|
* Usage: const model = kde(data, options); model.evaluate(x) or model.evaluate([x1,x2])
|
|
56
64
|
*/ function kde(data, options = {}) {
|
|
65
|
+
const deviation = void 0 === options.standardDeviation ? "population" : options.standardDeviation, adjustment = void 0 === options.bandwidthAdjust ? 1 : options.bandwidthAdjust;
|
|
66
|
+
if ("sample" !== deviation && "population" !== deviation) throw new RangeError("standardDeviation must be sample or population");
|
|
67
|
+
if (!Number.isFinite(adjustment) || adjustment <= 0) throw new RangeError("bandwidthAdjust must be finite and positive");
|
|
57
68
|
const n = data.length, kernel = options.kernel || exports.gaussian;
|
|
58
69
|
let h = options.bandwidth;
|
|
59
70
|
if (!h || h <= 0) {
|
|
60
|
-
const sd = std(data) || 0, method = options.bandwidthMethod || "scott";
|
|
71
|
+
const sd = std(data, deviation) || 0, method = options.bandwidthMethod || "scott";
|
|
61
72
|
h = "silverman" === method ? silverman(n, sd, 1) : scott(n, sd, 1);
|
|
62
73
|
}
|
|
63
74
|
// if still zero (constant data), evaluator returns zeros
|
|
64
|
-
|
|
75
|
+
if (h *= adjustment, !h || h <= 0) {
|
|
65
76
|
return {
|
|
66
77
|
bandwidth: 0,
|
|
67
78
|
kernel: kernel,
|
|
@@ -97,7 +108,7 @@ function std(values) {
|
|
|
97
108
|
}
|
|
98
109
|
};
|
|
99
110
|
}
|
|
100
|
-
const invNh = 1 /
|
|
111
|
+
const invNh = 1 / n / h;
|
|
101
112
|
function evalPoint(x) {
|
|
102
113
|
let sum = 0;
|
|
103
114
|
for (let j = 0; j < n; j++) sum += kernel((x - data[j]) / h);
|
package/cjs/common/kde.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/common/kde.ts"],"names":[],"mappings":"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","file":"kde.js","sourcesContent":["/**\n * Kernel Density Estimation (KDE) utilities\n *\n * Exports:\n * - Kernel functions: gaussian, epanechnikov\n * - bandwidth selectors: scott, silverman\n * - kde: main function to compute density estimates at provided points\n */\n\nexport type Kernel = (u: number) => number;\n\n/** Gaussian kernel (standard normal) */\nexport const gaussian: Kernel = (u: number) => {\n const invSqrt2Pi = 1 / Math.sqrt(2 * Math.PI);\n return invSqrt2Pi * Math.exp(-0.5 * u * u);\n};\n\n/** Epanechnikov kernel (compact support) */\nexport const epanechnikov: Kernel = (u: number) => {\n const absu = Math.abs(u);\n return absu <= 1 ? 0.75 * (1 - u * u) : 0;\n};\n\n/**\n * Bandwidth selectors\n * - scott: h = n^{-1/(d+4)} * std\n * - silverman: h = ( (4/(d+2))^{1/(d+4)} ) * n^{-1/(d+4)} * std\n */\nexport function scott(n: number, std: number, dim = 1) {\n if (n <= 0 || std === 0) {\n return 0;\n }\n return std * Math.pow(n, -1 / (dim + 4));\n}\n\nexport function silverman(n: number, std: number, dim = 1) {\n if (n <= 0 || std === 0) {\n return 0;\n }\n const factor = Math.pow(4 / (dim + 2), 1 / (dim + 4));\n return factor * std * Math.pow(n, -1 / (dim + 4));\n}\n\nexport interface KDEOptions {\n kernel?: Kernel;\n bandwidth?: number; // fixed bandwidth\n bandwidthMethod?: 'scott' | 'silverman';\n // if bandwidth not provided, compute from data using method\n}\n\n/**\n * Compute standard deviation for numeric array\n */\nfunction std(values: number[]) {\n const n = values.length;\n if (n === 0) {\n return 0;\n }\n let mean = 0;\n for (let i = 0; i < n; i++) {\n mean += values[i];\n }\n mean /= n;\n let s = 0;\n for (let i = 0; i < n; i++) {\n const d = values[i] - mean;\n s += d * d;\n }\n return Math.sqrt(s / n);\n}\n\nexport interface KDEEvaluator {\n bandwidth: number;\n kernel: Kernel;\n /**\n * Evaluate density at a single point or array of points.\n * - If given a number, returns a number.\n * - If given an array, returns an array aligned with input.\n */\n evaluate: ((x: number) => number) & ((xs: number[]) => number[]);\n /**\n * Produce N uniformly spaced points across the data range and evaluate densities.\n * Returns an array { x: number, y: number }[].\n */\n evaluateGrid: (N: number) => { x: number; y: number }[];\n}\n\n/**\n * Factory: create a KDE evaluator for given data and options.\n * Usage: const model = kde(data, options); model.evaluate(x) or model.evaluate([x1,x2])\n */\nexport function kde(data: number[], options: KDEOptions = {}): KDEEvaluator {\n const n = data.length;\n const kernel = options.kernel || gaussian;\n\n let h = options.bandwidth;\n if (!h || h <= 0) {\n const sd = std(data) || 0;\n const method = options.bandwidthMethod || 'scott';\n if (method === 'silverman') {\n h = silverman(n, sd, 1);\n } else {\n h = scott(n, sd, 1);\n }\n }\n\n // if still zero (constant data), evaluator returns zeros\n if (!h || h <= 0) {\n const zerosEval = (x: number | number[]) => {\n if (Array.isArray(x)) {\n const out: number[] = [];\n for (let i = 0; i < x.length; i++) {\n out.push(0);\n }\n return out;\n }\n return 0;\n };\n const zerosGrid = (N: number) => {\n const out: { x: number; y: number }[] = [];\n if (N <= 0) {\n return out;\n }\n // compute data min (use data range if available)\n let min = Infinity;\n let max = -Infinity;\n for (let j = 0; j < n; j++) {\n const v = data[j];\n if (v < min) {\n min = v;\n }\n if (v > max) {\n max = v;\n }\n }\n if (min === Infinity || max === -Infinity) {\n for (let i = 0; i < N; i++) {\n out.push({ x: 0, y: 0 });\n }\n return out;\n }\n for (let i = 0; i < N; i++) {\n out.push({ x: min, y: 0 });\n }\n return out;\n };\n return {\n bandwidth: 0,\n kernel,\n evaluate: zerosEval as any,\n evaluateGrid: zerosGrid\n };\n }\n\n const invNh = 1 / (n * h);\n\n function evalPoint(x: number) {\n let sum = 0;\n for (let j = 0; j < n; j++) {\n sum += kernel((x - data[j]) / h);\n }\n return sum * invNh;\n }\n\n function evaluate(x: number | number[]) {\n if (Array.isArray(x)) {\n const out: number[] = [];\n for (let i = 0; i < x.length; i++) {\n out.push(evalPoint(x[i]));\n }\n return out;\n }\n return evalPoint(x as number);\n }\n\n return {\n bandwidth: h,\n kernel,\n evaluate: evaluate as any,\n evaluateGrid(N: number) {\n const out: { x: number; y: number }[] = [];\n if (N <= 0) {\n return out;\n }\n // compute data range\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < n; i++) {\n const v = data[i];\n if (v < min) {\n min = v;\n }\n if (v > max) {\n max = v;\n }\n }\n if (min === Infinity || max === -Infinity) {\n return out;\n }\n if (min === max) {\n // single point repeated\n for (let i = 0; i < N; i++) {\n out.push({ x: min, y: evalPoint(min) });\n }\n return out;\n }\n\n const step = (max - min) / (N - 1);\n for (let i = 0; i < N; i++) {\n const x = i === N - 1 ? max : min + step * i;\n out.push({ x, y: evalPoint(x) });\n }\n return out;\n }\n };\n}\n\nexport default kde;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/common/kde.ts"],"names":[],"mappings":"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","file":"kde.js","sourcesContent":["/**\n * Kernel Density Estimation (KDE) utilities\n *\n * Exports:\n * - Kernel functions: gaussian, epanechnikov\n * - bandwidth selectors: scott, silverman\n * - kde: main function to compute density estimates at provided points\n */\n\nimport { mean } from './mean';\nimport { variance } from './variance';\n\nexport type Kernel = (u: number) => number;\n\n/** Gaussian kernel (standard normal) */\nexport const gaussian: Kernel = (u: number) => {\n const invSqrt2Pi = 1 / Math.sqrt(2 * Math.PI);\n return invSqrt2Pi * Math.exp(-0.5 * u * u);\n};\n\n/** Epanechnikov kernel (compact support) */\nexport const epanechnikov: Kernel = (u: number) => {\n const absu = Math.abs(u);\n return absu <= 1 ? 0.75 * (1 - u * u) : 0;\n};\n\n/**\n * Bandwidth selectors\n * - scott: h = n^{-1/(d+4)} * std\n * - silverman: h = ( (4/(d+2))^{1/(d+4)} ) * n^{-1/(d+4)} * std\n */\nexport function scott(n: number, std: number, dim = 1) {\n if (n <= 0 || std === 0) {\n return 0;\n }\n return std * Math.pow(n, -1 / (dim + 4));\n}\n\nexport function silverman(n: number, std: number, dim = 1) {\n if (n <= 0 || std === 0) {\n return 0;\n }\n const factor = Math.pow(4 / (dim + 2), 1 / (dim + 4));\n return factor * std * Math.pow(n, -1 / (dim + 4));\n}\n\nexport interface KDEOptions {\n kernel?: Kernel;\n bandwidth?: number; // fixed bandwidth\n bandwidthMethod?: 'scott' | 'silverman';\n /** Automatic bandwidth uses population deviation by default, preserving existing behavior. */\n standardDeviation?: 'sample' | 'population';\n /** Positive multiplier applied once to either fixed or automatic bandwidth. */\n bandwidthAdjust?: number;\n // if bandwidth not provided, compute from data using method\n}\n\n/**\n * Compute standard deviation for numeric array\n */\nfunction std(values: number[], convention: 'sample' | 'population') {\n const n = values.length;\n if (n < 2) {\n return 0;\n }\n const center = mean(values);\n const differences: number[] = [];\n let scale = 0;\n let sourceScale = 1;\n for (let i = 0; i < n; i++) {\n const difference = values[i] - center;\n differences.push(difference);\n scale = Math.max(scale, Math.abs(difference));\n }\n // Finite values of opposite signs can overflow subtraction although population deviation is representable.\n if (scale === Infinity) {\n sourceScale = Math.abs(center);\n for (const value of values) {\n sourceScale = Math.max(sourceScale, Math.abs(value));\n }\n scale = 0;\n for (let i = 0; i < n; i++) {\n differences[i] = values[i] / sourceScale - center / sourceScale;\n scale = Math.max(scale, Math.abs(differences[i]));\n }\n }\n if (scale === 0) {\n return 0;\n }\n for (let i = 0; i < n; i++) {\n differences[i] /= scale;\n }\n const correction = convention === 'population' ? (n - 1) / n : 1;\n return Math.sqrt(variance(differences) * correction) * scale * sourceScale;\n}\n\nexport interface KDEEvaluator {\n bandwidth: number;\n kernel: Kernel;\n /**\n * Evaluate density at a single point or array of points.\n * - If given a number, returns a number.\n * - If given an array, returns an array aligned with input.\n */\n evaluate: ((x: number) => number) & ((xs: number[]) => number[]);\n /**\n * Produce N uniformly spaced points across the data range and evaluate densities.\n * Returns an array { x: number, y: number }[].\n */\n evaluateGrid: (N: number) => { x: number; y: number }[];\n}\n\n/**\n * Factory: create a KDE evaluator for given data and options.\n * Usage: const model = kde(data, options); model.evaluate(x) or model.evaluate([x1,x2])\n */\nexport function kde(data: number[], options: KDEOptions = {}): KDEEvaluator {\n const deviation = options.standardDeviation === undefined ? 'population' : options.standardDeviation;\n const adjustment = options.bandwidthAdjust === undefined ? 1 : options.bandwidthAdjust;\n if (deviation !== 'sample' && deviation !== 'population') {\n throw new RangeError('standardDeviation must be sample or population');\n }\n if (!Number.isFinite(adjustment) || adjustment <= 0) {\n throw new RangeError('bandwidthAdjust must be finite and positive');\n }\n const n = data.length;\n const kernel = options.kernel || gaussian;\n\n let h = options.bandwidth;\n if (!h || h <= 0) {\n const sd = std(data, deviation) || 0;\n const method = options.bandwidthMethod || 'scott';\n if (method === 'silverman') {\n h = silverman(n, sd, 1);\n } else {\n h = scott(n, sd, 1);\n }\n }\n h *= adjustment;\n\n // if still zero (constant data), evaluator returns zeros\n if (!h || h <= 0) {\n const zerosEval = (x: number | number[]) => {\n if (Array.isArray(x)) {\n const out: number[] = [];\n for (let i = 0; i < x.length; i++) {\n out.push(0);\n }\n return out;\n }\n return 0;\n };\n const zerosGrid = (N: number) => {\n const out: { x: number; y: number }[] = [];\n if (N <= 0) {\n return out;\n }\n // compute data min (use data range if available)\n let min = Infinity;\n let max = -Infinity;\n for (let j = 0; j < n; j++) {\n const v = data[j];\n if (v < min) {\n min = v;\n }\n if (v > max) {\n max = v;\n }\n }\n if (min === Infinity || max === -Infinity) {\n for (let i = 0; i < N; i++) {\n out.push({ x: 0, y: 0 });\n }\n return out;\n }\n for (let i = 0; i < N; i++) {\n out.push({ x: min, y: 0 });\n }\n return out;\n };\n return {\n bandwidth: 0,\n kernel,\n evaluate: zerosEval as any,\n evaluateGrid: zerosGrid\n };\n }\n\n const invNh = 1 / n / h;\n\n function evalPoint(x: number) {\n let sum = 0;\n for (let j = 0; j < n; j++) {\n sum += kernel((x - data[j]) / h);\n }\n return sum * invNh;\n }\n\n function evaluate(x: number | number[]) {\n if (Array.isArray(x)) {\n const out: number[] = [];\n for (let i = 0; i < x.length; i++) {\n out.push(evalPoint(x[i]));\n }\n return out;\n }\n return evalPoint(x as number);\n }\n\n return {\n bandwidth: h,\n kernel,\n evaluate: evaluate as any,\n evaluateGrid(N: number) {\n const out: { x: number; y: number }[] = [];\n if (N <= 0) {\n return out;\n }\n // compute data range\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < n; i++) {\n const v = data[i];\n if (v < min) {\n min = v;\n }\n if (v > max) {\n max = v;\n }\n }\n if (min === Infinity || max === -Infinity) {\n return out;\n }\n if (min === max) {\n // single point repeated\n for (let i = 0; i < N; i++) {\n out.push({ x: min, y: evalPoint(min) });\n }\n return out;\n }\n\n const step = (max - min) / (N - 1);\n for (let i = 0; i < N; i++) {\n const x = i === N - 1 ? max : min + step * i;\n out.push({ x, y: evalPoint(x) });\n }\n return out;\n }\n };\n}\n\nexport default kde;\n"]}
|
|
@@ -23,4 +23,4 @@ __exportStar(require("./hashTable"), exports),
|
|
|
23
23
|
// Point
|
|
24
24
|
__exportStar(require("./point"), exports), __exportStar(require("./bounds"), exports),
|
|
25
25
|
__exportStar(require("./matrix"), exports);
|
|
26
|
-
//# sourceMappingURL=index.js.map
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js
CHANGED
|
@@ -3145,6 +3145,33 @@
|
|
|
3145
3145
|
};
|
|
3146
3146
|
}
|
|
3147
3147
|
|
|
3148
|
+
/** 有限数值的均值;空输入没有均值,不修改输入。 */
|
|
3149
|
+
function mean(values) {
|
|
3150
|
+
if (!values.length) {
|
|
3151
|
+
return undefined;
|
|
3152
|
+
}
|
|
3153
|
+
let scale = 0;
|
|
3154
|
+
for (const value of values) {
|
|
3155
|
+
if (!Number.isFinite(value)) {
|
|
3156
|
+
throw new RangeError('mean requires finite numbers');
|
|
3157
|
+
}
|
|
3158
|
+
scale = Math.max(scale, Math.abs(value));
|
|
3159
|
+
}
|
|
3160
|
+
if (scale === 0) {
|
|
3161
|
+
return 0;
|
|
3162
|
+
}
|
|
3163
|
+
let sum = 0;
|
|
3164
|
+
let correction = 0;
|
|
3165
|
+
for (const value of values) {
|
|
3166
|
+
const next = value / scale;
|
|
3167
|
+
const total = sum + next;
|
|
3168
|
+
// Neumaier compensation retains small contributions even when larger values cancel.
|
|
3169
|
+
correction += Math.abs(sum) >= Math.abs(next) ? sum - total + next : next - total + sum;
|
|
3170
|
+
sum = total;
|
|
3171
|
+
}
|
|
3172
|
+
return ((sum + correction) / values.length) * scale;
|
|
3173
|
+
}
|
|
3174
|
+
|
|
3148
3175
|
/**
|
|
3149
3176
|
* Kernel Density Estimation (KDE) utilities
|
|
3150
3177
|
*
|
|
@@ -3184,33 +3211,59 @@
|
|
|
3184
3211
|
/**
|
|
3185
3212
|
* Compute standard deviation for numeric array
|
|
3186
3213
|
*/
|
|
3187
|
-
function std(values) {
|
|
3214
|
+
function std(values, convention) {
|
|
3188
3215
|
const n = values.length;
|
|
3189
|
-
if (n
|
|
3216
|
+
if (n < 2) {
|
|
3190
3217
|
return 0;
|
|
3191
3218
|
}
|
|
3192
|
-
|
|
3219
|
+
const center = mean(values);
|
|
3220
|
+
const differences = [];
|
|
3221
|
+
let scale = 0;
|
|
3222
|
+
let sourceScale = 1;
|
|
3193
3223
|
for (let i = 0; i < n; i++) {
|
|
3194
|
-
|
|
3224
|
+
const difference = values[i] - center;
|
|
3225
|
+
differences.push(difference);
|
|
3226
|
+
scale = Math.max(scale, Math.abs(difference));
|
|
3227
|
+
}
|
|
3228
|
+
// Finite values of opposite signs can overflow subtraction although population deviation is representable.
|
|
3229
|
+
if (scale === Infinity) {
|
|
3230
|
+
sourceScale = Math.abs(center);
|
|
3231
|
+
for (const value of values) {
|
|
3232
|
+
sourceScale = Math.max(sourceScale, Math.abs(value));
|
|
3233
|
+
}
|
|
3234
|
+
scale = 0;
|
|
3235
|
+
for (let i = 0; i < n; i++) {
|
|
3236
|
+
differences[i] = values[i] / sourceScale - center / sourceScale;
|
|
3237
|
+
scale = Math.max(scale, Math.abs(differences[i]));
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
if (scale === 0) {
|
|
3241
|
+
return 0;
|
|
3195
3242
|
}
|
|
3196
|
-
mean /= n;
|
|
3197
|
-
let s = 0;
|
|
3198
3243
|
for (let i = 0; i < n; i++) {
|
|
3199
|
-
|
|
3200
|
-
s += d * d;
|
|
3244
|
+
differences[i] /= scale;
|
|
3201
3245
|
}
|
|
3202
|
-
|
|
3246
|
+
const correction = convention === 'population' ? (n - 1) / n : 1;
|
|
3247
|
+
return Math.sqrt(variance(differences) * correction) * scale * sourceScale;
|
|
3203
3248
|
}
|
|
3204
3249
|
/**
|
|
3205
3250
|
* Factory: create a KDE evaluator for given data and options.
|
|
3206
3251
|
* Usage: const model = kde(data, options); model.evaluate(x) or model.evaluate([x1,x2])
|
|
3207
3252
|
*/
|
|
3208
3253
|
function kde(data, options = {}) {
|
|
3254
|
+
const deviation = options.standardDeviation === undefined ? 'population' : options.standardDeviation;
|
|
3255
|
+
const adjustment = options.bandwidthAdjust === undefined ? 1 : options.bandwidthAdjust;
|
|
3256
|
+
if (deviation !== 'sample' && deviation !== 'population') {
|
|
3257
|
+
throw new RangeError('standardDeviation must be sample or population');
|
|
3258
|
+
}
|
|
3259
|
+
if (!Number.isFinite(adjustment) || adjustment <= 0) {
|
|
3260
|
+
throw new RangeError('bandwidthAdjust must be finite and positive');
|
|
3261
|
+
}
|
|
3209
3262
|
const n = data.length;
|
|
3210
3263
|
const kernel = options.kernel || gaussian;
|
|
3211
3264
|
let h = options.bandwidth;
|
|
3212
3265
|
if (!h || h <= 0) {
|
|
3213
|
-
const sd = std(data) || 0;
|
|
3266
|
+
const sd = std(data, deviation) || 0;
|
|
3214
3267
|
const method = options.bandwidthMethod || 'scott';
|
|
3215
3268
|
if (method === 'silverman') {
|
|
3216
3269
|
h = silverman(n, sd, 1);
|
|
@@ -3219,6 +3272,7 @@
|
|
|
3219
3272
|
h = scott(n, sd, 1);
|
|
3220
3273
|
}
|
|
3221
3274
|
}
|
|
3275
|
+
h *= adjustment;
|
|
3222
3276
|
// if still zero (constant data), evaluator returns zeros
|
|
3223
3277
|
if (!h || h <= 0) {
|
|
3224
3278
|
const zerosEval = (x) => {
|
|
@@ -3266,7 +3320,7 @@
|
|
|
3266
3320
|
evaluateGrid: zerosGrid
|
|
3267
3321
|
};
|
|
3268
3322
|
}
|
|
3269
|
-
const invNh = 1 /
|
|
3323
|
+
const invNh = 1 / n / h;
|
|
3270
3324
|
function evalPoint(x) {
|
|
3271
3325
|
let sum = 0;
|
|
3272
3326
|
for (let j = 0; j < n; j++) {
|
|
@@ -3523,33 +3577,6 @@
|
|
|
3523
3577
|
return method === 'kendall' ? kendall(x, y) : method === 'spearman' ? pearson(ranks(x), ranks(y)) : pearson(x, y);
|
|
3524
3578
|
}
|
|
3525
3579
|
|
|
3526
|
-
/** 有限数值的均值;空输入没有均值,不修改输入。 */
|
|
3527
|
-
function mean(values) {
|
|
3528
|
-
if (!values.length) {
|
|
3529
|
-
return undefined;
|
|
3530
|
-
}
|
|
3531
|
-
let scale = 0;
|
|
3532
|
-
for (const value of values) {
|
|
3533
|
-
if (!Number.isFinite(value)) {
|
|
3534
|
-
throw new RangeError('mean requires finite numbers');
|
|
3535
|
-
}
|
|
3536
|
-
scale = Math.max(scale, Math.abs(value));
|
|
3537
|
-
}
|
|
3538
|
-
if (scale === 0) {
|
|
3539
|
-
return 0;
|
|
3540
|
-
}
|
|
3541
|
-
let sum = 0;
|
|
3542
|
-
let correction = 0;
|
|
3543
|
-
for (const value of values) {
|
|
3544
|
-
const next = value / scale;
|
|
3545
|
-
const total = sum + next;
|
|
3546
|
-
// Neumaier compensation retains small contributions even when larger values cancel.
|
|
3547
|
-
correction += Math.abs(sum) >= Math.abs(next) ? sum - total + next : next - total + sum;
|
|
3548
|
-
sum = total;
|
|
3549
|
-
}
|
|
3550
|
-
return ((sum + correction) / values.length) * scale;
|
|
3551
|
-
}
|
|
3552
|
-
|
|
3553
3580
|
/** 有放回重采样;回调不得修改或持有复用的只读样本缓冲区。 */
|
|
3554
3581
|
function bootstrapEstimate(values, estimator, options) {
|
|
3555
3582
|
if (!values.length ||
|