AmericanCities
AmericanCities

Reputation: 139

d3 NaN when using javascript Filter (data.filter) on stacked Bar Chart

I have a stacked bar chart in d3. Each stack is made up of 4 svg rectangles. I would like to create a text box above each stack in the chart with a stack total.

The last rectangle in the stack data[i][3] contains elements x, y and y0. i represents stacks 0 through 3.

Here's a console output for :

            .data(data.filter(function(d,i){
                     console.log("This is i: " + i);
                     console.dir(d[3]);
                     return d[3];
            }))

This is i: 0 x: 0 y: 0.46 y0: 2.4

The idea is that I will be able to create a dataset for just the last rectangle of each stack and then find the y position for the text box by adding y and y0 for that rectangle.

I am able to do this using the d3 .filter(":last-child") option, but it creates empty rect elements which I do not want. When I try a javaScript filter I get a NaN result for d.x and d.y values. Any advice?

            stack.selectAll('.stackTotalBox')
            .data(data.filter(function(d,i){
                     console.log("This is i: " + i);
                     console.dir(d[3]);
                     return d[3];
            }))
            .enter()
            .append("rect")
           // .filter(":last-child")  -- this works but generates empty rect 
            .attr("class","stackTotalBox")
            .attr("x", function (d) {
                console.dir(d);
                return xScale(d.x) + 170/2 - 39.12;  // + width of stack/2 - width of text box/2
            })
            .attr("y", function (d) {
                    return yScale(d.y0 + d.y) - 40; // height of stack + room for text box
            })
            .attr("width", 78.24)      // width of text box
            .attr("height", 19.347)    // height of text box
            .attr("rx", 8)             // rounded corners
            .attr("ry", 8)             // rounded corners
            .attr("fill", "#BBBDBF");

Update with data structure of data

Data contains 4 arrays (one array per stack), each array has 4 objects(rectangles), Each object contains coordinates for a rectangle.

This is how it looks in console with the first stack/array expanded:

Array[4]
--> 0: Array[4] (This represents a Stacked bar)
----> 0: Object
----> 1: Object
----> 2: Object
----> 3: Object (This Represents the last rectangle in the stacked bar)
--------> x: 0 (First Array has x = 0, 2nd Array x = 1)
--------> y: 0.4 (height of rectangle)
--------> y0: 2.13 (height of preceding rectangles, starting Y coordinates)

--> 1: Array[4]
--> 2: Array[4]
--> 3: Array[4]

Upvotes: 0

Views: 417

Answers (1)

Natural Lam
Natural Lam

Reputation: 742

I see. You should use Array.prototype.map instead of Array.prototype.filter. if you use filter then your output will be included whenever closure return true. So in your case, since d[3] is an object and it's always true, you basically didn't filter anything and thus d is still a 2-d array, and d.x is undefined.

Try this to filter your data:

stack.selectAll('.stackTotalBox')
    .data(data.map(function(item){            
        return item[3];
    }))

Upvotes: 1

Related Questions