@numero-uno-jpn/rstats 0.5.0 → 0.6.1

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 (168) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.ja.md +36 -20
  3. package/README.md +34 -18
  4. package/THIRD_PARTY_NOTICES.md +25 -5
  5. package/dist/chunks/chunk-2JCIB5H2.js +2 -0
  6. package/dist/chunks/chunk-7JVSDGQQ.js +2 -0
  7. package/dist/chunks/chunk-7NK4SA6B.js +2 -0
  8. package/dist/chunks/chunk-AJYQNFXK.js +2 -0
  9. package/dist/chunks/chunk-DRNMIEYH.js +2 -0
  10. package/dist/chunks/chunk-NAYDS7CL.js +2 -0
  11. package/dist/chunks/chunk-NOCEAM44.js +2 -0
  12. package/dist/chunks/chunk-QNAIK4PY.js +2 -0
  13. package/dist/chunks/chunk-TPC6MTYC.js +2 -0
  14. package/dist/chunks/chunk-UGUQYWRQ.js +2 -0
  15. package/dist/chunks/chunk-XM2TVD63.js +2 -0
  16. package/dist/chunks/chunk-Y4IZV7XK.js +2 -0
  17. package/dist/chunks/chunk-ZWJ42QN6.js +2 -0
  18. package/dist/descriptive/basic.d.ts +73 -0
  19. package/dist/descriptive/basic.js +256 -0
  20. package/dist/descriptive/cov.d.ts +39 -0
  21. package/dist/descriptive/cov.js +105 -0
  22. package/dist/descriptive/hist.d.ts +64 -0
  23. package/dist/descriptive/hist.js +304 -0
  24. package/dist/descriptive/moments.d.ts +63 -0
  25. package/dist/descriptive/moments.js +158 -0
  26. package/dist/descriptive/quantile.d.ts +50 -0
  27. package/dist/descriptive/quantile.js +131 -0
  28. package/dist/descriptive/rank.d.ts +23 -0
  29. package/dist/descriptive/rank.js +72 -0
  30. package/dist/descriptive/table.d.ts +54 -0
  31. package/dist/descriptive/table.js +160 -0
  32. package/dist/descriptive.js +2 -0
  33. package/dist/distributions/arcsine.d.ts +24 -0
  34. package/dist/distributions/arcsine.js +73 -0
  35. package/dist/distributions/invgamma.d.ts +29 -0
  36. package/dist/distributions/invgamma.js +85 -0
  37. package/dist/distributions/kumaraswamy.d.ts +17 -0
  38. package/dist/distributions/kumaraswamy.js +96 -0
  39. package/dist/distributions/laplace.d.ts +23 -0
  40. package/dist/distributions/laplace.js +69 -0
  41. package/dist/distributions/multinomial.d.ts +24 -0
  42. package/dist/distributions/multinomial.js +70 -0
  43. package/dist/distributions/nbeta.js +28 -10
  44. package/dist/distributions/nchisq.js +20 -3
  45. package/dist/distributions/pareto.d.ts +23 -0
  46. package/dist/distributions/pareto.js +76 -0
  47. package/dist/distributions/summary.d.ts +25 -0
  48. package/dist/distributions/summary.js +289 -0
  49. package/dist/distributions/triangular.d.ts +25 -0
  50. package/dist/distributions/triangular.js +87 -0
  51. package/dist/distributions.js +2 -0
  52. package/dist/entries/descriptive.d.ts +7 -0
  53. package/dist/entries/descriptive.js +8 -0
  54. package/dist/entries/distributions.d.ts +41 -0
  55. package/dist/entries/distributions.js +41 -0
  56. package/dist/entries/linalg.d.ts +11 -0
  57. package/dist/entries/linalg.js +11 -0
  58. package/dist/entries/numerics.d.ts +8 -0
  59. package/dist/entries/numerics.js +6 -0
  60. package/dist/entries/special.d.ts +9 -0
  61. package/dist/entries/special.js +9 -0
  62. package/dist/entries/tests.d.ts +21 -0
  63. package/dist/entries/tests.js +20 -0
  64. package/dist/htest/ansariTest.d.ts +13 -0
  65. package/dist/htest/ansariTest.js +80 -0
  66. package/dist/htest/aov.d.ts +85 -0
  67. package/dist/htest/aov.js +178 -0
  68. package/dist/htest/binomTest.d.ts +36 -0
  69. package/dist/htest/binomTest.js +121 -0
  70. package/dist/htest/cor.d.ts +14 -0
  71. package/dist/htest/cor.js +4 -3
  72. package/dist/htest/core/ansari.d.ts +18 -0
  73. package/dist/htest/core/ansari.js +121 -0
  74. package/dist/htest/core/kolmogorov.d.ts +26 -0
  75. package/dist/htest/core/kolmogorov.js +221 -0
  76. package/dist/htest/core/mantelhaen.d.ts +26 -0
  77. package/dist/htest/core/mantelhaen.js +145 -0
  78. package/dist/htest/core/shapiro.d.ts +24 -0
  79. package/dist/htest/core/shapiro.js +142 -0
  80. package/dist/htest/core/smirnov.d.ts +20 -0
  81. package/dist/htest/core/smirnov.js +75 -0
  82. package/dist/htest/fisherTest.js +134 -120
  83. package/dist/htest/groups.d.ts +20 -0
  84. package/dist/htest/groups.js +62 -0
  85. package/dist/htest/ksTest.d.ts +31 -0
  86. package/dist/htest/ksTest.js +106 -0
  87. package/dist/htest/mantelhaenTest.d.ts +26 -0
  88. package/dist/htest/mantelhaenTest.js +196 -0
  89. package/dist/htest/mcnemarTest.d.ts +26 -0
  90. package/dist/htest/mcnemarTest.js +99 -0
  91. package/dist/htest/onewayTest.d.ts +26 -0
  92. package/dist/htest/onewayTest.js +97 -0
  93. package/dist/htest/pairwise.d.ts +64 -0
  94. package/dist/htest/pairwise.js +152 -0
  95. package/dist/htest/poissonTest.d.ts +35 -0
  96. package/dist/htest/poissonTest.js +170 -0
  97. package/dist/htest/propTest.d.ts +37 -0
  98. package/dist/htest/propTest.js +164 -0
  99. package/dist/htest/rankTests.d.ts +52 -0
  100. package/dist/htest/rankTests.js +234 -0
  101. package/dist/htest/types.d.ts +2 -0
  102. package/dist/htest/types.js +6 -0
  103. package/dist/htest/varTest.d.ts +48 -0
  104. package/dist/htest/varTest.js +118 -0
  105. package/dist/htest/wilcoxTest.js +136 -174
  106. package/dist/index.d.ts +6 -50
  107. package/dist/index.js +8 -50
  108. package/dist/integrate/quadpack.d.ts +29 -0
  109. package/dist/integrate/quadpack.js +525 -0
  110. package/dist/internal/seq.d.ts +5 -0
  111. package/dist/internal/seq.js +14 -0
  112. package/dist/internal/uniroot.js +10 -71
  113. package/dist/linalg/lu.d.ts +45 -0
  114. package/dist/linalg/lu.js +88 -0
  115. package/dist/linalg/ops.d.ts +90 -0
  116. package/dist/linalg/ops.js +320 -0
  117. package/dist/linalg.js +2 -0
  118. package/dist/models/lm.d.ts +98 -0
  119. package/dist/models/lm.js +187 -0
  120. package/dist/numerics/deriv.d.ts +37 -0
  121. package/dist/numerics/deriv.js +150 -0
  122. package/dist/numerics/integrate.d.ts +91 -0
  123. package/dist/numerics/integrate.js +264 -0
  124. package/dist/numerics/interp.d.ts +103 -0
  125. package/dist/numerics/interp.js +581 -0
  126. package/dist/numerics/ode.d.ts +23 -0
  127. package/dist/numerics/ode.js +59 -0
  128. package/dist/numerics.js +2 -0
  129. package/dist/optim/localmin.d.ts +16 -0
  130. package/dist/optim/localmin.js +97 -0
  131. package/dist/random/beta.js +1 -1
  132. package/dist/random/binomial.js +1 -1
  133. package/dist/random/continuous.js +1 -1
  134. package/dist/random/extra.d.ts +33 -0
  135. package/dist/random/extra.js +62 -0
  136. package/dist/random/gamma.js +1 -1
  137. package/dist/random/hyper.js +1 -1
  138. package/dist/random/mt.js +0 -1
  139. package/dist/random/poisson.js +0 -1
  140. package/dist/random/rank.js +1 -1
  141. package/dist/random/rng.js +1 -1
  142. package/dist/random/sample.js +1 -1
  143. package/dist/rstats.js +2 -2
  144. package/dist/special/besselIK.d.ts +38 -0
  145. package/dist/special/besselIK.js +315 -0
  146. package/dist/special/besselJY.d.ts +32 -0
  147. package/dist/special/besselJY.js +508 -0
  148. package/dist/special/besselSeries.d.ts +8 -0
  149. package/dist/special/besselSeries.js +24 -0
  150. package/dist/special/beta.js +22 -5
  151. package/dist/special/choose.d.ts +75 -0
  152. package/dist/special/choose.js +233 -0
  153. package/dist/special/erf.d.ts +28 -2
  154. package/dist/special/erf.js +37 -10
  155. package/dist/special/extra.d.ts +47 -0
  156. package/dist/special/extra.js +220 -0
  157. package/dist/special/igam.d.ts +4 -0
  158. package/dist/special/igam.js +57 -2
  159. package/dist/special/incbet.js +77 -22
  160. package/dist/special/lgammaDiff.d.ts +7 -0
  161. package/dist/special/lgammaDiff.js +16 -3
  162. package/dist/special/psigamma.d.ts +48 -0
  163. package/dist/special/psigamma.js +318 -0
  164. package/dist/special/rCompatible.d.ts +8 -0
  165. package/dist/special/rCompatible.js +1 -0
  166. package/dist/special.js +2 -0
  167. package/dist/tests.js +2 -0
  168. package/package.json +26 -1
