I'm having a bit of trouble understand selections and filtering in d3. Let's say I have a simple array:
data = [1, 2, 6, 3, 4]
I want to draw circles if the value < 5 and squares if it's >= 5. My code right now only draws circles and looks like this:
var svg = d3.select("body").append("svg")
svg.selectAll("shapes")
    .data(data)
    .enter()
    .append("circle")
and other attributes for circles. I need to use the .filter() method, but I don't know where to put it. I tried doing something like:
var svg = d3.select("body").append("svg")
svg.selectAll("shapes")
    .data(data)
    .enter()
    .filter(function(d){if (d>5){console.log('working');})
    .append("circle")
but then I get an error with the append method. Can someone point me in the right direction on how I'd accomplish this?
The problem is that after you .enter() you are returning a nested array, hence your error:
Uncaught TypeError: Object [object Array] has no method 'append'
To use .filter(), you need to apply it after the .append():
var data = d3.range(10);
var svg = d3.select("body").append("svg");
var shapes = svg.selectAll(".shapes")
    .data(data).enter();
shapes.append("circle")
    .filter(function(d){ return d < 5; })
    .attr("cx", function(d, i){ return (i+1) * 25; })
    .attr("cy", 10)
    .attr("r", 10);
shapes.append("rect")
    .filter(function(d){ return d >= 5; })
    .attr("x", function(d, i){ return (i+1) * 25; })
    .attr("y", 25)
    .attr("width", 10)
    .attr("height", 10);
Using the code above (also in this fiddle), I get the following output:

Note that you can also achieve the same effect using Array's filter method, e.g.
var shapes = svg.selectAll(".shapes")
    .data(data.filter(function(d){ return d < 5; })).enter()
    .append("circle")
    .attr("cx", function(d, i){ return (i+1) * 25; })
    .attr("cy", 10)
    .attr("r", 10);
It is also possible use the data to conditionally create circles or rectangles by providing a function argument to the append function
    .append(function(d, i){
        if (something to do with d) {
            ... return an SVG circle element
        } else {
            ... return an SVG rectangle element
        }
    })
e.g. like this
var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var svg = d3.select("body").append("svg");
function createSvgEl(name) {
    return document.createElementNS('http://www.w3.org/2000/svg', name);
}
svg
    .selectAll(".shapes")
    .data(data)
    .enter()
    .append(function(d, i){
        if (d <= 4) {
            return createSvgEl("circle");
        } else {
            return createSvgEl("rect");
        }
    });
svg.selectAll("circle")
        .attr("cx", function(d, i){ return (i+1) * 25; })
        .attr("cy", 10)
        .attr("r", 10);
svg.selectAll("rect")
        .attr("x", function(d, i){ return (i+1) * 25; })
        .attr("y", 25)
        .attr("width", 10)
        .attr("height", 10);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With