datly 0.0.2 → 0.0.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/README.MD +1773 -2386
- package/dist/datly.cjs +1 -1
- package/dist/datly.mjs +1 -1
- package/dist/datly.umd.js +1 -1
- package/package.json +3 -3
- package/src/code.js +2466 -0
- package/src/index.js +236 -480
- package/src/plot.js +609 -0
- package/src/core/dataLoader.js +0 -407
- package/src/core/utils.js +0 -306
- package/src/core/validator.js +0 -205
- package/src/dataviz/index.js +0 -1566
- package/src/descriptive/centralTendency.js +0 -208
- package/src/descriptive/dispersion.js +0 -273
- package/src/descriptive/position.js +0 -268
- package/src/descriptive/shape.js +0 -336
- package/src/inferential/confidenceIntervals.js +0 -561
- package/src/inferential/hypothesisTesting.js +0 -527
- package/src/inferential/normalityTests.js +0 -587
- package/src/insights/autoAnalyser.js +0 -685
- package/src/insights/interpreter.js +0 -543
- package/src/insights/patternDetector.js +0 -897
- package/src/insights/reportGenerator.js +0 -1072
- package/src/ml/ClassificationMetrics.js +0 -336
- package/src/ml/DecisionTree.js +0 -412
- package/src/ml/KNearestNeighbors.js +0 -317
- package/src/ml/LinearRegression.js +0 -179
- package/src/ml/LogisticRegression.js +0 -396
- package/src/ml/MachineLearning.js +0 -490
- package/src/ml/NaiveBayes.js +0 -296
- package/src/ml/RandomForest.js +0 -323
- package/src/ml/SupportVectorMachine.js +0 -299
- package/src/ml/baseModel.js +0 -106
- package/src/multivariate/correlation.js +0 -653
- package/src/multivariate/regression.js +0 -660
@@ -1,561 +0,0 @@
|
|
1
|
-
class ConfidenceIntervals {
|
2
|
-
mean(sample, confidence = 0.95) {
|
3
|
-
if (confidence <= 0 || confidence >= 1) {
|
4
|
-
throw new Error('Confidence level must be between 0 and 1');
|
5
|
-
}
|
6
|
-
|
7
|
-
const validSample = sample.filter(val =>
|
8
|
-
typeof val === 'number' && !isNaN(val) && isFinite(val)
|
9
|
-
);
|
10
|
-
|
11
|
-
if (validSample.length < 2) {
|
12
|
-
throw new Error('Need at least 2 valid observations');
|
13
|
-
}
|
14
|
-
|
15
|
-
const n = validSample.length;
|
16
|
-
const mean = validSample.reduce((sum, val) => sum + val, 0) / n;
|
17
|
-
const variance = validSample.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (n - 1);
|
18
|
-
const stdError = Math.sqrt(variance / n);
|
19
|
-
const alpha = 1 - confidence;
|
20
|
-
const tCritical = this.tInverse(1 - alpha / 2, n - 1);
|
21
|
-
const marginOfError = tCritical * stdError;
|
22
|
-
|
23
|
-
return {
|
24
|
-
mean: mean,
|
25
|
-
standardError: stdError,
|
26
|
-
marginOfError: marginOfError,
|
27
|
-
lowerBound: mean - marginOfError,
|
28
|
-
upperBound: mean + marginOfError,
|
29
|
-
confidence: confidence,
|
30
|
-
degreesOfFreedom: n - 1,
|
31
|
-
sampleSize: n
|
32
|
-
};
|
33
|
-
}
|
34
|
-
|
35
|
-
meanKnownVariance(sample, populationStd, confidence = 0.95) {
|
36
|
-
if (confidence <= 0 || confidence >= 1) {
|
37
|
-
throw new Error('Confidence level must be between 0 and 1');
|
38
|
-
}
|
39
|
-
|
40
|
-
if (populationStd <= 0) {
|
41
|
-
throw new Error('Population standard deviation must be positive');
|
42
|
-
}
|
43
|
-
|
44
|
-
const validSample = sample.filter(val =>
|
45
|
-
typeof val === 'number' && !isNaN(val) && isFinite(val)
|
46
|
-
);
|
47
|
-
|
48
|
-
if (validSample.length === 0) {
|
49
|
-
throw new Error('No valid numeric values found');
|
50
|
-
}
|
51
|
-
|
52
|
-
const n = validSample.length;
|
53
|
-
const mean = validSample.reduce((sum, val) => sum + val, 0) / n;
|
54
|
-
const stdError = populationStd / Math.sqrt(n);
|
55
|
-
const alpha = 1 - confidence;
|
56
|
-
const zCritical = this.normalInverse(1 - alpha / 2);
|
57
|
-
const marginOfError = zCritical * stdError;
|
58
|
-
|
59
|
-
return {
|
60
|
-
mean: mean,
|
61
|
-
standardError: stdError,
|
62
|
-
marginOfError: marginOfError,
|
63
|
-
lowerBound: mean - marginOfError,
|
64
|
-
upperBound: mean + marginOfError,
|
65
|
-
confidence: confidence,
|
66
|
-
sampleSize: n,
|
67
|
-
populationStd: populationStd
|
68
|
-
};
|
69
|
-
}
|
70
|
-
|
71
|
-
proportion(successes, total, confidence = 0.95) {
|
72
|
-
if (!Number.isInteger(successes) || !Number.isInteger(total)) {
|
73
|
-
throw new Error('Successes and total must be integers');
|
74
|
-
}
|
75
|
-
|
76
|
-
if (successes < 0 || total <= 0 || successes > total) {
|
77
|
-
throw new Error('Invalid values: 0 ≤ successes ≤ total, total > 0');
|
78
|
-
}
|
79
|
-
|
80
|
-
if (confidence <= 0 || confidence >= 1) {
|
81
|
-
throw new Error('Confidence level must be between 0 and 1');
|
82
|
-
}
|
83
|
-
|
84
|
-
const p = successes / total;
|
85
|
-
const alpha = 1 - confidence;
|
86
|
-
const zCritical = this.normalInverse(1 - alpha / 2);
|
87
|
-
|
88
|
-
if (total * p < 5 || total * (1 - p) < 5) {
|
89
|
-
console.warn('Warning: Normal approximation may not be accurate. Consider using Wilson score interval.');
|
90
|
-
}
|
91
|
-
|
92
|
-
const stdError = Math.sqrt(p * (1 - p) / total);
|
93
|
-
const marginOfError = zCritical * stdError;
|
94
|
-
|
95
|
-
const normalInterval = {
|
96
|
-
proportion: p,
|
97
|
-
standardError: stdError,
|
98
|
-
marginOfError: marginOfError,
|
99
|
-
lowerBound: Math.max(0, p - marginOfError),
|
100
|
-
upperBound: Math.min(1, p + marginOfError),
|
101
|
-
confidence: confidence,
|
102
|
-
sampleSize: total,
|
103
|
-
successes: successes
|
104
|
-
};
|
105
|
-
|
106
|
-
const wilsonInterval = this.wilsonScoreInterval(successes, total, confidence);
|
107
|
-
|
108
|
-
return {
|
109
|
-
normal: normalInterval,
|
110
|
-
wilson: wilsonInterval,
|
111
|
-
recommended: total * p >= 5 && total * (1 - p) >= 5 ? normalInterval : wilsonInterval
|
112
|
-
};
|
113
|
-
}
|
114
|
-
|
115
|
-
wilsonScoreInterval(successes, total, confidence = 0.95) {
|
116
|
-
const p = successes / total;
|
117
|
-
const alpha = 1 - confidence;
|
118
|
-
const z = this.normalInverse(1 - alpha / 2);
|
119
|
-
const z2 = z * z;
|
120
|
-
|
121
|
-
const denominator = 1 + z2 / total;
|
122
|
-
const center = (p + z2 / (2 * total)) / denominator;
|
123
|
-
const halfWidth = z * Math.sqrt(p * (1 - p) / total + z2 / (4 * total * total)) / denominator;
|
124
|
-
|
125
|
-
return {
|
126
|
-
proportion: p,
|
127
|
-
center: center,
|
128
|
-
halfWidth: halfWidth,
|
129
|
-
lowerBound: center - halfWidth,
|
130
|
-
upperBound: center + halfWidth,
|
131
|
-
confidence: confidence,
|
132
|
-
sampleSize: total,
|
133
|
-
successes: successes
|
134
|
-
};
|
135
|
-
}
|
136
|
-
|
137
|
-
variance(sample, confidence = 0.95) {
|
138
|
-
if (confidence <= 0 || confidence >= 1) {
|
139
|
-
throw new Error('Confidence level must be between 0 and 1');
|
140
|
-
}
|
141
|
-
|
142
|
-
const validSample = sample.filter(val =>
|
143
|
-
typeof val === 'number' && !isNaN(val) && isFinite(val)
|
144
|
-
);
|
145
|
-
|
146
|
-
if (validSample.length < 2) {
|
147
|
-
throw new Error('Need at least 2 valid observations');
|
148
|
-
}
|
149
|
-
|
150
|
-
const n = validSample.length;
|
151
|
-
const mean = validSample.reduce((sum, val) => sum + val, 0) / n;
|
152
|
-
const sampleVariance = validSample.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (n - 1);
|
153
|
-
|
154
|
-
const alpha = 1 - confidence;
|
155
|
-
const df = n - 1;
|
156
|
-
const chiSquareLower = this.chiSquareInverse(alpha / 2, df);
|
157
|
-
const chiSquareUpper = this.chiSquareInverse(1 - alpha / 2, df);
|
158
|
-
|
159
|
-
const lowerBound = (df * sampleVariance) / chiSquareUpper;
|
160
|
-
const upperBound = (df * sampleVariance) / chiSquareLower;
|
161
|
-
|
162
|
-
return {
|
163
|
-
sampleVariance: sampleVariance,
|
164
|
-
lowerBound: lowerBound,
|
165
|
-
upperBound: upperBound,
|
166
|
-
confidence: confidence,
|
167
|
-
degreesOfFreedom: df,
|
168
|
-
sampleSize: n
|
169
|
-
};
|
170
|
-
}
|
171
|
-
|
172
|
-
standardDeviation(sample, confidence = 0.95) {
|
173
|
-
const varianceCI = this.variance(sample, confidence);
|
174
|
-
|
175
|
-
return {
|
176
|
-
sampleStandardDeviation: Math.sqrt(varianceCI.sampleVariance),
|
177
|
-
lowerBound: Math.sqrt(varianceCI.lowerBound),
|
178
|
-
upperBound: Math.sqrt(varianceCI.upperBound),
|
179
|
-
confidence: confidence,
|
180
|
-
degreesOfFreedom: varianceCI.degreesOfFreedom,
|
181
|
-
sampleSize: varianceCI.sampleSize
|
182
|
-
};
|
183
|
-
}
|
184
|
-
|
185
|
-
meanDifference(sample1, sample2, confidence = 0.95, equalVariances = false) {
|
186
|
-
if (confidence <= 0 || confidence >= 1) {
|
187
|
-
throw new Error('Confidence level must be between 0 and 1');
|
188
|
-
}
|
189
|
-
|
190
|
-
const validSample1 = sample1.filter(val =>
|
191
|
-
typeof val === 'number' && !isNaN(val) && isFinite(val)
|
192
|
-
);
|
193
|
-
const validSample2 = sample2.filter(val =>
|
194
|
-
typeof val === 'number' && !isNaN(val) && isFinite(val)
|
195
|
-
);
|
196
|
-
|
197
|
-
if (validSample1.length < 2 || validSample2.length < 2) {
|
198
|
-
throw new Error('Both samples must have at least 2 valid observations');
|
199
|
-
}
|
200
|
-
|
201
|
-
const n1 = validSample1.length;
|
202
|
-
const n2 = validSample2.length;
|
203
|
-
const mean1 = validSample1.reduce((sum, val) => sum + val, 0) / n1;
|
204
|
-
const mean2 = validSample2.reduce((sum, val) => sum + val, 0) / n2;
|
205
|
-
const meanDiff = mean1 - mean2;
|
206
|
-
|
207
|
-
const var1 = validSample1.reduce((sum, val) => sum + Math.pow(val - mean1, 2), 0) / (n1 - 1);
|
208
|
-
const var2 = validSample2.reduce((sum, val) => sum + Math.pow(val - mean2, 2), 0) / (n2 - 1);
|
209
|
-
|
210
|
-
let stdError, df;
|
211
|
-
|
212
|
-
if (equalVariances) {
|
213
|
-
const pooledVar = ((n1 - 1) * var1 + (n2 - 1) * var2) / (n1 + n2 - 2);
|
214
|
-
stdError = Math.sqrt(pooledVar * (1/n1 + 1/n2));
|
215
|
-
df = n1 + n2 - 2;
|
216
|
-
} else {
|
217
|
-
stdError = Math.sqrt(var1/n1 + var2/n2);
|
218
|
-
df = Math.pow(var1/n1 + var2/n2, 2) /
|
219
|
-
(Math.pow(var1/n1, 2)/(n1-1) + Math.pow(var2/n2, 2)/(n2-1));
|
220
|
-
}
|
221
|
-
|
222
|
-
const alpha = 1 - confidence;
|
223
|
-
const tCritical = this.tInverse(1 - alpha / 2, df);
|
224
|
-
const marginOfError = tCritical * stdError;
|
225
|
-
|
226
|
-
return {
|
227
|
-
meanDifference: meanDiff,
|
228
|
-
sample1Mean: mean1,
|
229
|
-
sample2Mean: mean2,
|
230
|
-
standardError: stdError,
|
231
|
-
marginOfError: marginOfError,
|
232
|
-
lowerBound: meanDiff - marginOfError,
|
233
|
-
upperBound: meanDiff + marginOfError,
|
234
|
-
confidence: confidence,
|
235
|
-
degreesOfFreedom: df,
|
236
|
-
equalVariances: equalVariances
|
237
|
-
};
|
238
|
-
}
|
239
|
-
|
240
|
-
pairedMeanDifference(sample1, sample2, confidence = 0.95) {
|
241
|
-
if (sample1.length !== sample2.length) {
|
242
|
-
throw new Error('Paired samples must have equal length');
|
243
|
-
}
|
244
|
-
|
245
|
-
const differences = [];
|
246
|
-
for (let i = 0; i < sample1.length; i++) {
|
247
|
-
if (typeof sample1[i] === 'number' && typeof sample2[i] === 'number' &&
|
248
|
-
!isNaN(sample1[i]) && !isNaN(sample2[i]) &&
|
249
|
-
isFinite(sample1[i]) && isFinite(sample2[i])) {
|
250
|
-
differences.push(sample1[i] - sample2[i]);
|
251
|
-
}
|
252
|
-
}
|
253
|
-
|
254
|
-
if (differences.length < 2) {
|
255
|
-
throw new Error('Need at least 2 valid paired observations');
|
256
|
-
}
|
257
|
-
|
258
|
-
return this.mean(differences, confidence);
|
259
|
-
}
|
260
|
-
|
261
|
-
correlation(x, y, confidence = 0.95, method = 'pearson') {
|
262
|
-
if (confidence <= 0 || confidence >= 1) {
|
263
|
-
throw new Error('Confidence level must be between 0 and 1');
|
264
|
-
}
|
265
|
-
|
266
|
-
if (x.length !== y.length) {
|
267
|
-
throw new Error('x and y must have the same length');
|
268
|
-
}
|
269
|
-
|
270
|
-
const validPairs = [];
|
271
|
-
for (let i = 0; i < x.length; i++) {
|
272
|
-
if (typeof x[i] === 'number' && typeof y[i] === 'number' &&
|
273
|
-
!isNaN(x[i]) && !isNaN(y[i]) && isFinite(x[i]) && isFinite(y[i])) {
|
274
|
-
validPairs.push({ x: x[i], y: y[i] });
|
275
|
-
}
|
276
|
-
}
|
277
|
-
|
278
|
-
if (validPairs.length < 3) {
|
279
|
-
throw new Error('Need at least 3 valid paired observations');
|
280
|
-
}
|
281
|
-
|
282
|
-
const n = validPairs.length;
|
283
|
-
let r;
|
284
|
-
|
285
|
-
if (method === 'pearson') {
|
286
|
-
const xVals = validPairs.map(pair => pair.x);
|
287
|
-
const yVals = validPairs.map(pair => pair.y);
|
288
|
-
r = this.pearsonCorrelation(xVals, yVals);
|
289
|
-
} else {
|
290
|
-
throw new Error('Only Pearson correlation is supported for confidence intervals');
|
291
|
-
}
|
292
|
-
|
293
|
-
if (Math.abs(r) >= 1) {
|
294
|
-
throw new Error('Cannot calculate confidence interval for perfect correlation');
|
295
|
-
}
|
296
|
-
|
297
|
-
const fisherZ = 0.5 * Math.log((1 + r) / (1 - r));
|
298
|
-
const stdError = 1 / Math.sqrt(n - 3);
|
299
|
-
const alpha = 1 - confidence;
|
300
|
-
const zCritical = this.normalInverse(1 - alpha / 2);
|
301
|
-
const marginOfError = zCritical * stdError;
|
302
|
-
|
303
|
-
const lowerZ = fisherZ - marginOfError;
|
304
|
-
const upperZ = fisherZ + marginOfError;
|
305
|
-
|
306
|
-
const lowerR = (Math.exp(2 * lowerZ) - 1) / (Math.exp(2 * lowerZ) + 1);
|
307
|
-
const upperR = (Math.exp(2 * upperZ) - 1) / (Math.exp(2 * upperZ) + 1);
|
308
|
-
|
309
|
-
return {
|
310
|
-
correlation: r,
|
311
|
-
fisherZ: fisherZ,
|
312
|
-
standardError: stdError,
|
313
|
-
lowerBound: lowerR,
|
314
|
-
upperBound: upperR,
|
315
|
-
confidence: confidence,
|
316
|
-
sampleSize: n
|
317
|
-
};
|
318
|
-
}
|
319
|
-
|
320
|
-
pearsonCorrelation(x, y) {
|
321
|
-
const n = x.length;
|
322
|
-
const meanX = x.reduce((sum, val) => sum + val, 0) / n;
|
323
|
-
const meanY = y.reduce((sum, val) => sum + val, 0) / n;
|
324
|
-
|
325
|
-
let numerator = 0;
|
326
|
-
let sumXSquared = 0;
|
327
|
-
let sumYSquared = 0;
|
328
|
-
|
329
|
-
for (let i = 0; i < n; i++) {
|
330
|
-
const xDiff = x[i] - meanX;
|
331
|
-
const yDiff = y[i] - meanY;
|
332
|
-
numerator += xDiff * yDiff;
|
333
|
-
sumXSquared += xDiff * xDiff;
|
334
|
-
sumYSquared += yDiff * yDiff;
|
335
|
-
}
|
336
|
-
|
337
|
-
const denominator = Math.sqrt(sumXSquared * sumYSquared);
|
338
|
-
return denominator === 0 ? 0 : numerator / denominator;
|
339
|
-
}
|
340
|
-
|
341
|
-
median(sample, confidence = 0.95) {
|
342
|
-
if (confidence <= 0 || confidence >= 1) {
|
343
|
-
throw new Error('Confidence level must be between 0 and 1');
|
344
|
-
}
|
345
|
-
|
346
|
-
const validSample = sample.filter(val =>
|
347
|
-
typeof val === 'number' && !isNaN(val) && isFinite(val)
|
348
|
-
);
|
349
|
-
|
350
|
-
if (validSample.length < 3) {
|
351
|
-
throw new Error('Need at least 3 valid observations for median CI');
|
352
|
-
}
|
353
|
-
|
354
|
-
const sorted = [...validSample].sort((a, b) => a - b);
|
355
|
-
const n = sorted.length;
|
356
|
-
const alpha = 1 - confidence;
|
357
|
-
|
358
|
-
const z = this.normalInverse(1 - alpha / 2);
|
359
|
-
const j = Math.floor(n / 2 - z * Math.sqrt(n) / 2);
|
360
|
-
const k = Math.ceil(n / 2 + z * Math.sqrt(n) / 2);
|
361
|
-
|
362
|
-
const lowerIndex = Math.max(0, j - 1);
|
363
|
-
const upperIndex = Math.min(n - 1, k - 1);
|
364
|
-
|
365
|
-
const median = n % 2 === 0 ?
|
366
|
-
(sorted[n / 2 - 1] + sorted[n / 2]) / 2 :
|
367
|
-
sorted[Math.floor(n / 2)];
|
368
|
-
|
369
|
-
return {
|
370
|
-
median: median,
|
371
|
-
lowerBound: sorted[lowerIndex],
|
372
|
-
upperBound: sorted[upperIndex],
|
373
|
-
confidence: confidence,
|
374
|
-
sampleSize: n,
|
375
|
-
lowerIndex: lowerIndex + 1,
|
376
|
-
upperIndex: upperIndex + 1
|
377
|
-
};
|
378
|
-
}
|
379
|
-
|
380
|
-
bootstrapCI(sample, statistic, confidence = 0.95, iterations = 1000) {
|
381
|
-
if (confidence <= 0 || confidence >= 1) {
|
382
|
-
throw new Error('Confidence level must be between 0 and 1');
|
383
|
-
}
|
384
|
-
|
385
|
-
const validSample = sample.filter(val =>
|
386
|
-
typeof val === 'number' && !isNaN(val) && isFinite(val)
|
387
|
-
);
|
388
|
-
|
389
|
-
if (validSample.length === 0) {
|
390
|
-
throw new Error('No valid numeric values found');
|
391
|
-
}
|
392
|
-
|
393
|
-
const bootstrapStats = [];
|
394
|
-
|
395
|
-
for (let i = 0; i < iterations; i++) {
|
396
|
-
const bootstrapSample = [];
|
397
|
-
for (let j = 0; j < validSample.length; j++) {
|
398
|
-
const randomIndex = Math.floor(Math.random() * validSample.length);
|
399
|
-
bootstrapSample.push(validSample[randomIndex]);
|
400
|
-
}
|
401
|
-
|
402
|
-
const stat = this.calculateStatistic(bootstrapSample, statistic);
|
403
|
-
bootstrapStats.push(stat);
|
404
|
-
}
|
405
|
-
|
406
|
-
bootstrapStats.sort((a, b) => a - b);
|
407
|
-
|
408
|
-
const alpha = 1 - confidence;
|
409
|
-
const lowerIndex = Math.floor((alpha / 2) * iterations);
|
410
|
-
const upperIndex = Math.floor((1 - alpha / 2) * iterations) - 1;
|
411
|
-
|
412
|
-
const originalStat = this.calculateStatistic(validSample, statistic);
|
413
|
-
const bootstrapMean = bootstrapStats.reduce((sum, val) => sum + val, 0) / bootstrapStats.length;
|
414
|
-
|
415
|
-
return {
|
416
|
-
originalStatistic: originalStat,
|
417
|
-
bootstrapMean: bootstrapMean,
|
418
|
-
bias: bootstrapMean - originalStat,
|
419
|
-
standardError: this.calculateStandardDeviation(bootstrapStats),
|
420
|
-
lowerBound: bootstrapStats[lowerIndex],
|
421
|
-
upperBound: bootstrapStats[upperIndex],
|
422
|
-
confidence: confidence,
|
423
|
-
iterations: iterations
|
424
|
-
};
|
425
|
-
}
|
426
|
-
|
427
|
-
calculateStatistic(sample, statistic) {
|
428
|
-
switch (statistic) {
|
429
|
-
case 'mean':
|
430
|
-
return sample.reduce((sum, val) => sum + val, 0) / sample.length;
|
431
|
-
case 'median':
|
432
|
-
const sorted = [...sample].sort((a, b) => a - b);
|
433
|
-
const mid = Math.floor(sorted.length / 2);
|
434
|
-
return sorted.length % 2 === 0 ?
|
435
|
-
(sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
436
|
-
case 'std':
|
437
|
-
return this.calculateStandardDeviation(sample);
|
438
|
-
case 'var':
|
439
|
-
return this.calculateVariance(sample);
|
440
|
-
default:
|
441
|
-
if (typeof statistic === 'function') {
|
442
|
-
return statistic(sample);
|
443
|
-
}
|
444
|
-
throw new Error(`Unknown statistic: ${statistic}`);
|
445
|
-
}
|
446
|
-
}
|
447
|
-
|
448
|
-
calculateStandardDeviation(sample) {
|
449
|
-
const mean = sample.reduce((sum, val) => sum + val, 0) / sample.length;
|
450
|
-
const variance = sample.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (sample.length - 1);
|
451
|
-
return Math.sqrt(variance);
|
452
|
-
}
|
453
|
-
|
454
|
-
calculateVariance(sample) {
|
455
|
-
const mean = sample.reduce((sum, val) => sum + val, 0) / sample.length;
|
456
|
-
return sample.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (sample.length - 1);
|
457
|
-
}
|
458
|
-
|
459
|
-
normalInverse(p) {
|
460
|
-
if (p <= 0 || p >= 1) throw new Error('p must be between 0 and 1');
|
461
|
-
|
462
|
-
const a = [-3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02,
|
463
|
-
1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00];
|
464
|
-
const b = [-5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02,
|
465
|
-
6.680131188771972e+01, -1.328068155288572e+01, 1];
|
466
|
-
|
467
|
-
if (p > 0.5) return -this.normalInverse(1 - p);
|
468
|
-
|
469
|
-
const q = Math.sqrt(-2 * Math.log(p));
|
470
|
-
let num = a[5];
|
471
|
-
let den = b[5];
|
472
|
-
|
473
|
-
for (let i = 4; i >= 0; i--) {
|
474
|
-
num = num * q + a[i];
|
475
|
-
den = den * q + b[i];
|
476
|
-
}
|
477
|
-
|
478
|
-
return num / den;
|
479
|
-
}
|
480
|
-
|
481
|
-
tInverse(p, df) {
|
482
|
-
if (p <= 0 || p >= 1) return NaN;
|
483
|
-
|
484
|
-
let t = this.normalInverse(p);
|
485
|
-
const c1 = t / 4;
|
486
|
-
const c2 = (5 * t * t * t + 16 * t) / 96;
|
487
|
-
const c3 = (3 * t * t * t * t * t + 19 * t * t * t + 17 * t) / 384;
|
488
|
-
|
489
|
-
return t + c1 / df + c2 / (df * df) + c3 / (df * df * df);
|
490
|
-
}
|
491
|
-
|
492
|
-
chiSquareInverse(p, df) {
|
493
|
-
if (p <= 0 || p >= 1) throw new Error('p must be between 0 and 1');
|
494
|
-
if (df <= 0) throw new Error('Degrees of freedom must be positive');
|
495
|
-
|
496
|
-
let x = df;
|
497
|
-
const tolerance = 1e-12;
|
498
|
-
const maxIterations = 100;
|
499
|
-
|
500
|
-
for (let i = 0; i < maxIterations; i++) {
|
501
|
-
const fx = this.chiSquareCDF(x, df) - p;
|
502
|
-
const fpx = this.chiSquarePDF(x, df);
|
503
|
-
|
504
|
-
if (Math.abs(fx) < tolerance) break;
|
505
|
-
if (fpx === 0) break;
|
506
|
-
|
507
|
-
x = x - fx / fpx;
|
508
|
-
if (x <= 0) x = df / 2;
|
509
|
-
}
|
510
|
-
|
511
|
-
return Math.max(0, x);
|
512
|
-
}
|
513
|
-
|
514
|
-
chiSquareCDF(x, df) {
|
515
|
-
if (x <= 0) return 0;
|
516
|
-
return this.incompleteGamma(df / 2, x / 2) / this.gamma(df / 2);
|
517
|
-
}
|
518
|
-
|
519
|
-
chiSquarePDF(x, df) {
|
520
|
-
if (x <= 0) return 0;
|
521
|
-
return Math.pow(x, df / 2 - 1) * Math.exp(-x / 2) / (Math.pow(2, df / 2) * this.gamma(df / 2));
|
522
|
-
}
|
523
|
-
|
524
|
-
incompleteGamma(a, x) {
|
525
|
-
if (x <= 0) return 0;
|
526
|
-
|
527
|
-
let sum = 1;
|
528
|
-
let term = 1;
|
529
|
-
|
530
|
-
for (let n = 1; n < 100; n++) {
|
531
|
-
term *= x / (a + n - 1);
|
532
|
-
sum += term;
|
533
|
-
if (Math.abs(term) < 1e-12) break;
|
534
|
-
}
|
535
|
-
|
536
|
-
return Math.pow(x, a) * Math.exp(-x) * sum;
|
537
|
-
}
|
538
|
-
|
539
|
-
gamma(x) {
|
540
|
-
const coefficients = [
|
541
|
-
0.99999999999980993, 676.5203681218851, -1259.1392167224028,
|
542
|
-
771.32342877765313, -176.61502916214059, 12.507343278686905,
|
543
|
-
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7
|
544
|
-
];
|
545
|
-
|
546
|
-
if (x < 0.5) {
|
547
|
-
return Math.PI / (Math.sin(Math.PI * x) * this.gamma(1 - x));
|
548
|
-
}
|
549
|
-
|
550
|
-
x -= 1;
|
551
|
-
let result = coefficients[0];
|
552
|
-
for (let i = 1; i < coefficients.length; i++) {
|
553
|
-
result += coefficients[i] / (x + i);
|
554
|
-
}
|
555
|
-
|
556
|
-
const t = x + coefficients.length - 1.5;
|
557
|
-
return Math.sqrt(2 * Math.PI) * Math.pow(t, x + 0.5) * Math.exp(-t) * result;
|
558
|
-
}
|
559
|
-
}
|
560
|
-
|
561
|
-
export default ConfidenceIntervals;
|