2016-04-16 19 views
0

現在、いくつかのデータパスの領域を表示する領域グラフがあります。しかし、私は積み重ねたエリアチャートに変換する方法を探しています。基本的には、データセットを重ねて重ねて表示し、他の大きな領域に隠れないようにします。既存のd3領域をスタック領域に変換するにはどうすればよいですか?

私は2つの例:http://bl.ocks.org/mbostock/3885211http://bl.ocks.org/mbostock/3020685を見つけました。私が持っている問題は、私のデータが非常に異なった形式であり、d3がどのように実際にこの作業をしているかについてもわかりません。概念的には、d3が背後で何をしているのかを理解するのが難しい。私が理解しているのは、最後に追加されたレイヤーの違いを計算していることですが、スタックを使用せずに行うことができるようです。

私のデータは、このように構成されています

// datasets { data1: Array[10], data2: Array[10], data3: Array[10] } 
// data1 [{value: 2340234, year: 1945}...] 

そして、描画機能はこれです:

function draw(series) { 
    var data1 = []; 
    var data2 = []; 
    var data3 = []; 
    var prop = 0; 

    for (prop in series) { 
    var current = series[prop]; 

    data1.push({value: current.data1, year: current.year}); 
    data2.push({value: current.data2, year: current.year}); 
    data3.push({value: current.data3, year: current.year}); 
    } 

    var datasets = { 
    data1: data1, 
    data2: data2, 
    data3: data3 
    }; 

    // updated 
    var layers = [datasets.data1, datasets.data2, datasets.data3]; 

    var height = 800; 
    var width = window.innerWidth - 100; 

    var x = d3.time.scale() 
     .range([0, width]); 

    var y = d3.scale.linear() 
     .range([height, 0]); 

    var xAxis = d3.svg.axis() 
     .scale(x) 
     .orient("bottom"); 

    var yAxis = d3.svg.axis() 
     .scale(y) 
     .orient("left"); 

    // updated 
    var stack = d3.layout.stack() 
     .values(function(d) { return d.values; }); 
    /

    var stacked = stack(layers.map(function(layer) { 
    return { 
     values: layer.map(function(d) { 
     return { year: new Date(d.year, 0), y: +d.value}; 
     }) 
    }; 
    })); 

    var area = d3.svg.area() 
     .x(function(d) { 
      console.log(x(d.year) + ' is the result of x(d.year)') 
      return x(d.year); 
     }) 
     // d.year is defined correctly 
     .y0(height) 
     .y1(function(d) { 
      console.log(y(d.value) + ' is the result of y(d.value)') 
      return y(d.value); 
     }); 
     // d is Object {year: Sat Jan 01 2005 00:00:00 GMT-0800 (PST), y: 47390331, y0: 0} 
     // here y(d.value) returns NaN for some reason 

    var svg = d3.select('body').append("svg") 
    .append("g") 
     .attr("transform", "translate(" + 120 + "," + 30 + ")"); 

    // Calculate max value 
    var maxY = 0; 
    var minY = 0; 
    series.forEach(function(object) { 
    for (var key in object) { 
     if (object[key] > maxY) { 
     maxY = object[key]; 
     } 
    } 
    }); 

    // Calculate min value 
    series.forEach(function(object) { 
    for (var key in object) { 
     if (object[key] < minY) { 
     minY = object[key]; 
     } else if (minY === 0) { 
     continue; 
     } 
    } 
    }); 

    var minYear = new Date("1945"); 
    var maxYear = new Date("2015"); 

    x.domain([minYear, maxYear]); 
    y.domain([minY, maxY]); 

    svg.append("path").data(stacked) 
    .attr('d', function(d) { return area(d.values); }); 

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

    svg.append("g") 
    .attr("class", "y axis") 
    .call(yAxis); 

} 

積み上げ面グラフにこれを変換するための最良の方法は何ですか?

編集固定

。例で見られるようなソリューションは、計算の領域を含んでいた:

var area = d3.svg.area() 
    .x(function(d) { return x(d.year); }) 
    .y0(function(d) { return y(d.y0); }) 
    .y1(function(d) { return y(d.y0 + d.y); }); 

答えて

1

あなたが何をする必要があるかを簡単にフライバイ:


、適切なスタック・ジェネレータを作成します。

var stack = d3.layout.stack() 
    .values(function(d) { return d.values; }); 

をスタックジェネレータを使用してデータを実行します。ジェネレーターに「レイヤー」の配列を渡す必要があります。下の例では、私はlayers = [datasets.data1, datasets.data2, datasets.data3]が起こったと仮定します。

var stacked = stack(layers.map(function(layer) { 
    return { 
     values: layer.map(function(d) { 
     return {year: new Date(d.year, 0), y: +d.value}; 
     }) 
    }; 
    })); 

valuesは、ジェネレータの設定時に使用したものと同じものです。後で図面の中に必要なものがあれば、このオブジェクトに多くのものを追加することができます。


積み重ねられたデータを作成した後、地域の発電機を介して実行:あなたはあなたが欲しい場合は、これをやって続けることができ.datum(datasets[data]) —を使用し、あなたの元のコードでは

svg.append("path") 
    .data(stacked) 
    .attr("d", function(d) { return area(d.values); }); 

のが、forループます積み重ねられたデータ上で実行する必要があります。

for (var data in stacked) { ... 

はしかし、私は.data.datum以上のwherを使用することをお勧めしますe可能です。オリジナルのデータセットをd3ジェネレータに送る前に、たくさんの操作を行いますが、そのほとんどは不要であるか重複していると思われます。データセットと発電機は、あなたが気に特定のフィールド/値の位置をマッピング以外の何物でもないはずの設定

var datasets = ... 

    var stacked = stack(datasets.map(function(dataset) { ... })); 

    svg.selectAll("path") 
     .data(stacked) 
     .enter() 
     .attr("d", function(d) { return area(d.values); }); 

:あなたはのように見える何かに得ることができる必要があります。

もし役に立ちそうなら、私は実用的な例を得ることができます。私は実際のデータファイルが必要になります。

関連する問題