Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
215 views
in Technique[技术] by (71.8m points)

javascript - Is there a way to tell crossfilter to treat elements of array as separate records instead of treating whole array as single key?

I have data set where some of the field values are arrays and I'd like to use crossfilter and d3.js or dc.js to display histogram of how many times each of those values was present in the dataset.

Here's an example:

var data = [
    {"key":"KEY-1","tags":["tag1", "tag2"]},
    {"key":"KEY-2","tags":["tag2"]},
    {"key":"KEY-3","tags":["tag3", "tag1"]}];

var cf = crossfilter(data);

var tags = cf.dimension(function(d){ return d.tags;});
var tagsGroup = tags.group();


dc.rowChart("#chart")
    .renderLabel(true)
    .dimension(tags)
    .group(tagsGroup)
    .xAxis().ticks(3);

dc.renderAll();

And JSFiddle http://jsfiddle.net/uhXf5/2/

When I run that code it produces graph like this:

graph1

But what I want is something like this:

enter image description here

To make things even more complicated it would be awesome to be able to click on any of the rows and filter dataset by the tag that was clicked.

Anyone has any ideas how to achieve that?

Thanks, Kostya

question from:https://stackoverflow.com/questions/17524627/is-there-a-way-to-tell-crossfilter-to-treat-elements-of-array-as-separate-record

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Solved it myself, here's fiddle with working code http://jsfiddle.net/uhXf5/6/

Here's code in case someone will came across similar problem:

function reduceAdd(p, v) {
  v.tags.forEach (function(val, idx) {
     p[val] = (p[val] || 0) + 1; //increment counts
  });
  return p;
}

function reduceRemove(p, v) {
  v.tags.forEach (function(val, idx) {
     p[val] = (p[val] || 0) - 1; //decrement counts
  });
  return p;

}

function reduceInitial() {
  return {};  
}


var data = [
    {"key":"KEY-1","tags":["tag1", "tag2"], "date":new Date("10/02/2012")},
    {"key":"KEY-2","tags":["tag2"], "date": new Date("10/05/2012")},
    {"key":"KEY-3","tags":["tag3", "tag1"], "date":new Date("10/08/2012")}];

var cf = crossfilter(data);

var tags = cf.dimension(function(d){ return d.tags;});
var tagsGroup = tags.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value();
// hack to make dc.js charts work
tagsGroup.all = function() {
  var newObject = [];
  for (var key in this) {
    if (this.hasOwnProperty(key) && key != "all") {
      newObject.push({
        key: key,
        value: this[key]
      });
    }
  }
  return newObject;
}


var dates = cf.dimension(function(d){ return d.date;});
var datesGroup = dates.group();


var chart = dc.rowChart("#chart");
    chart                                                                                       
    .renderLabel(true)
    .dimension(tags)
    .group(tagsGroup)
    .filterHandler(function(dimension, filter){     
        dimension.filter(function(d) {return chart.filter() != null ? d.indexOf(chart.filter()) >= 0 : true;}); // perform filtering
        return filter; // return the actual filter value
       })
    .xAxis().ticks(3);

var chart2 = dc.barChart("#chart2");
    chart2  
    .width(500)
    .transitionDuration(800)
    .margins({top: 10, right: 50, bottom: 30, left: 40})
    .dimension(dates)
    .group(datesGroup)
    .elasticY(true)
    .elasticX(true)
    .round(d3.time.day.round)    
    .x(d3.time.scale())    
    .xUnits(d3.time.days)
    .centerBar(true)
    .renderHorizontalGridLines(true)       
    .brushOn(true);    


dc.renderAll();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...