d3.js分类时间序列(evolustrip)

时间:2013-02-12 12:58:32

标签: d3.js time-series

d3.js 中工作,我正在寻找一种显示分类时间序列数据的好方法。数据值不能同时发生,并且间隔不均匀,因此我的数据完全如下:

location = [[time1: home], [time4: work], [time5: cafe], [time7: home]]

等等。我理想的结果图就像可能被称为evolustrip的东西 - 看到这个图表的一种方式是带有可变宽度条的时间序列图,条形颜色对应于类别(例如'home')。

有人能指出我正确的方向吗?非常感谢你!

1 个答案:

答案 0 :(得分:1)

所以我最终制作了自己的d3.js解决方案:

我使用d3.time.scale比例作为时间维度,然后使用d3.scale.category20比例来为类别提供颜色。然后,我按照开始时间将分类数据绘制为时间轴上的相同高度的rects,并使用d3.time.scale比例计算每个rect的适当bin宽度。

可以在此处看到可重用组件(遵循http://bost.ocks.org/mike/chart/模式)示例:

function timeSeriesCategorical() {
    var w = 860,
        h = 70,
        margin = {top: 20, right: 80, bottom: 30, left: 50},
        width = w - margin.left - margin.right,
        height = h - margin.top - margin.bottom;
    var xValue = function(d) { return d[0]; },
        yValue = function(d) { return d[1]; };
    var yDomain = null;
    var xScale = d3.time.scale()
        .range([0, width]);
    var yScale = d3.scale.category20();
    var xAxis = d3.svg.axis()
        .scale(xScale)
        .tickSubdivide(1)
        .tickSize(-height)
        .orient('bottom');
    var yAxis = d3.svg.axis()
        .scale(yScale)
        .ticks(5)
        .orient('left');
    var binwidth = 20;

    function chart(selection) {
        selection.each(function(data) {

            // convert data to standard representation
            data = data.map(function(d, i) {
                return [xValue.call(data, d, i), yValue.call(data, d, i)];
                //return d;
            });

            // scale the x and y domains based on the actual data
            xScale.domain(d3.extent(data, function(d) { return d[0]; }));
            if (!yDomain) {
                yScale.domain(d3.extent(data, function(d) { return d[1]; }));
            } else {
                yScale.domain(yDomain);
            }

            // compute binwidths for TODO better comment
            // d looks like {timestamp, category}
            data.forEach(function(d, i) {
                if (data[i+1]) {
                    w_current = xScale(data[i][0]);
                    w_next = xScale(data[i+1][0]);
                    binwidth = w_next - w_current;
                }
                d.binwidth = binwidth;
            });

            // create chart space as svg
            // note: 'this' el should not contain svg already
            var svg = d3.select(this).append('svg').data(data);

            // external dimensions
            svg.attr('width', w)
                .attr('height', h);

            // internal dimensions
            svg = svg.append('g')
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            // x axis
            svg.append('g')
                .attr('class', 'x axis')
                .attr('transform', 'translate(0,' + height + ')')
                .call(xAxis);

            // TODO bars legend

            // bars
            svg.selectAll('rect')
                .data(data)
              .enter().append('rect')
                .attr('x', function(d, i) { return xScale(d[0]); })
                .attr('width', function(d, i) { return d.binwidth; })
                .attr('height', height)
                .attr('fill', function(d, i) { return yScale(d[1]); })
                .attr('stroke', function(d, i) { return yScale(d[1]); });

        });
    }

    chart.x = function(_) {
        if (!arguments.length) return xValue;
        xValue = _;
        return chart;
    };

    chart.y = function(_) {
        if (!arguments.length) return yValue;
        yValue = _;
        return chart;
    };

    chart.yDomain = function(_) {
        if (!arguments.length) return yDomain;
        yDomain = _;
        return chart;
    };

    return chart;
}

可以用以下内容调用:

d3.csv('./data.csv', function(data) {
     var chartActivity = timeSeriesCategorical()
        .x(function(d) { return d.when; })
        .y(function(d) { return d.activity; })
        .yDomain([0,1]);
     d3.select('#chart-activity')
        .datum(data)
        .call(chartActivity);
});

希望这对某人有帮助!制作的项目是https://github.com/interaction-design-lab/stress-sense-portal