@@ -3,10 +3,15 @@
3
3
  //
4
4
  // The statistics and normal approximation (mean, tie-corrected variance, direction of the continuity correction) use
5
5
  // the same formulas as scipy.stats wilcoxon (zero_method = "wilcox") and mannwhitneyu (scipy/stats/_wilcoxon.py, _mannwhitneyu.py;
6
- // SciPy commit a087e61, BSD-3-Clause, see THIRD_PARTY_NOTICES.md). Intervals and estimates follow Hodges & Lehmann (1963)
7
- // and Bauer (1972): the exact method uses order statistics of the Walsh averages (differences for two samples); the normal
8
- // approximation finds where the standardised statistic crosses the quantile by root finding (src/internal/uniroot.ts).
9
- // The switch between exact and normal approximation, handling of intervals that cannot be formed, and names follow observed R output.
6
+ // SciPy commit a087e61, BSD-3-Clause, see THIRD_PARTY_NOTICES.md).
7
+ // Intervals and estimates were written for rStats.js from Hodges & Lehmann (Ann. Math. Stat. 34, 1963) and Bauer
8
+ // (JASA 67, 1972) and R's documented behaviour: the exact interval takes order statistics of the Walsh averages
9
+ // (of the differences x_i - y_j for two samples) at ranks from the signed rank (rank sum) quantile, and the estimate is
10
+ // their median; the normal-approximation interval is where the standardised statistic of the shifted data, a step
11
+ // function of the shift, crosses the normal quantiles, found with R's uniroot conventions (src/internal/uniroot.ts,
12
+ // tolerance tolRoot), and the estimate is where it crosses 0 without continuity correction. The switch between exact
13
+ // and normal approximation, the reported confidence level when the requested one is not attainable, intervals that
14
+ // cannot be formed, and names follow R's documented and observed behaviour.
10
15
  // - The exact method is used when exact = null and n < 50 (both < 50 for two samples). With ties or zero differences,
