Skip to content

Commit dbf02f1

Browse files
authored
Merge pull request #4388 from plotly/fix-notched-box-autorange
Fix notched box autorange
2 parents 5ef8a61 + e663c4b commit dbf02f1

File tree

4 files changed

+52
-3
lines changed

4 files changed

+52
-3
lines changed

src/traces/box/attributes.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ module.exports = {
100100
role: 'style',
101101
editType: 'calc',
102102
description: [
103-
'Determines whether or not notches should be drawn.'
103+
'Determines whether or not notches are drawn.',
104+
'Notches displays a confidence interval around the median.',
105+
'We compute the confidence interval as median +/- 1.57 / IQR * sqrt(N),',
106+
'where IQR is the interquartile range and N is the sample size.',
107+
'If two boxes\' notches do not overlap there is 95% confidence their medians differ.',
108+
'See https://sites.google.com/site/davidsstatistics/home/notched-box-plots for more info.'
104109
].join(' ')
105110
},
106111
notchwidth: {

src/traces/box/calc.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ module.exports = function calc(gd, trace) {
6969
Lib.identity :
7070
function(pt) { return (pt.v < cdi.lf || pt.v > cdi.uf); };
7171

72+
var minLowerNotch = Infinity;
73+
var maxUpperNotch = -Infinity;
74+
7275
// build calcdata trace items, one item per distinct position
7376
for(i = 0; i < pLen; i++) {
7477
if(ptsPerBin[i].length > 0) {
@@ -123,6 +126,8 @@ module.exports = function calc(gd, trace) {
123126
var mci = 1.57 * iqr / Math.sqrt(bvLen);
124127
cdi.ln = cdi.med - mci;
125128
cdi.un = cdi.med + mci;
129+
minLowerNotch = Math.min(minLowerNotch, cdi.ln);
130+
maxUpperNotch = Math.max(maxUpperNotch, cdi.un);
126131

127132
cdi.pts2 = pts.filter(ptFilterFn);
128133

@@ -131,8 +136,11 @@ module.exports = function calc(gd, trace) {
131136
}
132137

133138
calcSelection(cd, trace);
134-
var extremes = Axes.findExtremes(valAxis, val, {padded: true});
135-
trace._extremes[valAxis._id] = extremes;
139+
140+
trace._extremes[valAxis._id] = Axes.findExtremes(valAxis,
141+
trace.notched ? val.concat([minLowerNotch, maxUpperNotch]) : val,
142+
{padded: true}
143+
);
136144

137145
if(cd.length > 0) {
138146
cd[0].t = {
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"data": [
3+
{
4+
"x": [113.35, 29.54, 21.7, 113.35, 29.54, 21.7],
5+
"name": "[113.35,29.54,21.7,113.35,29.54,21.7]",
6+
"type": "box",
7+
"notched": true
8+
},
9+
{
10+
"x": [39.4, 88.63, 39.4, 88.63],
11+
"name": "[39.4,88.63,39.4,88.63]",
12+
"type": "box",
13+
"notched": true
14+
}
15+
],
16+
"layout": {
17+
"title": {
18+
"text": "Samples where the confidence interval<br>median ± 1.57 / IQR * sqrt(N)<br>go beyond the fences",
19+
"x": 0.02
20+
},
21+
"xaxis": {
22+
"showline": true,
23+
"mirror": true,
24+
"zeroline": false
25+
},
26+
"yaxis": {
27+
"showline": true,
28+
"mirror": true,
29+
"zeroline": false
30+
},
31+
"showlegend": false,
32+
"margin": {"l": 220, "b": 20, "r": 20},
33+
"width": 600,
34+
"height": 300
35+
}
36+
}

0 commit comments

Comments
 (0)