Chris
Chris

Reputation: 5834

How to filter data using DC, D3, and Crossfilter to produce a bar chart?

The following produces a bar chart that shows 4 people on the x axis and the number of times they show up on the y-axis.However I'd like to filter this data to only count the owner's if they have an ID of "A."

Also, would it be possible to apply this filter with a button or an onClick handler so that the data is only filtered for ID of "A" upon pressing the button.

See code below and jsfiddle here: http://jsfiddle.net/chrisguzman/y9xt2/

var data = [{
    Owner: "Alyssa",
    ID: "A"
}, {
    Owner: "Alyssa",
    ID: "A"
}, {
    Owner: "Alyssa",
    ID: "A"
}, {
    Owner: "Alyssa",
    ID: "A"
}, {
    Owner: "Alyssa",
    ID: "B"
}, {
    Owner: "Bob",
    ID: "A"
}, {
    Owner: "Bob",
    ID: "A"
}, {
    Owner: "Bob",
    ID: "C"
}, {
    Owner: "Bob",
    ID: "C"
}, {
    Owner: "Bob",
    ID: "C"
}, {
    Owner: "Bob",
    ID: "C"
}, {
    Owner: "Bob",
    ID: "C"
}, {
    Owner: "Bob",
    ID: "D"
}, {
    Owner: "Joe",
    ID: "A"
}, {
    Owner: "Joe",
    ID: "A"
}, {
    Owner: "Joe",
    ID: "D"
}, {
    Owner: "Joe",
    ID: "D"
}, {
    Owner: "Joe",
    ID: "E"
}];

var ndx = crossfilter(data);


var XDimension = ndx.dimension(function (d) {
    return d.Owner;
});
var YDimension = XDimension.group().reduceCount(function (d) {
    return d.Owner;
});
dc.barChart("#Chart")
    .width(480).height(300)
    .dimension(XDimension)
    .group(YDimension)
    .centerBar(true)
    .gap(56)
    .x(d3.scale.ordinal().domain(XDimension))
    .xUnits(dc.units.ordinal)
    .xAxisLabel("Market Developer")
    .yAxisLabel("Unique Counts")
    .elasticY(true)
    .xAxis().tickFormat(function (v) {
    return v;
});
dc.renderAll();

Upvotes: 1

Views: 3284

Answers (2)

Vito Mantese
Vito Mantese

Reputation: 127

I'm not sure if you still needed to know how to add this to a button. If so just create a button with the following anchor.

<a class="filter" href="javascript:FilterDimension.filter("A");dc.redrawAll();" style="display: none;">filter</a>

<a class="reset" href="javascript:FilterDimension.filterAll();dc.redrawAll();" style="display: none;">reset</a>

Upvotes: 0

Chris
Chris

Reputation: 5834

Simply create another dimension based on ndx and have it return the field that needs to be filtered. Then, before dc.renderAll(), apply filter() and the key to filter by.

See JS Fiddle here: http://jsfiddle.net/chrisguzman/eL2XG/

var ndx = crossfilter(data);


var XDimension = ndx.dimension(function (d) {
    return d.Owner;
});
var YDimension = XDimension.group().reduceCount(function (d) {
    return d.Owner;
});

Create that new dimension

var FilterDimension = ndx.dimension(function (d) {
    return d.ID;
});

//

dc.barChart("#Chart")
    .width(480).height(300)
    .dimension(XDimension)
    .group(YDimension)
    .centerBar(true)
    .gap(56)
    .x(d3.scale.ordinal().domain(XDimension))
    .xUnits(dc.units.ordinal)
    .xAxisLabel("Market Developer")
    .yAxisLabel("Unique Counts")
    .elasticY(true)
    .xAxis().tickFormat(function (v) {
    return v;
});

Then filter by that new dimension

FilterDimension.filter("A");
dc.renderAll();

Also, see https://groups.google.com/forum/#!msg/dc-js-user-group/UFxvUND7hmY/btbAjqIIzl8J for more in-depth explanation

The reason this is because

"a grouping intersects the crossfilter's current filters, except for the associated dimension's filter. Thus, group methods consider only records that satisfy every filter except this dimension's filter. So, if the crossfilter of payments is filtered by type and total, then group by total only observes the filter by type."

Upvotes: 1

Related Questions