11
16
  // the normal approximation is used even when exact = true
12
17
  // - Only NaN is removed (R's documentation says non-finite values are removed, but in fact Inf is kept and ranked)
@@ -195,131 +200,112 @@ function signedRank(x0, exactOpt, paired, ctx) {
195
200
  : signedRankNormalCI(xo, ctx);
196
201
  return { ...result, ...ci };
197
202
  }
198
- /** Interval from order statistics of the Walsh averages (x_i + x_j) / 2 (i <= j) (Bauer 1972) and the Hodges-Lehmann estimate */
203
+ /** Interval with the given finite ends, the other end(s) open according to the alternative */
204
+ function shape(alternative, lower, upper) {
205
+ if (alternative === "less")
206
+ return [-Infinity, upper];
207
+ if (alternative === "greater")
208
+ return [lower, Infinity];
209
+ return [lower, upper];
210
+ }
211
+ /** Interval when no interval can be formed: the bounded end(s) are NaN and the confidence level 0 */
212
+ function noInterval(alternative, estimate, estimateNames) {
213
+ const out = { confInt: shape(alternative, NaN, NaN), confLevel: 0, estimate };
214
+ if (estimateNames !== undefined)
215
+ out.estimateNames = estimateNames;
216
+ return out;
217
+ }
218
+ /** Order-statistic ranks of an exact distribution-free interval: q from the lower-tail quantile (0 replaced by 1) */
219
+ function exactRank(quantile, alternative, a) {
220
+ const q = quantile(alternative === "two.sided" ? a / 2 : a);
221
+ return q === 0 ? 1 : q;
222
+ }
223
+ function checkTolRoot(tol) {
224
+ if (!(tol > 0))
225
+ throw new RangeError("tolRoot must be positive");
226
+ }
227
+ /**
228
+ * Exact interval from the order statistics of the Walsh averages (Bauer 1972) and the Hodges-Lehmann estimate, their
229
+ * median
230
+ */
199
231
  function signedRankExactCI(x, ctx) {
232
+ const { alternative, confLevel } = ctx;
200
233
  const n = x.length;
201
234
  const walsh = [];
202
235
  for (let i = 0; i < n; i++)
203
236
  for (let j = i; j < n; j++)
204
237
  walsh.push((x[i] + x[j]) / 2);
205
238
  walsh.sort(ascending);
206
- const total = walsh.length;
207
- const alpha = 1 - ctx.confLevel;
208
- let confInt;
209
- let achieved;
210
- if (ctx.alternative === "two.sided") {
211
- const qu = Math.max(1, qsignrank1(alpha / 2, n, true, false));
212
- achieved = 2 * psignrank1(qu - 1, n, true, false);
213
- confInt = [walsh[qu - 1], walsh[total - qu]];
214
- }
215
- else {
216
- const qu = Math.max(1, qsignrank1(alpha, n, true, false));
217
- achieved = psignrank1(qu - 1, n, true, false);
218
- confInt =
219
- ctx.alternative === "greater"
220
- ? [walsh[qu - 1], Infinity]
221
- : [-Infinity, walsh[total - qu]];
222
- }
223
- // An unreachable confidence level is replaced by the achieved level (2 significant digits)
224
- const confLevel = achieved - alpha > alpha / 2 ? 1 - signif2(achieved) : ctx.confLevel;
239
+ const N = walsh.length;
240
+ const a = 1 - confLevel;
241
+ const q = exactRank((p) => qsignrank1(p, n, true, false), alternative, a);
242
+ const tail = psignrank1(q - 1, n, true, false);
243
+ const achieved = alternative === "two.sided" ? 2 * tail : tail;
225
244
  return {
226
- confInt,
227
- confLevel,
245
+ confInt: shape(alternative, walsh[q - 1], walsh[N - q]),
246
+ confLevel: achieved - a > a / 2 ? 1 - signif2(achieved) : confLevel,
228
247
  estimate: sortedMedian(walsh),
229
248
  estimateNames: "(pseudo)median",
230
249
  };
231
250
  }
