Skip to content

Commit caade64

Browse files
authored
Merge pull request #1519 from plotly/bar-non-numeric-bug
Bar with non-numeric (x,y) items bug fix
2 parents c835242 + 6f0a95d commit caade64

File tree

5 files changed

+51
-43
lines changed

5 files changed

+51
-43
lines changed

src/traces/bar/calc.js

+3-17
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,11 @@ module.exports = function calc(gd, trace) {
4949

5050
// create the "calculated data" to plot
5151
var serieslen = Math.min(pos.length, size.length),
52-
cd = [];
52+
cd = new Array(serieslen);
5353

54-
// set position
54+
// set position and size
5555
for(i = 0; i < serieslen; i++) {
56-
57-
// add bars with non-numeric sizes to calcdata
58-
// so that ensure that traces with gaps are
59-
// plotted in the correct order
60-
61-
if(isNumeric(pos[i])) {
62-
cd.push({p: pos[i]});
63-
}
56+
cd[i] = { p: pos[i], s: size[i] };
6457
}
6558

6659
// set base
@@ -84,13 +77,6 @@ module.exports = function calc(gd, trace) {
8477
}
8578
}
8679

87-
// set size
88-
for(i = 0; i < cd.length; i++) {
89-
if(isNumeric(size[i])) {
90-
cd[i].s = size[i];
91-
}
92-
}
93-
9480
// auto-z and autocolorscale if applicable
9581
if(hasColorscale(trace, 'marker')) {
9682
colorscaleCalc(trace, trace.marker.color, 'marker', 'c');

src/traces/bar/set_positions.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'use strict';
1111

1212
var isNumeric = require('fast-isnumeric');
13+
var BADNUM = require('../../constants/numerical').BADNUM;
1314

1415
var Registry = require('../../registry');
1516
var Axes = require('../../plots/cartesian/axes');
@@ -37,8 +38,7 @@ module.exports = function setPositions(gd, plotinfo) {
3738
fullTrace.visible === true &&
3839
Registry.traceIs(fullTrace, 'bar') &&
3940
fullTrace.xaxis === xa._id &&
40-
fullTrace.yaxis === ya._id &&
41-
!calcTraces[i][0].placeholder
41+
fullTrace.yaxis === ya._id
4242
) {
4343
if(fullTrace.orientation === 'h') {
4444
calcTracesHorizontal.push(calcTraces[i]);
@@ -188,7 +188,7 @@ function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces) {
188188
for(var j = 0; j < calcTrace.length; j++) {
189189
var bar = calcTrace[j];
190190

191-
if(!isNumeric(bar.s)) continue;
191+
if(bar.s === BADNUM) continue;
192192

193193
var isOutmostBar = ((bar.b + bar.s) === sieve.get(bar.p, bar.s));
194194
if(isOutmostBar) bar._outmost = true;
@@ -395,6 +395,8 @@ function setBarCenter(gd, pa, sieve) {
395395
calcBar[pLetter] = calcBar.p +
396396
((poffsetIsArray) ? poffset[j] : poffset) +
397397
((barwidthIsArray) ? barwidth[j] : barwidth) / 2;
398+
399+
398400
}
399401
}
400402
}
@@ -502,7 +504,7 @@ function stackBars(gd, sa, sieve) {
502504
for(j = 0; j < trace.length; j++) {
503505
bar = trace[j];
504506

505-
if(!isNumeric(bar.s)) continue;
507+
if(bar.s === BADNUM) continue;
506508

507509
// stack current bar and get previous sum
508510
var barBase = sieve.put(bar.p, bar.b + bar.s),
@@ -533,7 +535,7 @@ function sieveBars(gd, sa, sieve) {
533535
for(var j = 0; j < trace.length; j++) {
534536
var bar = trace[j];
535537

536-
if(isNumeric(bar.s)) sieve.put(bar.p, bar.b + bar.s);
538+
if(bar.s !== BADNUM) sieve.put(bar.p, bar.b + bar.s);
537539
}
538540
}
539541
}
@@ -569,7 +571,7 @@ function normalizeBars(gd, sa, sieve) {
569571
for(var j = 0; j < trace.length; j++) {
570572
var bar = trace[j];
571573

572-
if(!isNumeric(bar.s)) continue;
574+
if(bar.s === BADNUM) continue;
573575

574576
var scale = Math.abs(sTop / sieve.get(bar.p, bar.s));
575577
bar.b *= scale;

src/traces/bar/sieve.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
module.exports = Sieve;
1212

1313
var Lib = require('../../lib');
14+
var BADNUM = require('../../constants/numerical').BADNUM;
1415

1516
/**
1617
* Helper class to sieve data from traces into bins
@@ -34,7 +35,7 @@ function Sieve(traces, separateNegativeValues, dontMergeOverlappingData) {
3435
var trace = traces[i];
3536
for(var j = 0; j < trace.length; j++) {
3637
var bar = trace[j];
37-
positions.push(bar.p);
38+
if(bar.p !== BADNUM) positions.push(bar.p);
3839
}
3940
}
4041
this.positions = positions;

test/jasmine/assets/custom_matchers.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ function isClose(actual, expected, precision) {
143143
return Math.abs(actual - expected) < precision;
144144
}
145145

146-
return actual === expected;
146+
return (
147+
actual === expected ||
148+
(isNaN(actual) && isNaN(expected))
149+
);
147150
}
148151

149152
function coercePosition(precision) {

test/jasmine/tests/bar_test.js

+34-18
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,39 @@ describe('Bar.calc', function() {
283283
var cd = gd.calcdata;
284284
assertPointField(cd, 'b', [[0, 1, 2], [0, 1, 0], [0, 0]]);
285285
});
286+
287+
it('should not exclude items with non-numeric x/y from calcdata', function() {
288+
var gd = mockBarPlot([{
289+
x: [5, NaN, 15, 20, null, 21],
290+
y: [20, NaN, 23, 25, null, 26]
291+
}]);
292+
293+
var cd = gd.calcdata;
294+
assertPointField(cd, 'x', [[5, NaN, 15, 20, NaN, 21]]);
295+
assertPointField(cd, 'y', [[20, NaN, 23, 25, NaN, 26]]);
296+
});
297+
298+
it('should not exclude items with non-numeric y from calcdata (to plots gaps correctly)', function() {
299+
var gd = mockBarPlot([{
300+
x: ['a', 'b', 'c', 'd'],
301+
y: [1, null, 'nonsense', 15]
302+
}]);
303+
304+
var cd = gd.calcdata;
305+
assertPointField(cd, 'x', [[0, 1, 2, 3]]);
306+
assertPointField(cd, 'y', [[1, NaN, NaN, 15]]);
307+
});
308+
309+
it('should not exclude items with non-numeric x from calcdata (to plots gaps correctly)', function() {
310+
var gd = mockBarPlot([{
311+
x: [1, null, 'nonsense', 15],
312+
y: [1, 2, 10, 30]
313+
}]);
314+
315+
var cd = gd.calcdata;
316+
assertPointField(cd, 'x', [[1, NaN, NaN, 15]]);
317+
assertPointField(cd, 'y', [[1, 2, 10, 30]]);
318+
});
286319
});
287320

288321
describe('Bar.setPositions', function() {
@@ -681,23 +714,6 @@ describe('Bar.setPositions', function() {
681714
expect(Axes.getAutoRange(ya)).toBeCloseToArray([-1.11, 1.11], undefined, '(ya.range)');
682715
});
683716

684-
it('should skip placeholder trace in position computations', function() {
685-
var gd = mockBarPlot([{
686-
x: [1, 2, 3],
687-
y: [2, 1, 2]
688-
}, {
689-
x: [null],
690-
y: [null]
691-
}]);
692-
693-
expect(gd.calcdata[0][0].t.barwidth).toEqual(0.8);
694-
695-
expect(gd.calcdata[1][0].x).toBe(false);
696-
expect(gd.calcdata[1][0].y).toBe(false);
697-
expect(gd.calcdata[1][0].placeholder).toBe(true);
698-
expect(gd.calcdata[1][0].t.barwidth).toBeUndefined();
699-
});
700-
701717
it('works with log axes (grouped bars)', function() {
702718
var gd = mockBarPlot([
703719
{y: [1, 10, 1e10, -1]},
@@ -1285,7 +1301,7 @@ function mockBarPlot(dataWithoutTraceType, layout) {
12851301

12861302
var gd = {
12871303
data: dataWithTraceType,
1288-
layout: layout,
1304+
layout: layout || {},
12891305
calcdata: []
12901306
};
12911307

0 commit comments

Comments
 (0)