Skip to content

Commit 76c19a0

Browse files
committed
update cochran test
1 parent e7f3b1a commit 76c19a0

File tree

5 files changed

+62
-43
lines changed

5 files changed

+62
-43
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "labkar-algorithms",
3-
"version": "4.0.0",
3+
"version": "5.0.0",
44
"description": "Labkar Algorithms",
55
"main": "dist/lib.js",
66
"author": "ODTÜ PAL",

src/algorithms/cochran.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,27 @@ import { CochranResult } from '../types';
33
import { sampleStandardDeviation } from 'simple-statistics';
44
import cochranCriticalValues from './cochranCriticalValues';
55

6+
type CochranOptions = {
7+
alpha: number;
8+
originalIndexes?: number[];
9+
outlierIndexes?: number[];
10+
}
11+
612
export function Cochran(
713
values: Array<number[]>,
8-
options: { alpha: number } = { alpha: 0.05 }
14+
options: CochranOptions = { alpha: 0.05 }
915
): CochranResult | null {
16+
17+
// Keep track of original indexes of values at the beginning
18+
// When we return indexes of outliers, this will be useful.
19+
const originalIndexes = options.originalIndexes
20+
? options.originalIndexes
21+
: values.map((_, i) => i);
22+
23+
// This is where we store outlier indexes across all iterations.
24+
// The indexes are relative to the original array.
25+
const outlierIndexes = options.outlierIndexes ? options.outlierIndexes : [];
26+
1027
/* p -> numune sayısı */
1128
const pValue = values.length;
1229

@@ -33,25 +50,24 @@ export function Cochran(
3350

3451
// These are the values used to calculate max deviation
3552
const cPairIndex = squareDeviations.indexOf(maxDeviation);
36-
const cPair = values[squareDeviations.indexOf(maxDeviation)];
37-
3853
const cValue = maxDeviation / sumOfSquareDeviations;
3954

4055
if (cValue < criticalValue) {
4156
return {
42-
outlier: false,
43-
cValue,
44-
cPair,
45-
cPairIndex: cPairIndex,
46-
maxDeviation,
57+
outlierIndexes,
58+
hasOutliers: outlierIndexes.length > 0,
4759
};
4860
}
4961

50-
return {
51-
outlier: true,
52-
cValue,
53-
cPair,
54-
cPairIndex,
55-
maxDeviation,
56-
};
62+
outlierIndexes.push(originalIndexes[cPairIndex]);
63+
originalIndexes.splice(cPairIndex, 1);
64+
65+
return Cochran(
66+
values.filter((_, i) => i !== cPairIndex),
67+
{
68+
alpha: options.alpha,
69+
originalIndexes,
70+
outlierIndexes
71+
}
72+
)
5773
}

src/types.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,11 @@ export type AResult = {
1111
};
1212

1313
export type CochranResult = {
14-
outlier: boolean;
14+
hasOutliers: boolean;
1515
/**
16-
* Value used to compare to the elected critical value
16+
* Indexes of outliers across all tests
1717
*/
18-
cValue: number;
19-
/**
20-
* The pair used to calculate the max deviation
21-
*/
22-
cPair: number[];
23-
/**
24-
* Index of the pair used to calculate the max deviation
25-
*/
26-
cPairIndex: number;
27-
/**
28-
* Maximum value among (stdDev(pair) ^ 2)
29-
*/
30-
maxDeviation: number;
18+
outlierIndexes: number[];
3119
};
3220

3321
export type ReferenceResult = {

tests/cochran.test.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,15 @@ describe('Cochran Algorithm', () => {
2121
];
2222

2323
let output = Cochran(samples, { alpha: 0.05 });
24-
expect(output?.maxDeviation).toBeCloseTo(31.205, 3);
25-
expect(output?.cPairIndex).toBe(11);
26-
expect(output?.cPair).toEqual([91, 83.1]);
27-
expect(output?.outlier).toBe(true);
24+
expect(output?.hasOutliers).toBe(true);
25+
expect(output?.outlierIndexes).toEqual([11]);
2826

2927
output = Cochran(samples, { alpha: 0.01 });
30-
expect(output?.outlier).toBe(true);
28+
expect(output?.hasOutliers).toBe(true);
29+
expect(output?.outlierIndexes).toEqual([11]);
3130
});
3231

33-
it.only('Cochran Algorithm Test (Straggler)', () => {
32+
it('Cochran Algorithm Test (Straggler)', () => {
3433
const samples = [
3534
[9.9, 10.2],
3635
[10.4, 9.5],
@@ -45,10 +44,10 @@ describe('Cochran Algorithm', () => {
4544
];
4645

4746
let output = Cochran(samples);
48-
expect(output?.outlier).toBe(true);
47+
expect(output?.hasOutliers).toBe(true);
4948

5049
output = Cochran(samples, { alpha: 0.01 });
51-
expect(output?.outlier).toBe(false);
50+
expect(output?.hasOutliers).toBe(false);
5251
});
5352

5453
it('Cochran Algorithm Test (Null)', () => {
@@ -58,7 +57,23 @@ describe('Cochran Algorithm', () => {
5857
expect(output).toBe(null);
5958
});
6059

61-
it.todo('Cochran Algorithm Test (Straggler)');
60+
it('Repeats test until there are no outliers', () => {
6261

63-
//TODO: Any value considered as straggler
62+
const samples = [
63+
[0.135, 0.194], // index=0 = outlier
64+
[0.187, 0.189],
65+
[0.182, 0.186],
66+
[0.188, 0.196],
67+
[0.191, 0.181],
68+
[0.188, 0.018], // index=5 = outlier
69+
[0.187, 0.196],
70+
[0.177, 0.186],
71+
[0.179, 0.187],
72+
[0.188, 0.196],
73+
]
74+
75+
const output = Cochran(samples, { alpha: 0.01 });
76+
expect(output?.outlierIndexes).toContain(0);
77+
expect(output?.outlierIndexes).toContain(5);
78+
})
6479
});

0 commit comments

Comments
 (0)