-
Notifications
You must be signed in to change notification settings - Fork 87
/
score.ts
142 lines (126 loc) · 3.61 KB
/
score.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Utilities for Scoring Validators
// Sorts an array by ascending values
export const asc = (arr: number[]) => arr.sort((a, b) => a - b);
export const absMin = (arr: number[]) => {
const sorted = asc(arr);
return Number(sorted[0]);
};
export const absMax = (arr: number[]) => {
const sorted = asc(arr);
return Number(sorted[sorted.length - 1]);
};
export const sum = (arr: number[]) => arr.reduce((a, b) => a + b, 0);
export const mean = (arr: number[]) => sum(arr) / arr.length;
export const std = (arr: number[]) => {
const mu = mean(arr);
const diffArr = arr.map((a) => (a - mu) ** 2);
return Math.sqrt(sum(diffArr) / (arr.length - 1));
};
export const quantile = (arr: number[], q: number) => {
const sorted = asc(arr);
const pos = (sorted.length - 1) * q;
const base = Math.floor(pos);
const rest = pos - base;
if (sorted[base + 1] !== undefined) {
return sorted[base] + rest * (sorted[base + 1] - sorted[base]);
} else {
return sorted[base];
}
};
export const q10 = (arr: number[]) => quantile(arr, 0.1);
export const q25 = (arr: number[]) => quantile(arr, 0.25);
export const q50 = (arr: number[]) => quantile(arr, 0.5);
export const q75 = (arr: number[]) => quantile(arr, 0.75);
export const q90 = (arr: number[]) => quantile(arr, 0.9);
export const median = (arr: number[]) => q50(arr);
export const scaled = (value: number, arr: number[]): number => {
const aq10 = q10(arr);
const aq90 = q90(arr);
if (value <= aq10) return 0;
if (value >= aq90) return 1;
return (value - aq10) / (aq90 - aq10);
};
export const scaledDefined = (
value: number,
arr: number[],
lowQuartile: number,
highQuartile: number,
): number => {
if (arr.length == 0) return 0;
const lowQ = quantile(arr, lowQuartile);
const highQ = quantile(arr, highQuartile);
if (value <= lowQ) return 0;
if (value >= highQ) return 1;
return (value - lowQ) / (highQ - lowQ);
};
export interface LocationStats {
values: { name?: string; numberOfNodes: number }[];
absoluteMin: number;
absoluteMax: number;
q10: number;
q25: number;
q50: number;
q75: number;
q90: number;
mean: number;
standardDeviation: number;
}
export interface Stats {
values: number[];
absoluteMin: number;
absoluteMax: number;
q10: number;
q25: number;
q50: number;
q75: number;
q90: number;
mean: number;
standardDeviation: number;
}
export const getStats = (arr: number[]): Stats => {
const arrAbsMin = arr.length !== 0 ? absMin(arr) : 0;
const arrAbsMax = arr.length !== 0 ? absMax(arr) : 0;
const arrQ10 = arr.length !== 0 ? q10(arr) : 0;
const arrQ25 = arr.length !== 0 ? q25(arr) : 0;
const arrQ50 = arr.length !== 0 ? q50(arr) : 0;
const arrQ75 = arr.length !== 0 ? q75(arr) : 0;
const arrQ90 = arr.length !== 0 ? q90(arr) : 0;
const arrMean = arr.length !== 0 ? mean(arr) : 0;
const arrStd = arr.length > 1 ? std(arr) : 0;
return {
values: arr,
absoluteMin: arrAbsMin,
absoluteMax: arrAbsMax,
q10: arrQ10,
q25: arrQ25,
q50: arrQ50,
q75: arrQ75,
q90: arrQ90,
mean: arrMean,
standardDeviation: arrStd,
};
};
export const lastValues = (
array: number[],
lastValue: number,
threshold: number,
): number[] => {
const sorted = asc(array);
return sorted.filter((x) => {
return lastValue - threshold < x;
});
};
export const variance = (arr: number[] = []): number => {
if (!arr.length) {
return 0;
}
const sum = arr.reduce((acc, val) => acc + val);
const { length: num } = arr;
const median = sum / num;
let variance = 0;
arr.forEach((num) => {
variance += (num - median) * (num - median);
});
variance /= num;
return variance;
};