Kos*_*nko 38 javascript d3.js crossfilter dc.js
我有一些数据集,其中一些字段值是数组,我想使用crossfilter和d3.js或dc.js来显示数据集中每个值存在多少次的直方图.
这是一个例子:
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();
Run Code Online (Sandbox Code Playgroud)
和JSFiddle http://jsfiddle.net/uhXf5/2/
当我运行该代码时,它生成如下图形:

但我想要的是这样的:

为了使事情变得更加复杂,能够通过单击的标记单击任何行和过滤数据集将是非常棒的.
任何人有任何想法如何实现这一点?
谢谢,克斯特亚
Kos*_*nko 33
自己解决了,这里是工作代码的小提琴http://jsfiddle.net/uhXf5/6/
这是代码,万一有人会遇到类似的问题:
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();
Run Code Online (Sandbox Code Playgroud)
Jef*_*etz 20
上面的例子是一个很好的方法.你可以更进一步.在上面的解决方案中,它只会根据您的第一个选择进行过滤.任何后续选择都将被忽略.
如果您希望它响应所有选择,您将创建一个filterHandler,如下所示:
barChart.filterHandler (function (dimension, filters) {
dimension.filter(null);
if (filters.length === 0)
dimension.filter(null);
else
dimension.filterFunction(function (d) {
for (var i=0; i < d.length; i++) {
if (filters.indexOf(d[i]) >= 0) return true;
}
return false;
});
return filters;
}
);
Run Code Online (Sandbox Code Playgroud)
这里的工作示例:http: //jsfiddle.net/jeffsteinmetz/cwShL/
DJ *_*tin 15
我想尝试为Jeff和Kostya列出的方法提供一些背景信息.
你会注意到tagsGroup使用groupAll与典型的group方法不同.Crossfilter告诉我们"返回的对象类似于标准分组,除了它没有top或order方法.而是使用value来检索所有匹配记录的reduce值." Kostya调用".value()"方法来检索代表整个组的单个对象.
var tagsGroup = tags.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value();
Run Code Online (Sandbox Code Playgroud)
此对象不适用于dc.js,因为dc.js期望组对象具有all方法.Kostya修补了该对象,使其具有"全部"方法,如下所示:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
这将适用于简单的dc.js图表,但您将无法使用所有dc.js功能,因为并非所有组功能都存在.例如,您将无法在图表上使用"上限"方法,因为cap方法期望组对象具有"顶部"方法.你也可以像这样修补top方法:
topicsGroup.top = function(count) {
var newObject = this.all();
newObject.sort(function(a, b){return b.value - a.value});
return newObject.slice(0, count);
};
Run Code Online (Sandbox Code Playgroud)
这将使您的图表使用上限方法:
barChart
.renderLabel(true)
.height(200)
.dimension(topicsDim)
.group(topicsGroup)
.cap(2)
.ordering(function(d){return -d.value;})
.xAxis().ticks(3);
Run Code Online (Sandbox Code Playgroud)
更新的示例可从http://jsfiddle.net/djmartin_umich/m7V89/#base获得
Jeff的答案确实有效,但是如果找到了一个项目,则无需跟踪"找到"变量或继续循环.如果X在[X,Y,Z]中,这已经减少了1/3的迭代量.
else
dimension.filterFunction(function (d) {
for (var i=0; i < d.length; i++) {
if (filters.indexOf(d[i]) >= 0) return true;
}
return false;
});
Run Code Online (Sandbox Code Playgroud)
或者,你可以修补dc.js filterFunction方法,这将处理所有情况.
| 归档时间: |
|
| 查看次数: |
10078 次 |
| 最近记录: |