232
- /** When the interval cannot be formed (NaN endpoints, confidence level 0) */
233
- function emptyInterval(alternative) {
234
- if (alternative === "less")
235
- return [-Infinity, NaN];
236
- if (alternative === "greater")
237
- return [NaN, Infinity];
238
- return [NaN, NaN];
239
- }
240
- /** Normal-approximation interval and estimate: root finding for where the standardised statistic crosses the quantile */
251
+ /**
252
+ * Normal-approximation interval: the shifts d at which the standardised signed rank statistic of x - d crosses the
253
+ * normal quantiles, and the estimate where it crosses 0 (found with uniroot, tolerance tolRoot)
254
+ */
241
255
  function signedRankNormalCI(x, ctx) {
242
- const { alternative, tolRoot } = ctx;
256
+ const { alternative, correct, confLevel, tolRoot } = ctx;
243
257
  const n = x.length;
244
258
  if (n === 0)
245
- return { confInt: emptyInterval(alternative), confLevel: 0, estimate: NaN };
246
- let mumin = Infinity;
247
- let mumax = -Infinity;
248
- for (const v of x) {
249
- mumin = Math.min(mumin, v);
250
- mumax = Math.max(mumax, v);
251
- }
252
- // With infinite endpoints, or a single point / all values equal, no interval can be formed (the estimate is the midrange)
253
- if (!Number.isFinite(mumin) ||
254
- !Number.isFinite(mumax) ||
255
- n === 1 ||
256
- mumin === mumax) {
257
- return {
258
- confInt: emptyInterval(alternative),
259
- confLevel: 0,
260
- estimate: (mumin + mumax) / 2,
261
- estimateNames: "midrange",
262
- };
259
+ return noInterval(alternative, NaN);
260
+ const lo = Math.min(...x);
261
+ const hi = Math.max(...x);
262
+ if (!Number.isFinite(lo) || !Number.isFinite(hi) || n === 1 || lo === hi) {
263
+ return noInterval(alternative, (lo + hi) / 2, "midrange");
263
264
  }
264
- // Standardised statistic of x - d minus zq (a decreasing step function of d)
265
- const wdiff = (d, zq, correct) => {
266
- const xd = x.map((v) => v - d).filter((v) => v !== 0);
267
- const [, dz, sigma] = signedRankStat(xd);
268
- return (dz - correction(dz, alternative, correct)) / sigma - zq;
265
+ const stat = (d, corr) => {
266
+ const [, centre, sigma] = signedRankStat(x.map((v) => v - d).filter((v) => v !== 0));
267
+ return (centre - correction(centre, alternative, corr)) / sigma;
269
268
  };
270
- const root = (zq, correct) => {
271
- const f = (d) => wdiff(d, zq, correct);
272
- if (!(tolRoot > 0))
273
- throw new RangeError("tolRoot must be positive");
274
- return uniroot(f, mumin, mumax, { tol: tolRoot });
269
+ const sLo = stat(lo, correct);
270
+ const sHi = stat(hi, correct);
271
+ const zUpper = (p) => -qnorm(p);
272
+ const reachable = (a) => {
273
+ if (alternative === "greater")
274
+ return !(sLo < zUpper(a));
275
+ if (alternative === "less")
276
+ return !(sHi > qnorm(a / 2));
277
+ return !(sLo < zUpper(a / 2)) && !(sHi > qnorm(a / 2));
275
278
  };
276
- let alpha = 1 - ctx.confLevel;
277
- let raised = false;
278
- // If an interval endpoint falls outside the range, double α
279
- for (;;) {
280
- let ok;
281
- if (alternative === "two.sided") {
282
- ok =
283
- !(wdiff(mumin, qnorm(alpha / 2, { lowerTail: false }), ctx.correct) < 0) && !(wdiff(mumax, qnorm(alpha / 2), ctx.correct) > 0);
284
- }
285
- else if (alternative === "greater") {
286
- ok = !(wdiff(mumin, qnorm(alpha, { lowerTail: false }), ctx.correct) < 0);
287
- }
288
- else {
289
- // R uses the α/2 quantile for the "less" check as well
290
- ok = !(wdiff(mumax, qnorm(alpha / 2), ctx.correct) > 0);
291
- }
292
- if (ok || alpha >= 1)
293
- break;
294
- alpha *= 2;
295
- raised = true;
279
+ let a = 1 - confLevel;
280
+ let enlarged = false;
281
+ while (!reachable(a) && a < 1) {
282
+ a *= 2;
283
+ enlarged = true;
296
284
  }
297
- const confLevel = raised ? 1 - Math.min(1, alpha) : ctx.confLevel;
285
+ checkTolRoot(tolRoot);
286
+ const crossing = (z) => uniroot((d) => stat(d, correct) - z, lo, hi, { tol: tolRoot, fLower: sLo - z, fUpper: sHi - z });
298
287
  let confInt;
299
- if (alpha >= 1) {
300
- const m = sortedMedian([...x].sort(ascending));
301
- confInt =
302
- alternative === "less"
303
- ? [-Infinity, m]
304
- : alternative === "greater"
305
- ? [m, Infinity]
306
- : [m, m];
307
- }
308
- else if (alternative === "two.sided") {
309
- confInt = [
310
- root(qnorm(alpha / 2, { lowerTail: false }), ctx.correct),
311
- root(qnorm(alpha / 2), ctx.correct),
312
- ];
288
+ if (a >= 1) {
289
+ const med = sortedMedian([...x].sort(ascending));
290
+ confInt = shape(alternative, med, med);
313
291
  }
314
- else if (alternative === "greater") {
315
- confInt = [root(qnorm(alpha, { lowerTail: false }), ctx.correct), Infinity];
316
- }
317
- else {
318
- confInt = [-Infinity, root(qnorm(alpha), ctx.correct)];
319
- }
320
- // The estimate has no continuity correction (its direction depends on alternative)
321
- const estimate = root(0, false);
322
- return { confInt, confLevel, estimate, estimateNames: "(pseudo)median" };
292
+ else if (alternative === "greater")
293
+ confInt = [crossing(zUpper(a)), Infinity];
294
+ else if (alternative === "less")
295
+ confInt = [-Infinity, crossing(qnorm(a))];
296
+ else
297
+ confInt = [crossing(zUpper(a / 2)), crossing(qnorm(a / 2))];
298
+ const estimate = uniroot((d) => stat(d, false), lo, hi, {
299
+ tol: tolRoot,
300
+ fLower: stat(lo, false),
301
+ fUpper: stat(hi, false),
302
+ });
303
+ return {
304
+ confInt,
305
+ confLevel: enlarged ? 1 - Math.min(1, a) : confLevel,
306
+ estimate,
307
+ estimateNames: "(pseudo)median",
308
+ };
323
309
  }
324
310
  // ---- Two-sample (rank sum test) ----
325
311
  /** Rank sum statistic of x - d and y: [W, W - expectation, standard deviation] */
@@ -380,92 +366,68 @@ function rankSum(x, y, exactOpt, ctx) {
380
366
  const ci = useExact ? rankSumExactCI(x, y, ctx) : rankSumNormalCI(x, y, ctx);
381
367
  return { ...result, ...ci };
382
368
  }
383
- /** Interval from order statistics of the differences x_i - y_j, and the Hodges-Lehmann estimate */
369
+ /** Exact interval from the order statistics of the differences x_i - y_j and their median as the estimate */
384
370
  function rankSumExactCI(x, y, ctx) {
371
+ const { alternative, confLevel } = ctx;
385
372
  const nx = x.length;
386
373
  const ny = y.length;
387
374
  const diffs = [];
388
- for (const a of x)
389
- for (const b of y)
390
- diffs.push(a - b);
375
+ for (const xi of x)
376
+ for (const yj of y)
377
+ diffs.push(xi - yj);
391
378
  diffs.sort(ascending);
392
- const total = diffs.length;
393
- const alpha = 1 - ctx.confLevel;
394
- let confInt;
395
- let achieved;
396
- if (ctx.alternative === "two.sided") {
397
- const qu = Math.max(1, qwilcox1(alpha / 2, nx, ny, true, false));
398
- achieved = 2 * pwilcox1(qu - 1, nx, ny, true, false);
399
- confInt = [diffs[qu - 1], diffs[total - qu]];
400
- }
401
- else {
402
- const qu = Math.max(1, qwilcox1(alpha, nx, ny, true, false));
403
- achieved = pwilcox1(qu - 1, nx, ny, true, false);
404
- confInt =
405
- ctx.alternative === "greater"
406
- ? [diffs[qu - 1], Infinity]
407
- : [-Infinity, diffs[total - qu]];
408
- }
409
- // An unreachable confidence level is replaced by the achieved level (unlike the signed rank case, not rounded)
410
- const confLevel = achieved - alpha > alpha / 2 ? 1 - achieved : ctx.confLevel;
379
+ const M = diffs.length;
380
+ const a = 1 - confLevel;
381
+ const q = exactRank((p) => qwilcox1(p, nx, ny, true, false), alternative, a);
382
+ const tail = pwilcox1(q - 1, nx, ny, true, false);
383
+ const achieved = alternative === "two.sided" ? 2 * tail : tail;
411
384
  return {
412
- confInt,
413
- confLevel,
385
+ confInt: shape(alternative, diffs[q - 1], diffs[M - q]),
386
+ confLevel: achieved - a > a / 2 ? 1 - achieved : confLevel,
414
387
  estimate: sortedMedian(diffs),
415
388
  estimateNames: "difference in location",
416
389
  };
417
390
  }
391
+ /**
392
+ * Normal-approximation interval: the shifts d at which the standardised rank sum statistic of (x - d, y) crosses the
393
+ * normal quantiles (clamped to the range of the differences), and the estimate where it crosses 0
394
+ */
418
395
  function rankSumNormalCI(x, y, ctx) {
419
- const { alternative, tolRoot } = ctx;
420
- let mumin = Infinity;
421
- let mumax = -Infinity;
422
- for (const a of x) {
423
- for (const b of y) {
424
- mumin = Math.min(mumin, a - b);
425
- mumax = Math.max(mumax, a - b);
426
- }
427
- }
428
- if (!Number.isFinite(mumin) || !Number.isFinite(mumax)) {
396
+ const { alternative, correct, confLevel, tolRoot } = ctx;
397
+ const lo = Math.min(...x) - Math.max(...y);
398
+ const hi = Math.max(...x) - Math.min(...y);
399
+ if (!Number.isFinite(lo) || !Number.isFinite(hi)) {
429
400
  throw new Error("cannot compute the confidence interval because the differences are not finite");
430
401
  }
431
- const wdiff = (d, zq, correct) => {
432
- const [, dz, sigma] = rankSumStat(x.map((v) => v - d), y);
433
- return (dz - correction(dz, alternative, correct)) / sigma - zq;
402
+ const stat = (d, corr) => {
403
+ const [, centre, sigma] = rankSumStat(x.map((v) => v - d), y);
404
+ return (centre - correction(centre, alternative, corr)) / sigma;
434
405
  };
435
- // If the quantile is not reached at the ends, return the ends
436
- const root = (zq, correct) => {
437
- const f = (d) => wdiff(d, zq, correct);
438
- const fLower = f(mumin);
439
- const fUpper = f(mumax);
440
- if (Number.isNaN(fLower) || Number.isNaN(fUpper)) {
406
+ const crossing = (z, corr) => {
407
+ const fLo = stat(lo, corr) - z;
408
+ const fHi = stat(hi, corr) - z;
409
+ if (Number.isNaN(fLo) || Number.isNaN(fHi)) {
441
410
  throw new Error("cannot compute the confidence interval because all observations are tied");
442
411
  }
443
- if (fLower <= 0)
444
- return mumin;
445
- if (fUpper >= 0)
446
- return mumax;
447
- if (!(tolRoot > 0))
448
- throw new RangeError("tolRoot must be positive");
449
- return uniroot(f, mumin, mumax, { tol: tolRoot, fLower, fUpper });
412
+ if (fLo <= 0)
413
+ return lo;
414
+ if (fHi >= 0)
415
+ return hi;
416
+ checkTolRoot(tolRoot);
417
+ return uniroot((d) => stat(d, corr) - z, lo, hi, { tol: tolRoot, fLower: fLo, fUpper: fHi });
450
418
  };
451
- const alpha = 1 - ctx.confLevel;
419
+ const a = 1 - confLevel;
452
420
  let confInt;
453
- if (alternative === "two.sided") {
454
- confInt = [
455
- root(qnorm(alpha / 2, { lowerTail: false }), ctx.correct),
456
- root(qnorm(alpha / 2), ctx.correct),
457
- ];
458
- }
459
- else if (alternative === "greater") {
460
- confInt = [root(qnorm(alpha, { lowerTail: false }), ctx.correct), Infinity];
461
- }
462
- else {
463
- confInt = [-Infinity, root(qnorm(alpha), ctx.correct)];
464
- }
421
+ if (alternative === "greater")
422
+ confInt = [crossing(-qnorm(a), correct), Infinity];
423
+ else if (alternative === "less")
424
+ confInt = [-Infinity, crossing(qnorm(a), correct)];
425
+ else
426
+ confInt = [crossing(-qnorm(a / 2), correct), crossing(qnorm(a / 2), correct)];
465
427
  return {
466
428
  confInt,
467
- confLevel: ctx.confLevel,
468
- estimate: root(0, false),
429
+ confLevel,
430
+ estimate: crossing(0, false),
469
431
  estimateNames: "difference in location",
470
432
  };
471
433
  }
package/dist/index.d.ts CHANGED
@@ -1,50 +1,6 @@
1
- export { gamma, lgamma } from "./special/gamma.js";
2
- export { beta, lbeta } from "./special/beta.js";
3
- export { dnorm, pnorm, qnorm, type NormalOptions } from "./distributions/normal.js";
4
- export { dgamma, pgamma, qgamma, type GammaParams } from "./distributions/gamma.js";
5
- export { dchisq, pchisq, qchisq } from "./distributions/chisq.js";
6
- export { dpois, ppois, qpois } from "./distributions/poisson.js";
7
- export { dbeta, pbeta, qbeta } from "./distributions/beta.js";
8
- export { dbinom, pbinom, qbinom } from "./distributions/binomial.js";
9
- export { dt, pt, qt } from "./distributions/t.js";
10
- export { df, pf, qf } from "./distributions/f.js";
11
- export { dunif, punif, qunif, type UniformParams } from "./distributions/uniform.js";
12
- export { dexp, pexp, qexp, type ExponentialParams } from "./distributions/exponential.js";
13
- export { dlnorm, plnorm, qlnorm, type LognormalParams } from "./distributions/lognormal.js";
14
- export { dlogis, plogis, qlogis, type LocationScaleParams } from "./distributions/logistic.js";
15
- export { dcauchy, pcauchy, qcauchy } from "./distributions/cauchy.js";
16
- export { dweibull, pweibull, qweibull, type WeibullParams } from "./distributions/weibull.js";
17
- export { dgeom, pgeom, qgeom } from "./distributions/geometric.js";
18
- export { dnbinom, pnbinom, qnbinom, type NegBinomialParams } from "./distributions/negbinomial.js";
19
- export { dhyper, phyper, qhyper } from "./distributions/hypergeometric.js";
20
- export { dsignrank, psignrank, qsignrank } from "./distributions/signrank.js";
21
- export { dwilcox, pwilcox, qwilcox } from "./distributions/wilcox.js";
22
- export { ptukey, qtukey, type TukeyOptions } from "./distributions/tukey.js";
23
- export type { DensityOptions, TailOptions } from "./internal/dpq.js";
24
- export type { NoncentralOption } from "./internal/noncentral.js";
25
- export type { Vectorizable, VectorResult } from "./internal/vectorize.js";
26
- export { setSeed, getRandomSeed, setRandomSeed } from "./random/rng.js";
27
- export { runif, rnorm, rexp, rlnorm, rlogis, rcauchy, rweibull } from "./random/continuous.js";
28
- export { rgamma, rchisq, rt, rf } from "./random/gamma.js";
29
- export { rbeta } from "./random/beta.js";
30
- export { rpois, rgeom, rnbinom } from "./random/poisson.js";
31
- export { rbinom, rmultinom } from "./random/binomial.js";
32
- export { rsignrank, rwilcox } from "./random/rank.js";
33
- export { sample, sampleInt, type SampleOptions } from "./random/sample.js";
34
- export { rhyper } from "./random/hyper.js";
35
- export { tTest, type TTestOptions, type TTestResult } from "./htest/tTest.js";
36
- export { chisqTest, type ChisqTestOptions, type ChisqTestResult } from "./htest/chisqTest.js";
37
- export { fisherTest, type FisherTestOptions, type FisherTestResult } from "./htest/fisherTest.js";
38
- export { wilcoxTest, type WilcoxTestOptions, type WilcoxTestResult } from "./htest/wilcoxTest.js";
39
- export { cor, corTest, type CorMethod, type CorOptions, type CorTestOptions, type CorTestResult } from "./htest/cor.js";
40
- export { pAdjust, type PAdjustMethod, type PAdjustOptions } from "./htest/pAdjust.js";
41
- export type { Alternative, Counts, HTest, Sample } from "./htest/types.js";
42
- export { crossprod, tcrossprod, backsolve, forwardsolve, type BacksolveOptions } from "./linalg/basic.js";
43
- export { norm, type NormOptions, type NormType } from "./linalg/norm.js";
44
- export { chol, chol2inv, type CholOptions, type CholPivotResult, type Chol2InvOptions } from "./linalg/chol.js";
45
- export { qr, qrQ, qrR, qrX, qrCoef, qrQy, qrQty, qrResid, qrFitted, qrSolve, type QR, type QROptions, type QRQOptions } from "./linalg/qr.js";
46
- export { solve, det, determinant, rcond, type SolveOptions, type Determinant, type RcondOptions } from "./linalg/solve.js";
47
- export { svd, type SvdOptions, type SvdResult } from "./linalg/svd.js";
48
- export { kappa, ginv, type KappaOptions } from "./linalg/kappa.js";
49
- export { eigen, type EigenOptions, type EigenResult } from "./linalg/eigen.js";
50
- export type { MatrixInput, VectorOrMatrix } from "./linalg/matrix.js";
1
+ export * from "./entries/special.js";
2
+ export * from "./entries/distributions.js";
3
+ export * from "./entries/tests.js";
4
+ export * from "./entries/linalg.js";
5
+ export * from "./entries/descriptive.js";
6
+ export * from "./entries/numerics.js";
package/dist/index.js CHANGED
@@ -1,50 +1,8 @@
1
- // Special functions
2
- export { gamma, lgamma } from "./special/gamma.js";
3
- export { beta, lbeta } from "./special/beta.js";
4
- // Distributions
5
- export { dnorm, pnorm, qnorm } from "./distributions/normal.js";
6
- export { dgamma, pgamma, qgamma } from "./distributions/gamma.js";
7
- export { dchisq, pchisq, qchisq } from "./distributions/chisq.js";
8
- export { dpois, ppois, qpois } from "./distributions/poisson.js";
9
- export { dbeta, pbeta, qbeta } from "./distributions/beta.js";
10
- export { dbinom, pbinom, qbinom } from "./distributions/binomial.js";
11
- export { dt, pt, qt } from "./distributions/t.js";
12
- export { df, pf, qf } from "./distributions/f.js";
13
- export { dunif, punif, qunif } from "./distributions/uniform.js";
14
- export { dexp, pexp, qexp } from "./distributions/exponential.js";
15
- export { dlnorm, plnorm, qlnorm } from "./distributions/lognormal.js";
16
- export { dlogis, plogis, qlogis } from "./distributions/logistic.js";
17
- export { dcauchy, pcauchy, qcauchy } from "./distributions/cauchy.js";
18
- export { dweibull, pweibull, qweibull } from "./distributions/weibull.js";
19
- export { dgeom, pgeom, qgeom } from "./distributions/geometric.js";
20
- export { dnbinom, pnbinom, qnbinom } from "./distributions/negbinomial.js";
21
- export { dhyper, phyper, qhyper } from "./distributions/hypergeometric.js";
22
- export { dsignrank, psignrank, qsignrank } from "./distributions/signrank.js";
23
- export { dwilcox, pwilcox, qwilcox } from "./distributions/wilcox.js";
24
- export { ptukey, qtukey } from "./distributions/tukey.js";
25
- // Random numbers (same streams as R's set.seed)
26
- export { setSeed, getRandomSeed, setRandomSeed } from "./random/rng.js";
27
- export { runif, rnorm, rexp, rlnorm, rlogis, rcauchy, rweibull } from "./random/continuous.js";
28
- export { rgamma, rchisq, rt, rf } from "./random/gamma.js";
29
- export { rbeta } from "./random/beta.js";
30
- export { rpois, rgeom, rnbinom } from "./random/poisson.js";
31
- export { rbinom, rmultinom } from "./random/binomial.js";
32
- export { rsignrank, rwilcox } from "./random/rank.js";
33
- export { sample, sampleInt } from "./random/sample.js";
34
- export { rhyper } from "./random/hyper.js";
35
- // Hypothesis tests (same content as R's htest, returned as plain objects)
36
- export { tTest } from "./htest/tTest.js";
37
- export { chisqTest } from "./htest/chisqTest.js";
38
- export { fisherTest } from "./htest/fisherTest.js";
39
- export { wilcoxTest } from "./htest/wilcoxTest.js";
40
- export { cor, corTest } from "./htest/cor.js";
41
- export { pAdjust } from "./htest/pAdjust.js";
42
- // Linear algebra (the core of scipy.linalg; names and results follow R; matrices are arrays of rows)
43
- export { crossprod, tcrossprod, backsolve, forwardsolve } from "./linalg/basic.js";
44
- export { norm } from "./linalg/norm.js";
45
- export { chol, chol2inv } from "./linalg/chol.js";
46
- export { qr, qrQ, qrR, qrX, qrCoef, qrQy, qrQty, qrResid, qrFitted, qrSolve } from "./linalg/qr.js";
47
- export { solve, det, determinant, rcond } from "./linalg/solve.js";
48
- export { svd } from "./linalg/svd.js";
49
- export { kappa, ginv } from "./linalg/kappa.js";
50
- export { eigen } from "./linalg/eigen.js";
1
+ // rStats.js: R's numerical core in TypeScript. Each area is also available on its own as a subpath export
2
+ // (rStats.js/distributions, /tests, /linalg, /descriptive, /numerics, /special; see src/entries/).
3
+ export * from "./entries/special.js";
4
+ export * from "./entries/distributions.js";
5
+ export * from "./entries/tests.js";
6
+ export * from "./entries/linalg.js";
7
+ export * from "./entries/descriptive.js";
8
+ export * from "./entries/numerics.js";
@@ -0,0 +1,29 @@
1
+ export type Integrand = (x: number) => number;
2
+ /** Result of dqagse / dqagie */
3
+ export interface QuadResult {
4
+ result: number;
5
+ abserr: number;
6
+ /** Number of integrand evaluations */
7
+ neval: number;
8
+ /**
9
+ * 0 normal termination; 1 maximum number of subdivisions; 2 roundoff error; 3 bad integrand behaviour;
10
+ * 4 roundoff error in the extrapolation table; 5 divergent or slowly convergent; 6 invalid input
11
+ */
12
+ ier: number;
13
+ /** Number of subintervals produced */
14
+ last: number;
15
+ }
16
+ /**
17
+ * Integral of f over the finite interval [a, b] (QUADPACK dqagse: 21-point Gauss-Kronrod rule, bisection of the
18
+ * interval with the largest error, epsilon-algorithm extrapolation).
19
+ *
20
+ * @param limit - Maximum number of subintervals (R's `subdivisions`).
21
+ */
22
+ export declare function dqagse(f: Integrand, a: number, b: number, epsabs: number, epsrel: number, limit: number): QuadResult;
23
+ /**
24
+ * Integral of f over an infinite range (QUADPACK dqagie): (bound, inf) for inf = 1, (-inf, bound) for inf = -1,
25
+ * (-inf, inf) for inf = 2, mapped to (0, 1] by x = bound + (1 - t) / t.
26
+ *
27
+ * @param limit - Maximum number of subintervals (R's `subdivisions`).
28
+ */
29
+ export declare function dqagie(f: Integrand, bound: number, inf: -1 | 1 | 2, epsabs: number, epsrel: number, limit: number): QuadResult;