@thi.ng/metrics 0.1.0 → 0.2.0
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/CHANGELOG.md +7 -1
- package/README.md +3 -3
- package/api.d.ts +2 -0
- package/metrics.d.ts +2 -2
- package/metrics.js +23 -5
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2025-07-
|
|
3
|
+
- **Last updated**: 2025-07-31T10:48:56Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -11,6 +11,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
11
11
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
12
12
|
and/or version bumps of transitive dependencies.
|
|
13
13
|
|
|
14
|
+
## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/metrics@0.2.0) (2025-07-31)
|
|
15
|
+
|
|
16
|
+
#### 🚀 Features
|
|
17
|
+
|
|
18
|
+
- add median to all metrics ([64c4a11](https://github.com/thi-ng/umbrella/commit/64c4a11))
|
|
19
|
+
|
|
14
20
|
## [0.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/metrics@0.1.0) (2025-07-30)
|
|
15
21
|
|
|
16
22
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
|
|
25
25
|
## About
|
|
26
26
|
|
|
27
|
-
Utilities for computing & aggregating value metrics (mean, min/max, sd), incl. support for circular domains.
|
|
27
|
+
Utilities for computing & aggregating value metrics (mean, median, min/max, sd), incl. support for circular domains.
|
|
28
28
|
|
|
29
29
|
## Status
|
|
30
30
|
|
|
31
|
-
**
|
|
31
|
+
**STABLE** - used in production
|
|
32
32
|
|
|
33
33
|
[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=%5Bmetrics%5D+in%3Atitle)
|
|
34
34
|
|
|
@@ -58,7 +58,7 @@ For Node.js REPL:
|
|
|
58
58
|
const met = await import("@thi.ng/metrics");
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
Package sizes (brotli'd, pre-treeshake): ESM:
|
|
61
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 698 bytes
|
|
62
62
|
|
|
63
63
|
## Dependencies
|
|
64
64
|
|
package/api.d.ts
CHANGED
package/metrics.d.ts
CHANGED
|
@@ -23,8 +23,8 @@ export declare const defMetric: (values: NumericArray) => Metric;
|
|
|
23
23
|
export declare const defWeightedMetric: (values: NumericArray, weights: NumericArray) => WeightedMetric;
|
|
24
24
|
/**
|
|
25
25
|
* Computes a {@link Metric} for given angular/circular `values` (normalized to
|
|
26
|
-
* [0,1] range). The `mean` and `sd` are computed using circular
|
|
27
|
-
* the `min`/`max` bounds via {@link circularRange}.
|
|
26
|
+
* [0,1] range). The `mean`, `media` and `sd` are computed using circular
|
|
27
|
+
* versions and the `min`/`max` bounds via {@link circularRange}.
|
|
28
28
|
*
|
|
29
29
|
* @param values
|
|
30
30
|
*/
|
package/metrics.js
CHANGED
|
@@ -4,6 +4,7 @@ import { circularMean, circularSD } from "@thi.ng/vectors/circular";
|
|
|
4
4
|
import { dot } from "@thi.ng/vectors/dot";
|
|
5
5
|
import { vmax } from "@thi.ng/vectors/max";
|
|
6
6
|
import { vmean } from "@thi.ng/vectors/mean";
|
|
7
|
+
import { vmedian } from "@thi.ng/vectors/median";
|
|
7
8
|
import { vmin } from "@thi.ng/vectors/min";
|
|
8
9
|
import { sd } from "@thi.ng/vectors/variance";
|
|
9
10
|
const defMetric = (values) => {
|
|
@@ -12,16 +13,17 @@ const defMetric = (values) => {
|
|
|
12
13
|
min,
|
|
13
14
|
max,
|
|
14
15
|
mean: vmean(values),
|
|
16
|
+
median: vmedian(values),
|
|
15
17
|
sd: sd(values)
|
|
16
18
|
};
|
|
17
19
|
};
|
|
18
20
|
const defWeightedMetric = (values, weights) => {
|
|
19
21
|
const [min, max] = valueRange(values);
|
|
20
|
-
const mean = vmean(values);
|
|
21
22
|
return {
|
|
22
23
|
min,
|
|
23
24
|
max,
|
|
24
|
-
mean,
|
|
25
|
+
mean: vmean(values),
|
|
26
|
+
median: vmedian(values),
|
|
25
27
|
sd: sd(values),
|
|
26
28
|
weighted: dot(values, weights)
|
|
27
29
|
};
|
|
@@ -34,6 +36,7 @@ const defCircularMetric = (values) => {
|
|
|
34
36
|
min,
|
|
35
37
|
max,
|
|
36
38
|
mean,
|
|
39
|
+
median: __circularMedian(values, min, max),
|
|
37
40
|
sd: circularSD(scaledValues) / TAU
|
|
38
41
|
};
|
|
39
42
|
};
|
|
@@ -66,9 +69,10 @@ const circularRange = (values, mean) => {
|
|
|
66
69
|
};
|
|
67
70
|
const aggregateMetrics = (metrics) => {
|
|
68
71
|
const mean = __mean(metrics, "mean");
|
|
72
|
+
const median = __mean(metrics, "median");
|
|
69
73
|
const sd2 = __mean(metrics, "sd");
|
|
70
74
|
const [min, max] = aggregateMetricRanges(metrics);
|
|
71
|
-
return {
|
|
75
|
+
return { min, max, mean, median, sd: sd2 };
|
|
72
76
|
};
|
|
73
77
|
const aggregateWeightedMetrics = (metrics) => {
|
|
74
78
|
const res = aggregateMetrics(metrics);
|
|
@@ -77,15 +81,29 @@ const aggregateWeightedMetrics = (metrics) => {
|
|
|
77
81
|
};
|
|
78
82
|
const aggregateCircularMetrics = (metrics) => {
|
|
79
83
|
const mean = circularMean(metrics.map((x) => x.mean * TAU)) / TAU;
|
|
80
|
-
const sd2 = __mean(metrics, "sd");
|
|
81
84
|
const [min, max] = aggregateMetricRanges(metrics);
|
|
82
|
-
|
|
85
|
+
const sd2 = __mean(metrics, "sd");
|
|
86
|
+
const median = __circularMedian(
|
|
87
|
+
metrics.map((x) => x.mean),
|
|
88
|
+
min,
|
|
89
|
+
max
|
|
90
|
+
);
|
|
91
|
+
return { min, max, mean, median, sd: sd2 };
|
|
83
92
|
};
|
|
84
93
|
const aggregateMetricRanges = (metrics) => [
|
|
85
94
|
vmin(metrics.map((x) => x.min)),
|
|
86
95
|
vmax(metrics.map((x) => x.max))
|
|
87
96
|
];
|
|
88
97
|
const __mean = (metrics, key) => vmean(metrics.map((x) => x[key]));
|
|
98
|
+
const __circularMedian = (values, min, max) => {
|
|
99
|
+
if (min <= max) return vmedian(values);
|
|
100
|
+
const n = values.length;
|
|
101
|
+
const m = n >> 1;
|
|
102
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
103
|
+
const split = sorted.findIndex((x) => x === min);
|
|
104
|
+
const reordered = sorted.slice(split).concat(sorted.slice(0, split));
|
|
105
|
+
return n & 1 ? reordered[m] : (reordered[m - 1] + reordered[m]) * 0.5;
|
|
106
|
+
};
|
|
89
107
|
export {
|
|
90
108
|
aggregateCircularMetrics,
|
|
91
109
|
aggregateMetricRanges,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/metrics",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Utilities for computing & aggregating value metrics (mean, min/max, sd), incl. support for circular domains",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Utilities for computing & aggregating value metrics (mean, median, min/max, sd), incl. support for circular domains",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
7
7
|
"typings": "./index.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@thi.ng/api": "^8.11.33",
|
|
43
43
|
"@thi.ng/math": "^5.11.33",
|
|
44
|
-
"@thi.ng/vectors": "^8.6.
|
|
44
|
+
"@thi.ng/vectors": "^8.6.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"esbuild": "^0.25.8",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"circular",
|
|
54
54
|
"interval",
|
|
55
55
|
"mean",
|
|
56
|
+
"median",
|
|
56
57
|
"range",
|
|
57
58
|
"standard-deviation",
|
|
58
59
|
"typescript"
|
|
@@ -83,8 +84,7 @@
|
|
|
83
84
|
}
|
|
84
85
|
},
|
|
85
86
|
"thi.ng": {
|
|
86
|
-
"status": "beta",
|
|
87
87
|
"year": 2025
|
|
88
88
|
},
|
|
89
|
-
"gitHead": "
|
|
89
|
+
"gitHead": "76ffdc6e27bced158471ed47700919e7079956ca\n"
|
|
90
90
|
}
|