【问题标题】:Create a running sum graph in dc.js在 dc.js 中创建运行总和图
【发布时间】:2014-03-09 01:28:27
【问题描述】:

我正在尝试在 crossfilter 中创建一个运行总和以与 dc.js 一起使用。 我有一组记录如下:

records = [{"date":"2014-01-01","field1":"value1","field2":"value11","value_field":-20},
           {"date":"2014-01-02","field1":"value2","field2":"value12","value_field":100},
           {"date":"2014-01-03","field1":"value1","field2":"value11","value_field":-10},
           {"date":"2014-01-04","field1":"value2","field2":"value12","value_field":150},
           ]

到目前为止,我已经创建了一个 barGraph,它可以很好地与其他维度配合使用,但我希望能够显示理论字段 runnning_total(沿维度日期)的折线图。

要在交叉过滤器中完成它,我可以使用fieldx 字段进行分组,并轻松获得相同的运行总图,但仅限于使用 dc.js 的值子组。

欢迎任何帮助。

【问题讨论】:

    标签: sum dc.js crossfilter cumulative-sum


    【解决方案1】:

    由于您是跨日期分组(根据您的 date dimension),reduce() 函数将用于执行聚合按日期分组,根据我的米老鼠示例中突出显示的单元格下面:

    使用运行总计,您需要执行完全不同的操作,循环行:

    您可以聚合数据,然后按如下方式附加运行总计字段。我还提供了一个如何使用 reduce 函数计算平均值的示例:

    records = [{ "date": "2014-01-01", "field1": "value1", "field2": "value11", "value_field": -20 },
        { "date": "2014-01-02", "field1": "value2", "field2": "value12", "value_field": 100 },
        { "date": "2014-01-03", "field1": "value1", "field2": "value11", "value_field": -10 },
        { "date": "2014-01-04", "field1": "value2", "field2": "value12", "value_field": 150 }
    ];
    
    
    var cf = crossfilter(records);                                 
    
    var dimensionDate = cf.dimension(function (d) {
            return d.date;
        });
    
    
    function reduceAdd(p, v) {
        p.total += v.value_field;
        p.count++;
        p.average = p.total / p.count;
        return p;
    }
    function reduceRemove(p, v) {
        p.total -= v.value_field;
        p.count--;
        p.average = p.count ? p.total / p.count : 0;
        return p;
    }
    function reduceInitial() {
        return {
            total: 0,
            count: 0,
            average: 0,
        };
    }
    
    
    
    var average = dimensionDate.group().reduce(reduceAdd, reduceRemove, reduceInitial).all();
    
    var averageWithRunningTotal = appendRuningTotal(average);  
    
    function appendRuningTotal(average) {
        var len = average.length,
            runningTotal = 0;
        for (var i = 0; i < len; i++) {
            runningTotal += average[i].value.total;
            average[i].RunningTotal = runningTotal;
        }
    
        return average;
    }
    

    这会返回以下内容:

    {"key":"2014-01-01","value":{"total":-20,"count":1,"average":-20},"RunningTotal":-20}
    {"key":"2014-01-02","value":{"total":100,"count":1,"average":100},"RunningTotal":80}
    {"key":"2014-01-03","value":{"total":-10,"count":1,"average":-10},"RunningTotal":70}
    {"key":"2014-01-04","value":{"total":150,"count":1,"average":150},"RunningTotal":220}
    

    【讨论】:

    • 所以我设法使用.valueAccessor 显示了初始运行总行。但是我仍然缺少的是当我选择其他条形图中的一个组时,运行总计自动更新的能力。我只想显示其中一个字段的选定值的运行总计。回到我的例子:只有field1=value1 记录的运行总数是多少?
    • 您可以在 reduce 函数中更改 p.total 值,以查看 field1。所以从这里:p.total += v.value_field; 到这里:p.total += v.value1; 如果你想要所有字段的总数,那么只需在 reduceInital 函数中为它们组成新变量并在 reduceAddreduceRemove 函数中分配给它们. :)
    • 也许我误解了您的评论,但我认为它不适用于我的情况。就我而言,不是ApplesBananas,而是NameCity。假设我的value 字段是该城市每天向该特定人员出售的橙子数量。我想展示的是 1. 运行中沿 dateDimension 销售的橙子总数的折线图 2. 一段时间内按城市销售的橙子总数的条形图。当我点击一个城市的栏时,如何让 lineChart 更新为正确的 runningTotal?
    • 我实际上并没有使用 dc.js,所以我只是在这里有交叉过滤器的知识。您是否需要立即知道如何按日期和城市进行分组?即单击该行应将数据过滤到伦敦并按日期。
    • 好的。单击该栏应仅显示按日期为伦敦所有人售出的橙子总数。
    【解决方案2】:

    好吧,我知道该操作已经构建了一个解决方案,但经过一段时间的努力,我能够破解它,所以如果其他人搜索它,请在此处发布。

    对以下内容使用累积:https://groups.google.com/forum/#!topic/dc-js-user-group/W9AvkP_dZ0U

    运行总和:

    var _group   = dim.group().reduceSum(function(d) {return 1;});
    
    var group = {
    all:function () {
     var cumulate = 0;
     var g = [];
     _group.all().forEach(function(d,i) {
       cumulate += d.value;
       g.push({key:d.key,value:cumulate})
     });
     return g;
    }
    

    };

    对于过去十二个月的计算:

    var _group   = dateDim.group().reduceSum(function(d) {return d.revenue;});
    var group = {
    all:function () {
    var g = [];
    _group.all().forEach(function(d,i) {
        var cumulate = 0;
        var monthcount =0;
        var dt =new Date( d.key);
        var ct =  new Date(d.key);
        ct.setFullYear(ct.getUTCFullYear() -1);
        _group.all().forEach(function(d2,i) {
            var dt2 = new Date(d2.key);
            if(dt2 <= dt && dt2 > ct){
                cumulate += d2.value;
                monthcount++; 
            }
        })
        if(monthcount>=11){
            console.log( ' Dt ' + dt + ' ' + cumulate + ' months ' + monthcount); 
            g.push({key:d.key,value:cumulate})
            }
        });
                    return g;
                }
            }; 
    

    【讨论】:

    • 6 年后重温这个(该死!),这是正确的解决方案。请注意您的组是否沿时间轴排序,并且需要根据每个特定情况进行调整,但这是要走的路。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 2015-12-13
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多