@zukhruf/statistics 0.0.0-stage → 0.8.4

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.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +10 -0
  3. package/README.md +53 -2
  4. package/dist/bootstrap/iid-bootstrap.d.ts +12 -0
  5. package/dist/bootstrap/iid-bootstrap.d.ts.map +1 -0
  6. package/dist/bootstrap/iid-bootstrap.js +30 -0
  7. package/dist/bootstrap/iid-bootstrap.js.map +1 -0
  8. package/dist/index.d.ts +10 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +9 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/interval/confidence-interval-method.d.ts +5 -0
  13. package/dist/interval/confidence-interval-method.d.ts.map +1 -0
  14. package/dist/interval/confidence-interval-method.js +2 -0
  15. package/dist/interval/confidence-interval-method.js.map +1 -0
  16. package/dist/interval/confidence-interval.d.ts +8 -0
  17. package/dist/interval/confidence-interval.d.ts.map +1 -0
  18. package/dist/interval/confidence-interval.js +18 -0
  19. package/dist/interval/confidence-interval.js.map +1 -0
  20. package/dist/interval/percentile-interval.d.ts +13 -0
  21. package/dist/interval/percentile-interval.d.ts.map +1 -0
  22. package/dist/interval/percentile-interval.js +20 -0
  23. package/dist/interval/percentile-interval.js.map +1 -0
  24. package/dist/quantile/higher.d.ts +5 -0
  25. package/dist/quantile/higher.d.ts.map +1 -0
  26. package/dist/quantile/higher.js +8 -0
  27. package/dist/quantile/higher.js.map +1 -0
  28. package/dist/quantile/inverted-cdf.d.ts +5 -0
  29. package/dist/quantile/inverted-cdf.d.ts.map +1 -0
  30. package/dist/quantile/inverted-cdf.js +13 -0
  31. package/dist/quantile/inverted-cdf.js.map +1 -0
  32. package/dist/quantile/linear.d.ts +5 -0
  33. package/dist/quantile/linear.d.ts.map +1 -0
  34. package/dist/quantile/linear.js +17 -0
  35. package/dist/quantile/linear.js.map +1 -0
  36. package/dist/quantile/lower.d.ts +5 -0
  37. package/dist/quantile/lower.d.ts.map +1 -0
  38. package/dist/quantile/lower.js +8 -0
  39. package/dist/quantile/lower.js.map +1 -0
  40. package/dist/quantile/quantile-method.d.ts +6 -0
  41. package/dist/quantile/quantile-method.d.ts.map +1 -0
  42. package/dist/quantile/quantile-method.js +20 -0
  43. package/dist/quantile/quantile-method.js.map +1 -0
  44. 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
- # Temporary Holding Version
1
+ # @zukhruf/statistics
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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"}
@@ -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,5 @@
1
+ import type { ConfidenceInterval } from './confidence-interval.ts';
2
+ export interface ConfidenceIntervalMethod {
3
+ of(distribution: readonly number[]): ConfidenceInterval;
4
+ }
5
+ //# sourceMappingURL=confidence-interval-method.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=confidence-interval-method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confidence-interval-method.js","sourceRoot":"","sources":["../../src/interval/confidence-interval-method.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export declare class ConfidenceInterval {
2
+ readonly low: number;
3
+ readonly high: number;
4
+ constructor(low: number, high: number);
5
+ isAbove(value: number): boolean;
6
+ isBelow(value: number): boolean;
7
+ }
8
+ //# sourceMappingURL=confidence-interval.d.ts.map
@@ -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,5 @@
1
+ import { QuantileMethod } from './quantile-method.ts';
2
+ export declare class Higher extends QuantileMethod {
3
+ protected valueAt(sorted: readonly number[], q: number): number;
4
+ }
5
+ //# sourceMappingURL=higher.d.ts.map
@@ -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,5 @@
1
+ import { QuantileMethod } from './quantile-method.ts';
2
+ export declare class InvertedCdf extends QuantileMethod {
3
+ protected valueAt(sorted: readonly number[], q: number): number;
4
+ }
5
+ //# sourceMappingURL=inverted-cdf.d.ts.map
@@ -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,5 @@
1
+ import { QuantileMethod } from './quantile-method.ts';
2
+ export declare class Linear extends QuantileMethod {
3
+ protected valueAt(sorted: readonly number[], q: number): number;
4
+ }
5
+ //# sourceMappingURL=linear.d.ts.map
@@ -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,5 @@
1
+ import { QuantileMethod } from './quantile-method.ts';
2
+ export declare class Lower extends QuantileMethod {
3
+ protected valueAt(sorted: readonly number[], q: number): number;
4
+ }
5
+ //# sourceMappingURL=lower.d.ts.map
@@ -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.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.8.4",
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
+ }