diff --git a/src/traces/box/attributes.js b/src/traces/box/attributes.js
index a8144de00d0..8b31df30dc9 100644
--- a/src/traces/box/attributes.js
+++ b/src/traces/box/attributes.js
@@ -100,7 +100,12 @@ module.exports = {
role: 'style',
editType: 'calc',
description: [
- 'Determines whether or not notches should be drawn.'
+ 'Determines whether or not notches are drawn.',
+ 'Notches displays a confidence interval around the median.',
+ 'We compute the confidence interval as median +/- 1.57 / IQR * sqrt(N),',
+ 'where IQR is the interquartile range and N is the sample size.',
+ 'If two boxes\' notches do not overlap there is 95% confidence their medians differ.',
+ 'See https://sites.google.com/site/davidsstatistics/home/notched-box-plots for more info.'
].join(' ')
},
notchwidth: {
diff --git a/src/traces/box/calc.js b/src/traces/box/calc.js
index 092d5795fdd..992c2dc64d7 100644
--- a/src/traces/box/calc.js
+++ b/src/traces/box/calc.js
@@ -69,6 +69,9 @@ module.exports = function calc(gd, trace) {
Lib.identity :
function(pt) { return (pt.v < cdi.lf || pt.v > cdi.uf); };
+ var minLowerNotch = Infinity;
+ var maxUpperNotch = -Infinity;
+
// build calcdata trace items, one item per distinct position
for(i = 0; i < pLen; i++) {
if(ptsPerBin[i].length > 0) {
@@ -123,6 +126,8 @@ module.exports = function calc(gd, trace) {
var mci = 1.57 * iqr / Math.sqrt(bvLen);
cdi.ln = cdi.med - mci;
cdi.un = cdi.med + mci;
+ minLowerNotch = Math.min(minLowerNotch, cdi.ln);
+ maxUpperNotch = Math.max(maxUpperNotch, cdi.un);
cdi.pts2 = pts.filter(ptFilterFn);
@@ -131,8 +136,11 @@ module.exports = function calc(gd, trace) {
}
calcSelection(cd, trace);
- var extremes = Axes.findExtremes(valAxis, val, {padded: true});
- trace._extremes[valAxis._id] = extremes;
+
+ trace._extremes[valAxis._id] = Axes.findExtremes(valAxis,
+ trace.notched ? val.concat([minLowerNotch, maxUpperNotch]) : val,
+ {padded: true}
+ );
if(cd.length > 0) {
cd[0].t = {
diff --git a/test/image/baselines/box_notched-inverted-end.png b/test/image/baselines/box_notched-inverted-end.png
new file mode 100644
index 00000000000..2e86923f0ca
Binary files /dev/null and b/test/image/baselines/box_notched-inverted-end.png differ
diff --git a/test/image/mocks/box_notched-inverted-end.json b/test/image/mocks/box_notched-inverted-end.json
new file mode 100644
index 00000000000..e8297b640c9
--- /dev/null
+++ b/test/image/mocks/box_notched-inverted-end.json
@@ -0,0 +1,36 @@
+{
+ "data": [
+ {
+ "x": [113.35, 29.54, 21.7, 113.35, 29.54, 21.7],
+ "name": "[113.35,29.54,21.7,113.35,29.54,21.7]",
+ "type": "box",
+ "notched": true
+ },
+ {
+ "x": [39.4, 88.63, 39.4, 88.63],
+ "name": "[39.4,88.63,39.4,88.63]",
+ "type": "box",
+ "notched": true
+ }
+ ],
+ "layout": {
+ "title": {
+ "text": "Samples where the confidence interval
median ± 1.57 / IQR * sqrt(N)
go beyond the fences",
+ "x": 0.02
+ },
+ "xaxis": {
+ "showline": true,
+ "mirror": true,
+ "zeroline": false
+ },
+ "yaxis": {
+ "showline": true,
+ "mirror": true,
+ "zeroline": false
+ },
+ "showlegend": false,
+ "margin": {"l": 220, "b": 20, "r": 20},
+ "width": 600,
+ "height": 300
+ }
+}