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

d3.js分类时间序列(evolustrip),d3.js,time-series,D3.js,Time Series,在d3.js中,我正在寻找一种显示分类时间序列数据的好方法。数据值不能同时出现,且间距不均匀,因此我得到的数据完全类似于: location = [[time1: home], [time4: work], [time5: cafe], [time7: home]] 等等。我理想的结果图类似于一种可能被称为-一种查看此图表的方式是作为一个具有可变宽度条形图的时间序列图,条形图的颜色对应于类别(例如“home”) 谁能给我指出正确的方向吗?非常感谢你 所以我最终设计了自己的d3.js解决方案:

在d3.js中,我正在寻找一种显示分类时间序列数据的好方法。数据值不能同时出现,且间距不均匀,因此我得到的数据完全类似于:

location = [[time1: home], [time4: work], [time5: cafe], [time7: home]]
等等。我理想的结果图类似于一种可能被称为-一种查看此图表的方式是作为一个具有可变宽度条形图的时间序列图,条形图的颜色对应于类别(例如“home”)


谁能给我指出正确的方向吗?非常感谢你

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

我使用d3.time.scale刻度作为时间维度,然后使用d3.scale.category20刻度为类别提供颜色。然后,我将分类数据按开始时间在时间轴上绘制为相同高度的矩形,并使用d3.time.scale scale计算每个矩形的适当箱子宽度

此处可以看到一个可重用组件(遵循中的模式)示例:

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);
});

希望这对某人有帮助!这个项目是在

完成的,所以我最终设计了自己的d3.js解决方案:

我使用d3.time.scale刻度作为时间维度,然后使用d3.scale.category20刻度为类别提供颜色。然后,我将分类数据按开始时间在时间轴上绘制为相同高度的矩形,并使用d3.time.scale scale计算每个矩形的适当箱子宽度

此处可以看到一个可重用组件(遵循中的模式)示例:

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);
});
希望这对某人有帮助!为其制作的项目位于