在D3.js中绘制多行

在D3.js中绘制多行,d3.js,line,D3.js,Line,到目前为止,我一直在使用循环向D3可视化添加行元素,但这似乎不符合API的精神 假设我有一些数据 var data = {time: 1, value: 2, value2: 5, value3: 3,value4: 2}, {time: 2, value: 4, value2: 9, value3: 2,value4: 4}, {time: 3, value: 8, value2:12, value3: 2,value4:15}]); 我想要四行,

到目前为止,我一直在使用循环向D3可视化添加行元素,但这似乎不符合API的精神

假设我有一些数据

var data = {time: 1, value: 2, value2: 5, value3: 3,value4: 2},
           {time: 2, value: 4, value2: 9, value3: 2,value4: 4},
           {time: 3, value: 8, value2:12, value3: 2,value4:15}]);
我想要四行,时间是所有四行的X

我可以这样做:

var l = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[1]]);})
        .interpolate("basis");
var l2 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[2]]);})
        .interpolate("basis");
var l3 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[3]]);})
        .interpolate("basis");  
var l4 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[4]]);})
        .interpolate("basis");
var series = [
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 8}],
  [{time: 1, value: 5}, {time: 2, value: 9}, {time: 3, value: 12}],
  [{time: 1, value: 3}, {time: 2, value: 2}, {time: 3, value: 2}],
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 15}]
];
var times = [1, 2, 3];

var values = [
  [2, 4, 8],
  [5, 9, 12],
  [3, 2, 2],
  [2, 4, 15]
];
然后逐个(或通过循环)添加这些


有没有更好更通用的方法添加这些路径

是的。首先,我将重组您的数据以便于迭代,如下所示:

var l = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[1]]);})
        .interpolate("basis");
var l2 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[2]]);})
        .interpolate("basis");
var l3 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[3]]);})
        .interpolate("basis");  
var l4 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[4]]);})
        .interpolate("basis");
var series = [
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 8}],
  [{time: 1, value: 5}, {time: 2, value: 9}, {time: 3, value: 12}],
  [{time: 1, value: 3}, {time: 2, value: 2}, {time: 3, value: 2}],
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 15}]
];
var times = [1, 2, 3];

var values = [
  [2, 4, 8],
  [5, 9, 12],
  [3, 2, 2],
  [2, 4, 15]
];
现在您只需要一个通用行:

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d) { return x(d.time); })
    .y(function(d) { return y(d.value); });
然后,您可以一次性添加所有路径元素:

group.selectAll(".line")
    .data(series)
  .enter().append("path")
    .attr("class", "line")
    .attr("d", line);
如果要使数据结构格式更小,还可以将时间提取到单独的数组中,然后使用2D数组作为值。看起来是这样的:

var l = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[1]]);})
        .interpolate("basis");
var l2 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[2]]);})
        .interpolate("basis");
var l3 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[3]]);})
        .interpolate("basis");  
var l4 = d3.svg.line()
        .x(function(d){return xScale(d[keys[0]]);})
        .y(function(d,i){
            return yScale(d[keys[4]]);})
        .interpolate("basis");
var series = [
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 8}],
  [{time: 1, value: 5}, {time: 2, value: 9}, {time: 3, value: 12}],
  [{time: 1, value: 3}, {time: 2, value: 2}, {time: 3, value: 2}],
  [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 15}]
];
var times = [1, 2, 3];

var values = [
  [2, 4, 8],
  [5, 9, 12],
  [3, 2, 2],
  [2, 4, 15]
];
因为矩阵不包含时间值,所以需要从line generator的x-accessor中查找它。另一方面,由于您可以将矩阵值直接传递到y标尺,y存取器得到简化:

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d, i) { return x(times[i]); })
    .y(y);
创建元素时保持不变:

group.selectAll(".line")
    .data(values)
  .enter().append("path")
    .attr("class", "line")
    .attr("d", line);

迈克,我在这里用你的例子在多行上取得了一些进展,但是你怎么做呢?想知道你是否能注意到这个问题:--谢谢
x
y
指的是刻度,您应该在使用前定义刻度。我不确定这是否应该直接可用,但目前,此代码无法放入示例文件中并起作用。至少对像我这样的新手来说不是这样的。这是完整的吗?其中是
group。选择All
from,我看不到定义的组对象。group指的是svg组,您应该在添加路径之前定义该组。