在dc.js时间序列折线图中绘制缺少日期的间隙

时间:2017-05-09 23:04:12

标签: dc.js crossfilter

好的,我已经看过this机票和this问题了,并且已经尝试了几个例子。也许我只是密集,但我真的无法破解这个。

我有一系列时间序列的事件。默认情况下,dc.js在间隙上连接一条直线(当它们真的不应该时,它看起来像是在那里表示的东西)。例如,在this图表中,我们的数据如下:

    {"time":"2014-06-09T18:45:00.000Z","input":17755156,"output":250613233.333333},
    {"time":"2014-06-09T18:46:00.000Z","input":18780286.6666667,"output":134619822.666667},
    {"time":"2014-06-09T18:47:00.000Z","input":20074614.6666667,"output":203239834.666667},
    {"time":"2014-06-09T18:48:00.000Z","input":22955373.3333333,"output":348996205.333333},
    {"time":"2014-06-09T18:49:00.000Z","input":19119089.3333333,"output":562631022.666667},
    {"time":"2014-06-09T18:50:00.000Z","input":15404272,"output":389916332},
    {"time":"2014-06-09T18:51:00.000Z","input":null,"output":null},
    {"time":"2014-06-09T21:25:20.000Z","input":5266038.66666667,"output":62598396},
    {"time":"2014-06-09T21:26:20.000Z","input":6367678.66666667,"output":84494096},
    {"time":"2014-06-09T21:27:20.000Z","input":5051610.66666667,"output":88812540},
    {"time":"2014-06-09T21:28:20.000Z","input":5761069.33333333,"output":79098036},
    {"time":"2014-06-09T21:29:20.000Z", "input":5110277.33333333,"output":45816729.3333333}

尽管只有两组实际的数据,但是该图表上有一条连接它们的线。如何在没有数据的情况下将dc.js线图绘制为0。我尝试过使用.defined(function(d) { return !isNaN(d.x);}).defined(function(d) { return d.y != null; })等等,但这只是在迭代不存在的数据。

1 个答案:

答案 0 :(得分:1)

在使用crossfilter时尝试保留空值很棘手,因为crossfilter完全是关于聚合的。

请记住,reduceSum会添加找到的任何值,从零开始,0 + null === 0

在您的情况下,您似乎并未实际汇总,因为您的时间戳是唯一的,因此您可以执行以下操作:

var input  = time.group().reduce(
    function(p, d) {
       if(d.input !== null)
           p += d.input;
       else p = null;
       return p;
    },
    function(p, d) {
       if(d.input !== null)
           p -= d.input;
       else p = null;
       return p;
    },
    function(){ return 0; }
);

是的,这比reduceSum要复杂得多,如果不止一个数据落入存储桶,它可能会变得更加复杂。 (不确定你想做什么 - 是否有可能部分定义数据点?)

通过这种方式定义缩减,null减少为null,dc.js能够找到间隙: line chart with gaps

你小提琴的叉子(谢谢!):http://jsfiddle.net/gordonwoodhull/omLko77k/3/

编辑:计算空值

如果您正在做一个真实的"减少bin中有多个值的情况,我认为您需要计算非空值的数量以及保持运行总和。

如果没有非空值,则总和应为null

这次重新使用我们的代码:

function null_counter(field) {
    return {
        add: function(p, d) {
            if(d[field] !== null) {
                p.nvalues++;
                p.sum += d[field];
            }
            return p;
        },
        remove: function(p, d) {
            if(d[field] !== null) {
                p.nvalues--;
                p.sum -= d[field];
                if(!p.nvalues)
                    p.sum = null;
            }
            return p;
        },
        init: function() {
            return {nvalues: 0, sum: null};
        }
    }
}

像这样应用(并且这次得到正确的字段):

var input_reducer = null_counter('input');
var input = time.group().reduce(
    input_reducer.add,
    input_reducer.remove,
    input_reducer.init
);
var output_reducer = null_counter('output');
var output = time.group().reduce(
    output_reducer.add,
    output_reducer.remove,
    output_reducer.init
);

由于我们正在缩减为具有两个值{nvalues, sum}的对象,因此我们需要使所有访问器更复杂一些:

    .valueAccessor(function(kv) { return kv.value.sum; })
    .defined(function(d){
        return (d.data.value.sum !== null);
    })
chart.stack(output, "Output bits",
            function(kv) { return kv.value.sum; });

更新了fork:http://jsfiddle.net/gordonwoodhull/omLko77k/9/