如何进行复杂的crossfilter减少

时间:2015-12-28 09:04:16

标签: d3.js dc.js crossfilter

我正在尝试使用自定义缩减(reduceAdd,reduceRemove等)创建一个用于放入dc.js的变量,并且无法弄清楚如何编写它。

我在这些reduce函数之外编写了函数,现在必须复制相同的reduce函数内部,以便对绘制的图形使用相同的函数。为外部reduce函数编写的逻辑和代码如下

逻辑:对于每个唯一的contact_week available(日期),找到weeknumber的最大值,然后总结TOTCOUNT变量和DECAY_CNT变量并计算百分比(DECAY_CNT / TOTCOUNT)。

以下是不使用crossfilter的原始代码:

 //Decay % logic   
  var dates = d3.map(filter1,function(d) { return d.CONTACT_WEEK;}).keys() ;
  console.log(dates);
  var sum1,sum2 = 0;


  for(var i=0; i<dates.length; i++)
    {
      data1 = filter1.filter(function(d) { return d.CONTACT_WEEK == dates[i] ;});
      //console.log(data1);
      var max = d3.max(data1, function(d) { return +d.WEEK_NUMBER ;});
      //console.log(max);
      data2 = data1.filter(function(d) { return d.WEEK_NUMBER == max ;});

      var sum1 = d3.sum(data2, function(d) { return d.TOTCOUNT ;});
      var sum2 = d3.sum(data2, function(d) { return d.DECAY_CNT ;});
      console.log(sum1);
      var decay = sum2/sum1 * 100 ;
      console.log(decay); 

    } 

这样做的第一步是确定日期的唯一值(contact_week) - 如何在reduce函数中执行此操作,因为它已经是遍历数据的for循环?

我想对于max等,我们可以使用reductio或其他一些逻辑,如评论中所述,但我并没有真正得到这里的方法/设计

对方法/解决方案的任何帮助都将受到高度赞赏。

UPDATE2:

使用relocation

尝试新方法

数据说明:

我的数据中的几列 - contact_week(日期); week_number(数字 - -4到6); decay_cnt(整数); totcount(整数);持续时间(序数值 - 前,中,后);

现在,我需要计算一个称为衰减%的百分比,其计算方法如下: 对于每个唯一的contact_week,找到最大的week_number,现在对于此过滤的数据集,计算sum(decay_cnt)/ sum(totcount)

这必须在条形图中绘制,其中x轴是持续时间,公制 - 衰减%是y轴

为了计算各个日期的周数的最大值,我现在绘制了一个条形图,其中contact_week为x轴,最大为week_number为y轴。 如何获得我需要的图表?

代码:

dateDimension2  = ndx.dimension(function(d) {return d.CONTACT_WEEK ;});
decayGroup = reductio().max(function (d) { return d.WEEK_NUMBER; })(dateDimension2.group());


chart2
    .width(500)
    .height(200)
    .x(d3.scale.ordinal())
    //.x(d3.scale.ordinal().domain(["DURING","POST1"]))
    .xUnits(dc.units.ordinal)
    //.xUnits(function(){return 10;})
    //.brushOn(false)
    .yAxisLabel("Decay (in %)")
    .dimension(dateDimension)
    .group(decayGroup)
    .gap(10)
    .elasticY(true)
    //.yAxis().tickValues([0, 5, 10, 15])
    //.title(function(d) { return d.key + ": " + d3.round(d.value.new_count,2); })
    /*.valueAccessor(function (p) {
    //return p.value.count > 0 ? (p.value.dec_total / p.value.new_count) * 100  : 0;
    return p.value.decay ;
    })*/
    .valueAccessor(function(d) { return d.value.max; })
    .on('renderlet', function(chart) {
        chart.selectAll('rect').on("click", function(d) {
            console.log("click!", d);
        });
    })
    .yAxis().ticks(5);

任何方法/建议都将受到高度赞赏

我认为解决方案主要在于假组/维度和减少组合方法。任何替代品都是最受欢迎的!

1 个答案:

答案 0 :(得分:3)

我刚刚为这类问题添加了a FAQan example

正如那里所解释的那样,我们的想法是保持一系列行,这些行落入每个bin,因为crossfilter doesn't provide access to that yet。一旦我们获得了实际行,您的计算几乎与您现在的计算相同,除了交叉过滤器跟踪您的周列表。

因此您可以使用示例中的这些函数:

protected void writeDirEntry(int id, DirectoryHandle dir, Buffer buffer, int index, Path f, String shortName, LinkOption... options) throws IOException {
   ...
    if (version == SFTP_V3) {
        // added shortName argument
        String longName = getLongName(f, options, shortName);
    } else {
    ...
}

// added shortName parameter
protected String getLongName(Path f, LinkOption... options, String shortName) throws IOException {
    // added shortName argument
    return getLongName(f, true, options, shortName);
}

// added shortName parameter
private String getLongName(Path f, boolean sendAttrs, LinkOption... options, String shortName) throws IOException {
    ...
    // added shortName argument
    return getLongName(f, attributes, shortName);
}

// added shortName parameter
private String getLongName(Path f, Map<String, ?> attributes, String shortName) throws IOException {
    ...
    return (SftpHelper.getBool(isDirectory) ? "d" : (SftpHelper.getBool(isLink) ? "l" : "-"))
            + PosixFilePermissions.toString(perms) + "  "
            + (attributes.containsKey("nlink") ? attributes.get("nlink") : "1")
            + " " + username + " " + group + " " + lengthString + " "
            + UnixDateFormat.getUnixDate((FileTime) attributes.get("lastModifiedTime"))
            // using shortName instead of getShortName(f) 
            + " " + shortName;
}

// + you need to modify sendPath to pass getShortName(f) 
//   to its call to getLongName

您需要在记录中使用唯一键,以便可以可靠地添加和删除它们。我假设您的记录中有 function groupArrayAdd(keyfn) { var bisect = d3.bisector(keyfn); return function(elements, item) { var pos = bisect.right(elements, keyfn(item)); elements.splice(pos, 0, item); return elements; }; } function groupArrayRemove(keyfn) { var bisect = d3.bisector(keyfn); return function(elements, item) { var pos = bisect.left(elements, keyfn(item)); if(keyfn(elements[pos])===keyfn(item)) elements.splice(pos, 1); return elements; }; } function groupArrayInit() { return []; } 字段。

定义您的周尺寸和组,如下所示:

ID

然后,在价值访问者中,最有效的时间来计算您的指标。因此,您可以使用在问题中发布的代码的核心来定义值访问器。

(当然,此代码未经测试,因为我不知道您的数据。)

var weekDimension = ndx.dimension(function(d) {return d.CONTACT_WEEK ;}),
    id_function = function(r) { return r.ID; },
    weekGroup = weekDimension.group().reduce(groupArrayAdd(id_function), groupArrayRemove(id_function), groupArrayInit);