crossfilter.js,如何处理日期维度上的人为重复
crossfilter.js, how to deal with artificial duplicates on a date dimension
我正在做一个 rails 项目。数据结构如下所示。一个 session 可以有很多事件。
[{"id":102,"user_id":"user_2","date":"2015-10-08","count":2,"duration":0,"events":[{"event_type":"Event1","reference_id":"23","duration":2},{"event_type":"Event2","reference_id":"22","duration":3}]}
鉴于上述数据结构,我可以根据 session_date 等生成图表。但我确实需要根据嵌套事件数组中的数据生成饼图(例如 event_type 或 reference_id)。
现在我做了一些阅读,似乎 crossfilter 在平面数据结构上效果最好。所以我将结构展平,以便每个事件都有自己的行。
[{"id":102,"date":"2015-10-08","count":2,"duration":0,"event_type":"Event1","reference_id":"23","user_id":"user_1","event_duration":2},{"id":102,"date":"2015-10-08","count":2,"duration":0,"event_type":"Event2","reference_id":"22","user_id":"user_2","duration":3}]
我使用以前的事件 jsonarray 的数据不再有问题。
但是现在我遇到了以下问题,我需要一个条形图来显示每天 session 的数量。在上面的示例中,我将在 2015/10/8 有一个 Session 和两个事件。
我创建了这样的日期维度:
var dateDimension = ndx.dimension(function(d) {
return d.date;
});
过去常常这样分组:
var dateGroup = dateDimension.group();
我这样初始化图表:
visitorBarChart.width(800)
.height(250)
.dimension(dateDimension).group(dateGroup)
.x(d3.time.scale().domain([minDate,maxDate]))
.xAxisLabel("Date")
.yAxisLabel("Visitors");
但很明显,因为我的记录中有重复的日期,所以这不再有效。它几乎是按日期计算事件的数量。
我需要像 group(date,id).count 这样的东西。
我是 crossfilter 的新手,dc.js,希望我能准确描述问题。我在网上搜索了几个小时,但我想不通。
我想我必须用 reduceAdd/reduceRemove 做一些工作,但我想不出来
如有任何帮助,我们将不胜感激!
好吧,我自己可能已经找到了解决方案。我在我的组中使用以下函数调用 reduce。
function reduceInitial() {
return {
unique: d3.map(),
count: 0
};
}
function reduceAdd(p, v) {
var id = v.id;
var date = v.date;
//is there a date for the current id?
var check = p.unique.get(id);
// nopes add to count, add date to id
if(!check){
++p.count;
p.unique.set(id,date);
}else{
//mhhh that should not be neccessary
if(check != date){
++p.count;
p.unique.set(id,date);
}
}
//console.log(v)
//console.log("---")
//console.log(p)
return p;
}
function reduceRemove(p, v) {
var id = v.id;
var date = v.date;
var check = p.unique.get(id);
if(check){
if(check == date){
p.unique.remove(id);
--p.count;
}
}
return p;
}
我想我可以只使用数组而不是 d3.map,但目前看来还可以
您已经差不多明白了,但您还需要跟踪每个 ID 所见的每个日期的数量,并且只将您看到的第一个日期添加到计数中,如果有则从计数中删除不再是那个日期了。
我愿意 Reductio, as most of the reason I built it is to make these complex and computationally expensive aggregations easier to do right and efficiently. What you want to do is what I call exception aggregation。使用 Reductio 你会做:
var group = dateDimension.group();
var reducer = reductio()
.exception(function(d) { return d.id; })
.exceptionCount(true);
reducer(group);
祝你好运!
我正在做一个 rails 项目。数据结构如下所示。一个 session 可以有很多事件。
[{"id":102,"user_id":"user_2","date":"2015-10-08","count":2,"duration":0,"events":[{"event_type":"Event1","reference_id":"23","duration":2},{"event_type":"Event2","reference_id":"22","duration":3}]}
鉴于上述数据结构,我可以根据 session_date 等生成图表。但我确实需要根据嵌套事件数组中的数据生成饼图(例如 event_type 或 reference_id)。
现在我做了一些阅读,似乎 crossfilter 在平面数据结构上效果最好。所以我将结构展平,以便每个事件都有自己的行。
[{"id":102,"date":"2015-10-08","count":2,"duration":0,"event_type":"Event1","reference_id":"23","user_id":"user_1","event_duration":2},{"id":102,"date":"2015-10-08","count":2,"duration":0,"event_type":"Event2","reference_id":"22","user_id":"user_2","duration":3}]
我使用以前的事件 jsonarray 的数据不再有问题。 但是现在我遇到了以下问题,我需要一个条形图来显示每天 session 的数量。在上面的示例中,我将在 2015/10/8 有一个 Session 和两个事件。
我创建了这样的日期维度:
var dateDimension = ndx.dimension(function(d) {
return d.date;
});
过去常常这样分组:
var dateGroup = dateDimension.group();
我这样初始化图表:
visitorBarChart.width(800)
.height(250)
.dimension(dateDimension).group(dateGroup)
.x(d3.time.scale().domain([minDate,maxDate]))
.xAxisLabel("Date")
.yAxisLabel("Visitors");
但很明显,因为我的记录中有重复的日期,所以这不再有效。它几乎是按日期计算事件的数量。
我需要像 group(date,id).count 这样的东西。
我是 crossfilter 的新手,dc.js,希望我能准确描述问题。我在网上搜索了几个小时,但我想不通。
我想我必须用 reduceAdd/reduceRemove 做一些工作,但我想不出来
如有任何帮助,我们将不胜感激!
好吧,我自己可能已经找到了解决方案。我在我的组中使用以下函数调用 reduce。
function reduceInitial() {
return {
unique: d3.map(),
count: 0
};
}
function reduceAdd(p, v) {
var id = v.id;
var date = v.date;
//is there a date for the current id?
var check = p.unique.get(id);
// nopes add to count, add date to id
if(!check){
++p.count;
p.unique.set(id,date);
}else{
//mhhh that should not be neccessary
if(check != date){
++p.count;
p.unique.set(id,date);
}
}
//console.log(v)
//console.log("---")
//console.log(p)
return p;
}
function reduceRemove(p, v) {
var id = v.id;
var date = v.date;
var check = p.unique.get(id);
if(check){
if(check == date){
p.unique.remove(id);
--p.count;
}
}
return p;
}
我想我可以只使用数组而不是 d3.map,但目前看来还可以
您已经差不多明白了,但您还需要跟踪每个 ID 所见的每个日期的数量,并且只将您看到的第一个日期添加到计数中,如果有则从计数中删除不再是那个日期了。
我愿意 Reductio, as most of the reason I built it is to make these complex and computationally expensive aggregations easier to do right and efficiently. What you want to do is what I call exception aggregation。使用 Reductio 你会做:
var group = dateDimension.group();
var reducer = reductio()
.exception(function(d) { return d.id; })
.exceptionCount(true);
reducer(group);
祝你好运!