Skip to content

Commit 59cd257

Browse files
committed
implement quartilemethod options in violin trace
1 parent 68a4917 commit 59cd257

File tree

6 files changed

+125
-1
lines changed

6 files changed

+125
-1
lines changed

src/traces/violin/attributes.js

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ module.exports = {
154154
hovertext: boxAttrs.hovertext,
155155
hovertemplate: boxAttrs.hovertemplate,
156156

157+
quartilemethod: boxAttrs.quartilemethod,
158+
157159
box: {
158160
visible: {
159161
valType: 'boolean',

src/traces/violin/defaults.js

+2
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
4848
var meanLineWidth = coerce2('meanline.width', lineWidth);
4949
var meanLineVisible = coerce('meanline.visible', Boolean(meanLineColor || meanLineWidth));
5050
if(!meanLineVisible) traceOut.meanline = {visible: false};
51+
52+
coerce('quartilemethod');
5153
};
9.39 KB
Loading

test/image/mocks/box_quartile-methods.json

+33-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,37 @@
1313
"y": [1, 2, 3, 4, 5],
1414
"name": "inclusive",
1515
"quartilemethod": "inclusive"
16-
}]
16+
},
17+
18+
{
19+
"type": "violin",
20+
"yaxis": "y2",
21+
"y": [1, 2, 3, 4, 5],
22+
"name": "linear"
23+
}, {
24+
"type": "violin",
25+
"yaxis": "y2",
26+
"y": [1, 2, 3, 4, 5],
27+
"name": "exclusive",
28+
"quartilemethod": "exclusive"
29+
}, {
30+
"type": "violin",
31+
"yaxis": "y2",
32+
"y": [1, 2, 3, 4, 5],
33+
"name": "inclusive",
34+
"quartilemethod": "inclusive"
35+
}],
36+
"layout": {
37+
"yaxis": {
38+
"domain": [0, 0.45]
39+
},
40+
"yaxis2": {
41+
"domain": [0.55, 1]
42+
},
43+
"width": 500,
44+
"height": 500,
45+
"title": {
46+
"text": "box and violin quartile methods"
47+
}
48+
}
1749
}

test/jasmine/tests/violin_test.js

+77
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,85 @@ describe('Test violin calc:', function() {
223223
Plots.doCalcdata(gd);
224224
cd = gd.calcdata[0];
225225
fullLayout = gd._fullLayout;
226+
return cd;
226227
}
227228

229+
it('should compute q1/q3 depending on *quartilemethod*', function() {
230+
// samples from https://en.wikipedia.org/wiki/Quartile
231+
var specs = {
232+
// N is odd and is spanned by (4n+3)
233+
odd: {
234+
sample: [6, 7, 15, 36, 39, 40, 41, 42, 43, 47, 49],
235+
methods: {
236+
linear: {q1: 20.25, q3: 42.75},
237+
exclusive: {q1: 15, q3: 43},
238+
inclusive: {q1: 25.5, q3: 42.5}
239+
}
240+
},
241+
// N is odd and is spanned by (4n+1)
242+
odd2: {
243+
sample: [6, 15, 36, 39, 40, 42, 43, 47, 49],
244+
methods: {
245+
linear: {q1: 30.75, q3: 44},
246+
exclusive: {q1: 25.5, q3: 45},
247+
inclusive: {q1: 36, q3: 43}
248+
}
249+
},
250+
// N is even
251+
even: {
252+
sample: [7, 15, 36, 39, 40, 41],
253+
methods: {
254+
linear: {q1: 15, q3: 40},
255+
exclusive: {q1: 15, q3: 40},
256+
inclusive: {q1: 15, q3: 40}
257+
}
258+
},
259+
// samples from http://jse.amstat.org/v14n3/langford.html
260+
s4: {
261+
sample: [1, 2, 3, 4],
262+
methods: {
263+
linear: {q1: 1.5, q3: 3.5},
264+
exclusive: {q1: 1.5, q3: 3.5},
265+
inclusive: {q1: 1.5, q3: 3.5}
266+
}
267+
},
268+
s5: {
269+
sample: [1, 2, 3, 4, 5],
270+
methods: {
271+
linear: {q1: 1.75, q3: 4.25},
272+
exclusive: {q1: 1.5, q3: 4.5},
273+
inclusive: {q1: 2, q3: 4}
274+
}
275+
},
276+
s6: {
277+
sample: [1, 2, 3, 4, 5, 6],
278+
methods: {
279+
linear: {q1: 2, q3: 5},
280+
exclusive: {q1: 2, q3: 5},
281+
inclusive: {q1: 2, q3: 5}
282+
}
283+
},
284+
s7: {
285+
sample: [1, 2, 3, 4, 5, 6, 7],
286+
methods: {
287+
linear: {q1: 2.25, q3: 5.75},
288+
exclusive: {q1: 2, q3: 6},
289+
inclusive: {q1: 2.5, q3: 5.5}
290+
}
291+
}
292+
};
293+
294+
for(var name in specs) {
295+
var spec = specs[name];
296+
297+
for(var m in spec.methods) {
298+
var cd = _calc({y: spec.sample, quartilemethod: m});
299+
expect(cd[0].q1).toBe(spec.methods[m].q1, ['q1', m, name].join(' | '));
300+
expect(cd[0].q3).toBe(spec.methods[m].q3, ['q3', m, name].join(' | '));
301+
}
302+
}
303+
});
304+
228305
it('should compute bandwidth and span based on the sample and *spanmode*', function() {
229306
var y = [1, 1, 2, 2, 3];
230307

test/plot-schema.json

+11
Original file line numberDiff line numberDiff line change
@@ -69495,6 +69495,17 @@
6949569495
false
6949669496
]
6949769497
},
69498+
"quartilemethod": {
69499+
"description": "Sets the method used to compute the sample's Q1 and Q3 quartiles. The *linear* method uses the 25th percentile for Q1 and 75th percentile for Q3 as computed using method #10 (listed on http://www.amstat.org/publications/jse/v14n3/langford.html). The *exclusive* method uses the median to divide the ordered dataset into two halves if the sample is odd, it does not include the median in either half - Q1 is then the median of the lower half and Q3 the median of the upper half. The *inclusive* method also uses the median to divide the ordered dataset into two halves but if the sample is odd, it includes the median in both halves - Q1 is then the median of the lower half and Q3 the median of the upper half.",
69500+
"dflt": "linear",
69501+
"editType": "calc",
69502+
"valType": "enumerated",
69503+
"values": [
69504+
"linear",
69505+
"exclusive",
69506+
"inclusive"
69507+
]
69508+
},
6949869509
"scalegroup": {
6949969510
"description": "If there are multiple violins that should be sized according to to some metric (see `scalemode`), link them by providing a non-empty group id here shared by every trace in the same group. If a violin's `width` is undefined, `scalegroup` will default to the trace's name. In this case, violins with the same names will be linked together",
6950069511
"dflt": "",

0 commit comments

Comments
 (0)