-
Notifications
You must be signed in to change notification settings - Fork 0
/
violin-plot.js
70 lines (63 loc) · 1.76 KB
/
violin-plot.js
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
function processViolin(step, precision, densityWidth, ...args) {
let xiData = [];
//process the xi
function prcessXi(args) {
let tempXdata = [];
let tileSteps = 6; //Nbr of point at the top and end of the violin
let min = Infinity,
max = -Infinity;
//process the range of the data set
args.forEach((e) => {
min = Math.min(min, Math.min(...e));
max = Math.max(max, Math.max(...e));
});
for (i = min - tileSteps * step; i < max + tileSteps * step; i++) {
tempXdata.push(i);
}
return tempXdata;
}
xiData = prcessXi(args);
//the KDE gaussian function
function kdeProcess(xi, u) {
return (1 / Math.sqrt(2 * Math.PI)) * Math.exp(Math.pow(xi - u, 2) / -2);
}
let gap = -1;
//Create the upper and lower line of the violin
function violinProcess(dataSource) {
let data = [];
let N = dataSource.length;
gap++;
for (i = 0; i < xiData.length; i++) {
let temp = 0;
for (j = 0; j < dataSource.length; j++) {
temp = temp + kdeProcess(xiData[i], dataSource[j]);
}
data.push([xiData[i], (1 / N) * temp]);
}
return data.map((violinPoint, i) => {
if (violinPoint[1] > precision) {
return [xiData[i], -(violinPoint[1]*densityWidth) + gap, (violinPoint[1]*densityWidth) + gap];
} else {
return [xiData[i], null, null];
}
});
}
let results = [];
let stat = [];
let index = 0;
args.forEach((e) => {
results.push([]);
stat.push([]);
results[index] = violinProcess(e).slice();
//Min, Q1, Median, Q3, Max
stat[index].push(
Math.min(...e),
jStat.quartiles(e)[0],
jStat.quartiles(e)[1],
jStat.quartiles(e)[2],
Math.max(...e)
);
index++;
});
return { xiData, results, stat };
}