【问题标题】:crossfilter.js, how to deal with artificial duplicates on a date dimensioncrossfilter.js,如何处理日期维度上的人为重复
【发布时间】:2015-10-09 16:17:10
【问题描述】:

我正在做一个 Rails 项目。数据结构如下所示。一个会话可以有很多事件。

[{"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)。

现在我做了一些阅读,似乎交叉过滤器在平面数据结构上效果最好。所以我将结构展平,以便每个事件都有自己的行。

[{"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 的数据时不再有问题。 但是现在我遇到了以下问题,我需要一个显示每天会话数的条形图。在上面的示例中,我将在 2015/10/8 举行一个包含两个事件的会话。

我这样创建日期维度:

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,但现在似乎可以工作

【问题讨论】:

    标签: javascript dc.js crossfilter


    【解决方案1】:

    您已经知道了,但您还需要跟踪您为每个 ID 看到的每个日期的数量,并且只添加您看到的第一个日期的计数,如果没有则从计数中删除更多的那个日期。

    我会支持Reductio,因为我构建它的大部分原因是为了让这些复杂且计算成本高昂的聚合更容易正确和高效地完成。你想做的就是我所说的exception aggregation。使用 Reductio,您可以:

    var group = dateDimension.group();
    var reducer = reductio()
        .exception(function(d) { return d.id; })
        .exceptionCount(true);
    
    reducer(group);
    

    祝你好运!

    【讨论】:

    • 嗨,伊桑。感谢您的答复!还原看起来真的很不错。但我不太确定如何使用它。如果我尝试您的代码,我会得到以下异常:Uncaught TypeError: Cannot read property 'bisect' of undefined(anonymous function) @ reductio.js?body=1:1087
    • 这很有趣。你所有的记录都有id吗?如果没有,您需要确保它们至少都已定义。如果你想整理一个例子,我很乐意看看。
    • 我的错误.. 我在 crossfilter 和 dc 之前包含了 reductio。现在就像一个魅力。我什至修复了一个饼图,它在一分钟内就出现了类似的问题 :)
    猜你喜欢
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    相关资源
    最近更新 更多