web-dev-qa-db-ja.com

D3.jsで複数の線を描く

これまで、ループを使用して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}]);

4つの行があります。4つすべての時間を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");

そして、これらを1つずつ(またはループで)追加します。

var line1 = group.selectAll("path.path1")
        .attr("d",l(data));
var line2 = group.selectAll("path.path2")
        .attr("d",l2(data));
var line3 = group.selectAll("path.path3")
        .attr("d",l3(data));
var line4 = group.selectAll("path.path4")
        .attr("d",l4(data));

これらのパスを追加するより一般的な方法はありますか?

39
winter

はい。まず、次のように反復を容易にするためにデータを再構築します。

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 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 times = [1, 2, 3];

var values = [
  [2, 4, 8],
  [5, 9, 12],
  [3, 2, 2],
  [2, 4, 15]
];

マトリックスには時間値が含まれていないため、ラインジェネレーターのxアクセサーから検索する必要があります。一方、マトリックス値を直接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);
74
mbostock