Reputation: 311
I try to use crossfilter
to filter my data at the same time on both a dimension and a group.
Say, I want to be able to filterExact
on my "byCylinders" dimension, and at the same time filter on the value of my groupByBrand
group (which reduce-counts cars by brand name).
(both checkboxes checked).
See code: http://jsbin.com/xajuc/2/watch?js,output
The problem I see is that I don't get both filters recognized at once, or I don't understand how to bind d3.data()
correctly.
I understand that I could create a new "ad-hoc" dimension, but as dimensions are expensive, this might not be the best way to do it..
Any ideas?
Upvotes: 1
Views: 2107
Reputation: 20120
The problem isn't with your use of crossfilter, but your d3 display. Since you aren't using crossfilter for your brand filtering, it should be okay to use that dimension for fetching results (it wouldn't observe any dimension.filter
on that same dimension, however).
The problem is that you don't have an update step for the bins that changed but were not removed. Crossfilter does not automatically remove bins with 0 items, so the actual number of bins won't change in response to your byCylinders.filter
, only the size. Thus there are no enters or exits when just clicking the cylinders checkbox - only the other filter actually removes bins.
So by adding an update step after the insert, you can see the numbers change:
var result = d3.select("body")
.select("div#result")
.selectAll("div")
.data(resultData);
result.enter()
.append("div");
result
.text(function(d){
return d.key + " : " + d.value + " cars found";});
This takes advantage of the fact that the items in .enter()
become available for updates immediately after they are processed.
http://jsbin.com/qesafu/2/edit
Upvotes: 1
Reputation: 374
You can bring in your data as .json, zip the various data elements, and pass .data() the entire data set. I think the following could apply to your filters as well. I will explain this like you are bringing in your data (not necessarily filtered) as a whole. Hopefully this will shine light on how .data() can be utilized with associated data in d3.
data.json example:
{
"property1":[0, 0, 0, 0],
"property2":['name1', 'name2', 'name3', 'name4']
}
Bring in the data as .json:
d3.json("data.json", function(data) {
// zip the two (or more) attributes of your data
data = d3.zip(data.property1, data.property2).map(function(d) {
property1 = +d[0];
property2 = +d[1];
// return object for each property
return {prop1: property1, prop2: property2};
});
}
And then .data() can get that zip:
.data(data)
You can call just one of the data properties at a time:
// histogram example
d3.layout.histogram()
.bins()
.value( function(d) { return d.attr1; })
(data)
Do you see how .value
returns just one the properties of the zip? But the other property is still associated. You could have multiple properties, use a few for whatever computations you may be doing, and then use the others as metadata FOR those data properties because they are all zipped together in a nice little bundle for you.
Another option is passing in one array / data to .data() and using the index for the other.
Both options outlined here:
d3 array input line graph example
With a detailed example of the former here:
http://bl.ocks.org/patrickberkeley/9162034
I think these concepts are what you are after. Let me know if I am wrong.
Upvotes: 0