@zukhruf/statistics 0.0.0-stage → 0.8.3
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/LICENSE +21 -0
- package/NOTICE +10 -0
- package/README.md +53 -2
- package/dist/bootstrap/iid-bootstrap.d.ts +12 -0
- package/dist/bootstrap/iid-bootstrap.d.ts.map +1 -0
- package/dist/bootstrap/iid-bootstrap.js +30 -0
- package/dist/bootstrap/iid-bootstrap.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/interval/confidence-interval-method.d.ts +5 -0
- package/dist/interval/confidence-interval-method.d.ts.map +1 -0
- package/dist/interval/confidence-interval-method.js +2 -0
- package/dist/interval/confidence-interval-method.js.map +1 -0
- package/dist/interval/confidence-interval.d.ts +8 -0
- package/dist/interval/confidence-interval.d.ts.map +1 -0
- package/dist/interval/confidence-interval.js +18 -0
- package/dist/interval/confidence-interval.js.map +1 -0
- package/dist/interval/percentile-interval.d.ts +13 -0
- package/dist/interval/percentile-interval.d.ts.map +1 -0
- package/dist/interval/percentile-interval.js +20 -0
- package/dist/interval/percentile-interval.js.map +1 -0
- package/dist/quantile/higher.d.ts +5 -0
- package/dist/quantile/higher.d.ts.map +1 -0
- package/dist/quantile/higher.js +8 -0
- package/dist/quantile/higher.js.map +1 -0
- package/dist/quantile/inverted-cdf.d.ts +5 -0
- package/dist/quantile/inverted-cdf.d.ts.map +1 -0
- package/dist/quantile/inverted-cdf.js +13 -0
- package/dist/quantile/inverted-cdf.js.map +1 -0
- package/dist/quantile/linear.d.ts +5 -0
- package/dist/quantile/linear.d.ts.map +1 -0
- package/dist/quantile/linear.js +17 -0
- package/dist/quantile/linear.js.map +1 -0
- package/dist/quantile/lower.d.ts +5 -0
- package/dist/quantile/lower.d.ts.map +1 -0
- package/dist/quantile/lower.js +8 -0
- package/dist/quantile/lower.js.map +1 -0
- package/dist/quantile/quantile-method.d.ts +6 -0
- package/dist/quantile/quantile-method.d.ts.map +1 -0
- package/dist/quantile/quantile-method.js +20 -0
- package/dist/quantile/quantile-method.js.map +1 -0
- package/package.json +40 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ezzabuzaid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@zukhruf/statistics
|
|
2
|
+
Copyright 2026 ezzabuzaid
|
|
3
|
+
|
|
4
|
+
This package ports the semantics of the methods lower, higher, linear and
|
|
5
|
+
inverted_cdf of numpy.quantile in NumPy 2.5.4, including the _lerp of its
|
|
6
|
+
linear method, Copyright (c) NumPy Developers, BSD 3-Clause License,
|
|
7
|
+
https://github.com/numpy/numpy. The package does not include NumPy's code.
|
|
8
|
+
The names of the percentile bootstrap follow SciPy (scipy.stats.bootstrap)
|
|
9
|
+
and arch (arch.bootstrap.IIDBootstrap); the package includes no code of
|
|
10
|
+
either.
|
package/README.md
CHANGED
|
@@ -1,3 +1,54 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @zukhruf/statistics
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The percentile bootstrap and the quantile methods of NumPy in JavaScript, to the last bit. Use it when a TypeScript eval must give the same interval as a Python program, such as the summary of a benchmark or the comparison of two models.
|
|
4
|
+
|
|
5
|
+
The package is public on npm. Until 2026-11-07 it was private and reached through a workspace path (ADR 0001); it became public with `@zukhruf/evals`, which depends on it (backlog #3888).
|
|
6
|
+
|
|
7
|
+
## Use it
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Random } from 'python-random';
|
|
11
|
+
|
|
12
|
+
import { IidBootstrap, Linear, PercentileInterval } from '@zukhruf/statistics';
|
|
13
|
+
|
|
14
|
+
const random = new Random(42);
|
|
15
|
+
const bootstrap = new IidBootstrap({
|
|
16
|
+
nResamples: 1000,
|
|
17
|
+
randomIndex: (n) => random.randrange(n),
|
|
18
|
+
});
|
|
19
|
+
const interval = bootstrap.interval(
|
|
20
|
+
scores,
|
|
21
|
+
(resample) =>
|
|
22
|
+
resample.reduce((sum, score) => sum + score, 0) / resample.length,
|
|
23
|
+
new PercentileInterval({ low: 0.025, high: 0.975, method: new Linear() }),
|
|
24
|
+
);
|
|
25
|
+
interval.low; // the 2.5% quantile of the 1000 means, as numpy.percentile
|
|
26
|
+
interval.isAbove(0); // true when the whole interval lies above 0
|
|
27
|
+
|
|
28
|
+
new Linear().of([1, 2, 3, 4], 0.5); // 2.5, as numpy.quantile(a, 0.5)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| Export | NumPy, SciPy or arch | What it does |
|
|
32
|
+
| -------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
+
| `QuantileMethod` | the `method` of `numpy.quantile` | A rule that gives the value at the quantile `q` of sorted values: `of(sorted, q)`. `q` is from 0 to 1. A `q` out of that range, or no values, throws a `RangeError`. |
|
|
34
|
+
| `Lower` | `method='lower'` | The value at the index `floor((n − 1)q)`. |
|
|
35
|
+
| `Higher` | `method='higher'` | The value at the index `ceil((n − 1)q)`. |
|
|
36
|
+
| `Linear` | `method='linear'`, the default of NumPy | The line between the two values around the index `(n − 1)q`, computed as NumPy's `_lerp` computes it, so the bits are NumPy's. d3-array's `quantileSorted` gives other bits for 1 value of 10. |
|
|
37
|
+
| `InvertedCdf` | `method='inverted_cdf'` | The nearest rank: the value at the index `ceil(nq) − 1`, and the first value when `q` is 0. |
|
|
38
|
+
| `ConfidenceInterval` | the `ConfidenceInterval` of `scipy.stats.bootstrap` | `low` and `high`. `isAbove(value)` is true when `low > value`, and `isBelow(value)` is true when `high < value`: the whole interval lies on one side of the value. |
|
|
39
|
+
| `ConfidenceIntervalMethod` | the `method` of `scipy.stats.bootstrap` | A rule that gives the confidence interval of a bootstrap distribution: `of(distribution)`. `PercentileInterval` is one. A caller with a rule of its own writes another. |
|
|
40
|
+
| `PercentileInterval` | `method='percentile'` of `scipy.stats.bootstrap` | The `low` and the `high` quantile of a bootstrap distribution, both read with one quantile method, as `numpy.percentile` reads them. It sorts a copy, so the distribution does not change. |
|
|
41
|
+
| `IidBootstrap` | `arch.bootstrap.IIDBootstrap`; `n_resamples` and `bootstrap_distribution` of SciPy | Draws `nResamples` resamples of the data, with replacement. `distribution(data, statistic)` gives the statistic of each resample. `interval(data, statistic, method)` gives the interval that a `ConfidenceIntervalMethod` reads from that distribution. Data with no items throws a `RangeError`. |
|
|
42
|
+
|
|
43
|
+
The random generator is an input. `randomIndex(n)` gives an index from 0 to n − 1. Each item of a resample takes one call, in order, resample by resample, as a Python loop over the same generator does. So `(n) => random.randrange(n)` of python-random draws as CPython's `random.Random`, and a port of NumPy's `default_rng` draws as `integers(0, n, n)` when it draws one index for each call. An index out of range throws a `RangeError`.
|
|
44
|
+
|
|
45
|
+
These parts stay with each caller, because each caller has its own rule:
|
|
46
|
+
|
|
47
|
+
- the random generators: python-random is on npm, and the NumPy generators are in `@zukhruf/random`. Each caller gives `randomIndex`;
|
|
48
|
+
- a stratified bootstrap (relevance-filtering) and a block bootstrap (`@zukhruf/event-detection`): they draw their own resamples and give their distribution to `PercentileInterval`;
|
|
49
|
+
- an interval with a rule of its own at each end, such as the `lower` method at the low end and the `higher` method at the high end of the Structured Output Benchmark: its caller writes it as a `ConfidenceIntervalMethod`;
|
|
50
|
+
- a p-value and a verdict, such as "better" when the interval of a difference lies above 0: each caller builds its rule from `isAbove` and `isBelow`.
|
|
51
|
+
|
|
52
|
+
## Documentation
|
|
53
|
+
|
|
54
|
+
- [ADR 0001: one home for the percentile bootstrap that six places copied, reached through a workspace path](docs/adr/0001-one-home-for-the-percentile-bootstrap-that-six-places-copied.md)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ConfidenceIntervalMethod } from '../interval/confidence-interval-method.ts';
|
|
2
|
+
import type { ConfidenceInterval } from '../interval/confidence-interval.ts';
|
|
3
|
+
export declare class IidBootstrap {
|
|
4
|
+
#private;
|
|
5
|
+
constructor({ nResamples, randomIndex, }: {
|
|
6
|
+
readonly nResamples: number;
|
|
7
|
+
readonly randomIndex: (n: number) => number;
|
|
8
|
+
});
|
|
9
|
+
distribution<T>(data: readonly T[], statistic: (resample: readonly T[]) => number): number[];
|
|
10
|
+
interval<T>(data: readonly T[], statistic: (resample: readonly T[]) => number, method: ConfidenceIntervalMethod): ConfidenceInterval;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=iid-bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iid-bootstrap.d.ts","sourceRoot":"","sources":["../../src/bootstrap/iid-bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAC1F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAM7E,qBAAa,YAAY;;gBAIX,EACV,UAAU,EACV,WAAW,GACZ,EAAE;QACD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;KAC7C;IAOD,YAAY,CAAC,CAAC,EACZ,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,KAAK,MAAM,GAC5C,MAAM,EAAE;IAQX,QAAQ,CAAC,CAAC,EACR,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,KAAK,MAAM,EAC7C,MAAM,EAAE,wBAAwB,GAC/B,kBAAkB;CAatB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// The bootstrap of arch.bootstrap.IIDBootstrap: resamples of independent
|
|
2
|
+
// items, drawn with replacement. The caller's generator gives each random
|
|
3
|
+
// index, one call for each item, in order, resample by resample, as a Python
|
|
4
|
+
// loop over the same generator draws them.
|
|
5
|
+
export class IidBootstrap {
|
|
6
|
+
#nResamples;
|
|
7
|
+
#randomIndex;
|
|
8
|
+
constructor({ nResamples, randomIndex, }) {
|
|
9
|
+
this.#nResamples = nResamples;
|
|
10
|
+
this.#randomIndex = randomIndex;
|
|
11
|
+
}
|
|
12
|
+
// The bootstrap distribution of scipy.stats.bootstrap: the statistic of
|
|
13
|
+
// each resample, in the order of the resamples.
|
|
14
|
+
distribution(data, statistic) {
|
|
15
|
+
if (data.length === 0)
|
|
16
|
+
throw new RangeError('A bootstrap needs at least one item');
|
|
17
|
+
return Array.from({ length: this.#nResamples }, () => statistic(Array.from({ length: data.length }, () => this.#item(data))));
|
|
18
|
+
}
|
|
19
|
+
interval(data, statistic, method) {
|
|
20
|
+
return method.of(this.distribution(data, statistic));
|
|
21
|
+
}
|
|
22
|
+
#item(data) {
|
|
23
|
+
const index = this.#randomIndex(data.length);
|
|
24
|
+
const item = data[index];
|
|
25
|
+
if (item === undefined)
|
|
26
|
+
throw new RangeError(`A random index is from 0 to ${data.length - 1}, not ${index}`);
|
|
27
|
+
return item;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=iid-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iid-bootstrap.js","sourceRoot":"","sources":["../../src/bootstrap/iid-bootstrap.ts"],"names":[],"mappings":"AAGA,yEAAyE;AACzE,0EAA0E;AAC1E,6EAA6E;AAC7E,2CAA2C;AAC3C,MAAM,OAAO,YAAY;IACd,WAAW,CAAS;IACpB,YAAY,CAAwB;IAE7C,YAAY,EACV,UAAU,EACV,WAAW,GAIZ;QACC,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IAClC,CAAC;IAED,wEAAwE;IACxE,gDAAgD;IAChD,YAAY,CACV,IAAkB,EAClB,SAA6C;QAE7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YACnB,MAAM,IAAI,UAAU,CAAC,qCAAqC,CAAC,CAAC;QAC9D,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,CACnD,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CACvE,CAAC;IACJ,CAAC;IAED,QAAQ,CACN,IAAkB,EAClB,SAA6C,EAC7C,MAAgC;QAEhC,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAI,IAAkB;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,IAAI,KAAK,SAAS;YACpB,MAAM,IAAI,UAAU,CAClB,+BAA+B,IAAI,CAAC,MAAM,GAAG,CAAC,SAAS,KAAK,EAAE,CAC/D,CAAC;QACJ,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { IidBootstrap } from './bootstrap/iid-bootstrap.ts';
|
|
2
|
+
export { ConfidenceInterval } from './interval/confidence-interval.ts';
|
|
3
|
+
export type { ConfidenceIntervalMethod } from './interval/confidence-interval-method.ts';
|
|
4
|
+
export { PercentileInterval } from './interval/percentile-interval.ts';
|
|
5
|
+
export { Higher } from './quantile/higher.ts';
|
|
6
|
+
export { InvertedCdf } from './quantile/inverted-cdf.ts';
|
|
7
|
+
export { Linear } from './quantile/linear.ts';
|
|
8
|
+
export { Lower } from './quantile/lower.ts';
|
|
9
|
+
export { QuantileMethod } from './quantile/quantile-method.ts';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,YAAY,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { IidBootstrap } from "./bootstrap/iid-bootstrap.js";
|
|
2
|
+
export { ConfidenceInterval } from "./interval/confidence-interval.js";
|
|
3
|
+
export { PercentileInterval } from "./interval/percentile-interval.js";
|
|
4
|
+
export { Higher } from "./quantile/higher.js";
|
|
5
|
+
export { InvertedCdf } from "./quantile/inverted-cdf.js";
|
|
6
|
+
export { Linear } from "./quantile/linear.js";
|
|
7
|
+
export { Lower } from "./quantile/lower.js";
|
|
8
|
+
export { QuantileMethod } from "./quantile/quantile-method.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence-interval-method.d.ts","sourceRoot":"","sources":["../../src/interval/confidence-interval-method.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE,MAAM,WAAW,wBAAwB;IACvC,EAAE,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CAAC;CACzD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence-interval-method.js","sourceRoot":"","sources":["../../src/interval/confidence-interval-method.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence-interval.d.ts","sourceRoot":"","sources":["../../src/interval/confidence-interval.ts"],"names":[],"mappings":"AACA,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAMrC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAK/B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;CAGhC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// A low and a high value, such as two quantiles of a bootstrap distribution.
|
|
2
|
+
export class ConfidenceInterval {
|
|
3
|
+
low;
|
|
4
|
+
high;
|
|
5
|
+
constructor(low, high) {
|
|
6
|
+
this.low = low;
|
|
7
|
+
this.high = high;
|
|
8
|
+
}
|
|
9
|
+
// The whole interval lies above the value.
|
|
10
|
+
isAbove(value) {
|
|
11
|
+
return this.low > value;
|
|
12
|
+
}
|
|
13
|
+
// The whole interval lies below the value.
|
|
14
|
+
isBelow(value) {
|
|
15
|
+
return this.high < value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=confidence-interval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence-interval.js","sourceRoot":"","sources":["../../src/interval/confidence-interval.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,OAAO,kBAAkB;IACpB,GAAG,CAAS;IACZ,IAAI,CAAS;IAEtB,YAAY,GAAW,EAAE,IAAY;QACnC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,2CAA2C;IAC3C,OAAO,CAAC,KAAa;QACnB,OAAO,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,2CAA2C;IAC3C,OAAO,CAAC,KAAa;QACnB,OAAO,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { QuantileMethod } from '../quantile/quantile-method.ts';
|
|
2
|
+
import type { ConfidenceIntervalMethod } from './confidence-interval-method.ts';
|
|
3
|
+
import { ConfidenceInterval } from './confidence-interval.ts';
|
|
4
|
+
export declare class PercentileInterval implements ConfidenceIntervalMethod {
|
|
5
|
+
#private;
|
|
6
|
+
constructor({ low, high, method, }: {
|
|
7
|
+
readonly low: number;
|
|
8
|
+
readonly high: number;
|
|
9
|
+
readonly method: QuantileMethod;
|
|
10
|
+
});
|
|
11
|
+
of(distribution: readonly number[]): ConfidenceInterval;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=percentile-interval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"percentile-interval.d.ts","sourceRoot":"","sources":["../../src/interval/percentile-interval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAM9D,qBAAa,kBAAmB,YAAW,wBAAwB;;gBAKrD,EACV,GAAG,EACH,IAAI,EACJ,MAAM,GACP,EAAE;QACD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;KACjC;IAMD,EAAE,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB;CAOxD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ConfidenceInterval } from "./confidence-interval.js";
|
|
2
|
+
// The percentile method of scipy.stats.bootstrap: the low and the high
|
|
3
|
+
// quantile of a bootstrap distribution, both read with one quantile method,
|
|
4
|
+
// as numpy.percentile reads them. It sorts a copy, so the distribution stays
|
|
5
|
+
// as it is.
|
|
6
|
+
export class PercentileInterval {
|
|
7
|
+
#low;
|
|
8
|
+
#high;
|
|
9
|
+
#method;
|
|
10
|
+
constructor({ low, high, method, }) {
|
|
11
|
+
this.#low = low;
|
|
12
|
+
this.#high = high;
|
|
13
|
+
this.#method = method;
|
|
14
|
+
}
|
|
15
|
+
of(distribution) {
|
|
16
|
+
const sorted = distribution.toSorted((a, b) => a - b);
|
|
17
|
+
return new ConfidenceInterval(this.#method.of(sorted, this.#low), this.#method.of(sorted, this.#high));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=percentile-interval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"percentile-interval.js","sourceRoot":"","sources":["../../src/interval/percentile-interval.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,uEAAuE;AACvE,4EAA4E;AAC5E,6EAA6E;AAC7E,YAAY;AACZ,MAAM,OAAO,kBAAkB;IACpB,IAAI,CAAS;IACb,KAAK,CAAS;IACd,OAAO,CAAiB;IAEjC,YAAY,EACV,GAAG,EACH,IAAI,EACJ,MAAM,GAKP;QACC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,EAAE,CAAC,YAA+B;QAChC,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,OAAO,IAAI,kBAAkB,CAC3B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,EAClC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CACpC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"higher.d.ts","sourceRoot":"","sources":["../../src/quantile/higher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,qBAAa,MAAO,SAAQ,cAAc;IACxC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;CAGhE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { QuantileMethod } from "./quantile-method.js";
|
|
2
|
+
// numpy.quantile(method='higher'): the value at ceil((n - 1)q).
|
|
3
|
+
export class Higher extends QuantileMethod {
|
|
4
|
+
valueAt(sorted, q) {
|
|
5
|
+
return QuantileMethod.value(sorted, Math.ceil((sorted.length - 1) * q));
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=higher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"higher.js","sourceRoot":"","sources":["../../src/quantile/higher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,gEAAgE;AAChE,MAAM,OAAO,MAAO,SAAQ,cAAc;IAC9B,OAAO,CAAC,MAAyB,EAAE,CAAS;QACpD,OAAO,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inverted-cdf.d.ts","sourceRoot":"","sources":["../../src/quantile/inverted-cdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAKtD,qBAAa,WAAY,SAAQ,cAAc;IAC7C,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;CAMhE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { QuantileMethod } from "./quantile-method.js";
|
|
2
|
+
// numpy.quantile(method='inverted_cdf'), the nearest rank: NumPy reads the
|
|
3
|
+
// index nq - 1, keeps it when it is whole and else takes the next one, and
|
|
4
|
+
// reads the first value below 0.
|
|
5
|
+
export class InvertedCdf extends QuantileMethod {
|
|
6
|
+
valueAt(sorted, q) {
|
|
7
|
+
const index = sorted.length * q - 1;
|
|
8
|
+
const previous = Math.floor(index);
|
|
9
|
+
const picked = index - previous === 0 ? previous : previous + 1;
|
|
10
|
+
return QuantileMethod.value(sorted, Math.max(picked, 0));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=inverted-cdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inverted-cdf.js","sourceRoot":"","sources":["../../src/quantile/inverted-cdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,2EAA2E;AAC3E,2EAA2E;AAC3E,iCAAiC;AACjC,MAAM,OAAO,WAAY,SAAQ,cAAc;IACnC,OAAO,CAAC,MAAyB,EAAE,CAAS;QACpD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;QAChE,OAAO,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../../src/quantile/linear.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAMtD,qBAAa,MAAO,SAAQ,cAAc;IACxC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;CAYhE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { QuantileMethod } from "./quantile-method.js";
|
|
2
|
+
// numpy.quantile(method='linear'), the default of NumPy: the line between the
|
|
3
|
+
// values around the index (n - 1)q, as NumPy's _lerp computes it. From the
|
|
4
|
+
// middle on, _lerp goes back from the upper value, so a fraction of 0.5 or
|
|
5
|
+
// more gives other bits than a + (b - a)t.
|
|
6
|
+
export class Linear extends QuantileMethod {
|
|
7
|
+
valueAt(sorted, q) {
|
|
8
|
+
const position = (sorted.length - 1) * q;
|
|
9
|
+
const below = Math.floor(position);
|
|
10
|
+
const a = QuantileMethod.value(sorted, below);
|
|
11
|
+
const b = QuantileMethod.value(sorted, Math.min(below + 1, sorted.length - 1));
|
|
12
|
+
const t = position - below;
|
|
13
|
+
const difference = b - a;
|
|
14
|
+
return t >= 0.5 ? b - difference * (1 - t) : a + difference * t;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=linear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear.js","sourceRoot":"","sources":["../../src/quantile/linear.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,2CAA2C;AAC3C,MAAM,OAAO,MAAO,SAAQ,cAAc;IAC9B,OAAO,CAAC,MAAyB,EAAE,CAAS;QACpD,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,cAAc,CAAC,KAAK,CAC5B,MAAM,EACN,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CACvC,CAAC;QACF,MAAM,CAAC,GAAG,QAAQ,GAAG,KAAK,CAAC;QAC3B,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC;IAClE,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lower.d.ts","sourceRoot":"","sources":["../../src/quantile/lower.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,qBAAa,KAAM,SAAQ,cAAc;IACvC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;CAGhE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { QuantileMethod } from "./quantile-method.js";
|
|
2
|
+
// numpy.quantile(method='lower'): the value at floor((n - 1)q).
|
|
3
|
+
export class Lower extends QuantileMethod {
|
|
4
|
+
valueAt(sorted, q) {
|
|
5
|
+
return QuantileMethod.value(sorted, Math.floor((sorted.length - 1) * q));
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=lower.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lower.js","sourceRoot":"","sources":["../../src/quantile/lower.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,gEAAgE;AAChE,MAAM,OAAO,KAAM,SAAQ,cAAc;IAC7B,OAAO,CAAC,MAAyB,EAAE,CAAS;QACpD,OAAO,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare abstract class QuantileMethod {
|
|
2
|
+
of(sorted: readonly number[], q: number): number;
|
|
3
|
+
protected abstract valueAt(sorted: readonly number[], q: number): number;
|
|
4
|
+
protected static value(sorted: readonly number[], index: number): number;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=quantile-method.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quantile-method.d.ts","sourceRoot":"","sources":["../../src/quantile/quantile-method.ts"],"names":[],"mappings":"AAGA,8BAAsB,cAAc;IAClC,EAAE,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAQhD,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAGxE,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;CAMzE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// A rule that gives the value at the quantile q of sorted values: a method of
|
|
2
|
+
// numpy.quantile, with NumPy's name. q is from 0 to 1, as NumPy requires. A
|
|
3
|
+
// subclass gives only where its rule reads the values (Template Method).
|
|
4
|
+
export class QuantileMethod {
|
|
5
|
+
of(sorted, q) {
|
|
6
|
+
if (!(q >= 0 && q <= 1))
|
|
7
|
+
throw new RangeError(`A quantile is from 0 to 1, not ${q}`);
|
|
8
|
+
if (sorted.length === 0)
|
|
9
|
+
throw new RangeError('A quantile needs at least one value');
|
|
10
|
+
return this.valueAt(sorted, q);
|
|
11
|
+
}
|
|
12
|
+
// The value at an index that the rule computed, which is always in range.
|
|
13
|
+
static value(sorted, index) {
|
|
14
|
+
const value = sorted[index];
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
throw new RangeError(`No value at the index ${index}`);
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=quantile-method.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quantile-method.js","sourceRoot":"","sources":["../../src/quantile/quantile-method.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4EAA4E;AAC5E,yEAAyE;AACzE,MAAM,OAAgB,cAAc;IAClC,EAAE,CAAC,MAAyB,EAAE,CAAS;QACrC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,MAAM,IAAI,UAAU,CAAC,kCAAkC,CAAC,EAAE,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YACrB,MAAM,IAAI,UAAU,CAAC,qCAAqC,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACjC,CAAC;IAID,0EAA0E;IAChE,MAAM,CAAC,KAAK,CAAC,MAAyB,EAAE,KAAa;QAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS;YACrB,MAAM,IAAI,UAAU,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zukhruf/statistics",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.8.3",
|
|
4
|
+
"description": "The percentile bootstrap and the quantile methods of NumPy in JavaScript, to the last bit: resamples of a dataset with a random generator that the caller gives, the percentile interval of their statistic, and NumPy's quantile methods.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/JanuaryLabs/zukhruf",
|
|
9
|
+
"directory": "packages/statistics"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/JanuaryLabs/zukhruf/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/JanuaryLabs/zukhruf/tree/main/packages/statistics#readme",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"statistics",
|
|
17
|
+
"bootstrap",
|
|
18
|
+
"confidence-interval",
|
|
19
|
+
"quantile",
|
|
20
|
+
"numpy"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": {
|
|
24
|
+
"./package.json": "./package.json",
|
|
25
|
+
".": {
|
|
26
|
+
"@zukhruf/source": "./src/index.ts",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"NOTICE",
|
|
35
|
+
"!dist/spec/**",
|
|
36
|
+
"!**/*.tsbuildinfo",
|
|
37
|
+
"!**/*.test.*"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
}
|
|
42
|
+
}
|