Skip to content

Commit 36cc37d

Browse files
committed
replace Scott's rule fallback with \propto (max - min)
- to avoid "sharp" transitions from Silverman to Scott value - make custom bandwidth value use that same fallback when "too small" - rename "scott-rule" mock to "bandwidth-edge-cases"
1 parent 0661af3 commit 36cc37d

File tree

4 files changed

+247
-15
lines changed

4 files changed

+247
-15
lines changed

src/traces/violin/calc.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ module.exports = function calc(gd, trace) {
7171
return cd;
7272
};
7373

74-
// Default to Silveman's rule of thumb, but if 'too small' use Scott's rule
74+
// Default to Silveman's rule of thumb
7575
// - https://stats.stackexchange.com/a/6671
7676
// - https://en.wikipedia.org/wiki/Kernel_density_estimation#A_rule-of-thumb_bandwidth_estimator
7777
// - https://github.com/statsmodels/statsmodels/blob/master/statsmodels/nonparametric/bandwidths.py
@@ -80,21 +80,27 @@ function silvermanRule(len, ssd, iqr) {
8080
return 1.059 * a * Math.pow(len, -0.2);
8181
}
8282

83-
function scottRule(len, ssd) {
84-
return ssd * Math.pow(len, -0.2);
85-
}
86-
8783
function calcBandwidth(trace, cdi, vals) {
88-
if(trace.bandwidth) return trace.bandwidth;
89-
90-
var len = vals.length;
91-
var ssd = Lib.stdev(vals, len - 1, cdi.mean);
92-
var bw = silvermanRule(len, ssd, cdi.q3 - cdi.q1);
84+
var bw;
9385

94-
if((cdi.max - cdi.min) / bw > 1e5) {
95-
bw = scottRule(len, ssd);
86+
if(trace.bandwidth) {
87+
bw = trace.bandwidth;
88+
} else {
89+
var len = vals.length;
90+
var ssd = Lib.stdev(vals, len - 1, cdi.mean);
91+
bw = silvermanRule(len, ssd, cdi.q3 - cdi.q1);
9692
}
97-
return bw;
93+
94+
// Limit how small the bandwidth can be.
95+
//
96+
// Silverman's rule of thumb can be "very" small
97+
// when IQR does a poor job at describing the spread
98+
// of the distribution.
99+
// We also want to limit custom bandwidths
100+
// to not blow up kde computations.
101+
return ((cdi.max - cdi.min) / bw) < 1e5 ?
102+
bw :
103+
(cdi.max - cdi.min) / 100;
98104
}
99105

100106
function calcSpan(trace, cdi, valAxis, bandwidth) {
Loading
-19.9 KB
Binary file not shown.

test/image/mocks/violin_scott-rule.json renamed to test/image/mocks/violin_bandwidth-edge-cases.json

Lines changed: 228 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"data": [
33
{
4-
"name": "with scott rule bandwidth",
4+
"name": "silverman value is too small",
55
"type": "violin",
66
"points": false,
77
"y": [
@@ -227,7 +227,233 @@
227227
},
228228
{
229229
"bandwidth": 0.03364359551927969,
230-
"name": "with custom bandwidth",
230+
"name": "OK custom bandwidth",
231+
"type": "violin",
232+
"points": false,
233+
"y": [
234+
2.4403208885500003e-7,
235+
6.624100740240001e-8,
236+
8.164963286729999e-8,
237+
0.00000550607937631,
238+
3.02033017347e-8,
239+
3.7801716937800004e-7,
240+
5.56297659998e-8,
241+
5.406555702509999e-8,
242+
3.31213740697e-8,
243+
1.0835987313399999e-7,
244+
3.19669534548e-7,
245+
2.8017014902900004e-8,
246+
2.4514782933900002e-8,
247+
5.95554346643e-7,
248+
4.70654584492e-8,
249+
2.3361313822699997e-11,
250+
3.06469187871e-7,
251+
2.07771831308e-8,
252+
5.04663715295e-8,
253+
5.67592023418e-8,
254+
6.719484075659999e-8,
255+
2.3359219312100003e-9,
256+
7.32680903665e-8,
257+
1.56153538012e-7,
258+
5.92551838794e-8,
259+
6.48377885533e-8,
260+
6.5098659424e-8,
261+
1.92267340995e-7,
262+
6.27042106128e-10,
263+
3.79763712636e-8,
264+
5.79353363587e-8,
265+
2.01568499962e-7,
266+
4.5710354583899996e-8,
267+
8.68326386359e-8,
268+
2.00314121449e-7,
269+
4.16735959037e-11,
270+
1.05264632654e-7,
271+
1.3219377534799998e-8,
272+
1.1323983991099999e-7,
273+
7.9066491519e-9,
274+
3.29907596399e-7,
275+
3.58952178646e-7,
276+
3.06223788373e-8,
277+
1.34570962274e-7,
278+
1.95650463375e-7,
279+
8.88142553786e-8,
280+
6.33259714546e-7,
281+
7.89150230354e-8,
282+
3.44378121049e-8,
283+
3.56491902649e-8,
284+
7.17020398538e-8,
285+
0.00000117543109624,
286+
1.31723026752e-7,
287+
6.15562220021e-7,
288+
1.0411983170000001e-8,
289+
6.35306917979e-8,
290+
1.4244199622e-7,
291+
5.50507070561e-8,
292+
4.11937918362e-7,
293+
1.1436582759e-7,
294+
9.00381861905e-8,
295+
3.5761650960999997e-7,
296+
5.406555702509999e-8,
297+
1.91340425062e-8,
298+
4.05244277276e-8,
299+
1.67071698044e-8,
300+
2.64702379432e-7,
301+
4.54083719121e-8,
302+
1.15367276299e-8,
303+
7.01160189225e-8,
304+
2.12020626256e-7,
305+
7.55952714792e-8,
306+
3.35252445825e-8,
307+
6.410902643609999e-8,
308+
7.822972433139998e-8,
309+
3.00394443348e-8,
310+
1.85872035552e-7,
311+
3.21694096675e-8,
312+
1.9166603712099998e-8,
313+
1.4382528776500002e-7,
314+
2.30600946296e-7,
315+
1.1977210552999998e-7,
316+
3.21694096675e-8,
317+
3.1720115986e-7,
318+
5.00989110573e-12,
319+
2.14001834758e-9,
320+
3.57324647064e-7,
321+
9.836368168600001e-8,
322+
1.3317117896700002e-8,
323+
6.624100740240001e-8,
324+
3.0650079256e-8,
325+
3.23881793333e-8,
326+
0.0000010477687171799999,
327+
2.47766478953e-8,
328+
4.00638166198e-7,
329+
3.7385796368e-8,
330+
0.00000110210670495,
331+
5.16171069606e-9,
332+
5.5306060294599996e-8,
333+
7.43346458468e-8,
334+
2.98025726842e-8,
335+
4.50223643894e-8,
336+
2.6869636474599998e-11,
337+
2.23102995275e-7,
338+
6.624100740240001e-8,
339+
8.837339991869999e-8,
340+
1.0959679528299999e-7,
341+
7.70759415991e-8,
342+
9.19332979062e-8,
343+
5.72570744297e-9,
344+
5.67957997273e-12,
345+
7.200621520489999e-8,
346+
8.75570719476e-8,
347+
1.38879577383e-7,
348+
5.8323354775900006e-8,
349+
8.46519385822e-8,
350+
0.0000010404658225700002,
351+
2.7344550343299998e-8,
352+
1.1561451197599999e-7,
353+
3.37647982763e-7,
354+
1.03142857372e-7,
355+
3.0261981891400004e-8,
356+
1.0770523872e-7,
357+
5.56297659998e-8,
358+
4.45345220689e-7,
359+
5.190799176779999e-7,
360+
1.1878461076600001e-7,
361+
6.37944980645e-8,
362+
1.028044903e-7,
363+
2.35063847817e-8,
364+
3.35252445825e-8,
365+
1.75860650771e-7,
366+
5.95322200005e-8,
367+
2.3051930735100003e-7,
368+
1.01713704525e-7,
369+
6.36298925611e-8,
370+
8.32962182234e-9,
371+
1.73171410467e-7,
372+
5.92070463445e-8,
373+
1.35192178624e-7,
374+
1.80208181383e-7,
375+
2.32965100186e-7,
376+
5.558425986229999e-7,
377+
1.64668938007e-7,
378+
6.01836809013e-8,
379+
1.9915955477200002e-16,
380+
9.96792751761e-9,
381+
1.63404871286e-9,
382+
2.64702379432e-7,
383+
7.55162232084e-8,
384+
5.49833977189e-8,
385+
3.4953095347400004e-8,
386+
2.21025674493e-8,
387+
1.01029071417e-7,
388+
2.30733613826e-7,
389+
8.50266378712e-8,
390+
3.492997660290001e-8,
391+
1.72122175426e-7,
392+
6.06902637292e-8,
393+
2.0951701376400003e-8,
394+
5.13108366946e-7,
395+
2.80764979683e-7,
396+
7.49786710527e-7,
397+
1.28767098858e-7,
398+
0.00000130482668731,
399+
2.94524334014e-8,
400+
1.0383202068400001e-7,
401+
1.06529852732e-7,
402+
3.06223788373e-8,
403+
6.666061263539999e-8,
404+
2.77669768835e-7,
405+
1.9614212065399998e-7,
406+
7.57552863852e-9,
407+
1.3646260448700003e-8,
408+
1.55911616248e-8,
409+
4.2985875019e-8,
410+
5.35662859053e-7,
411+
1.31723026752e-7,
412+
2.8589493252999997e-8,
413+
6.15562220021e-7,
414+
2.48257838284e-8,
415+
5.54992004418e-8,
416+
1.59590984401e-7,
417+
1.05027747717e-7,
418+
4.16404749061e-15,
419+
3.21694096675e-8,
420+
1.55235536247e-8,
421+
7.22158660254e-8,
422+
7.3548078204e-11,
423+
5.12189467799e-8,
424+
5.78423562453e-7,
425+
7.34977455259e-8,
426+
8.428837152339999e-8,
427+
5.41683911418e-8,
428+
2.0892157394300002e-7,
429+
8.45875572871e-8,
430+
3.19669534548e-7,
431+
2.4721993929599997e-8,
432+
1.97866536768e-7,
433+
3.1078269037e-8,
434+
4.7958877370199995e-8,
435+
1.63190113114e-8,
436+
1.55306103512e-7,
437+
6.20692035531e-7,
438+
3.82587877803e-7,
439+
3.3292850458999995e-12,
440+
6.62976422611e-11,
441+
0.363112695543,
442+
1.2438406655e-7,
443+
1.57716890468e-7,
444+
8.270934005960001e-8,
445+
7.7356150975e-8,
446+
4.17240969082e-7,
447+
1.5340551258000003e-8,
448+
7.2558862077e-7,
449+
8.628154354439999e-8,
450+
0.00000130967390314,
451+
5.63969380635e-8
452+
]
453+
},
454+
{
455+
"bandwidth": 1e-8,
456+
"name": "custom bandwidth is too small",
231457
"type": "violin",
232458
"points": false,
233459
"y": [

0 commit comments

Comments
 (0)