web-dev-qa-db-ja.com

負の値の棒グラフ

負の値を持つことができるd3棒グラフを作成する必要があります。理想的には、軸のゼロ位置はデータの範囲に基づいて計算する必要がありますが、正と負の範囲が対称である、つまり常にグラフの中央にあると想定するソリューションを選択します。

これが私が達成したいことの例です。

Bar chart with negative values

27
khaledh

OK、データセットとして数値の配列があり、これには正と負の値が含まれているとしましょう。

var data = [-15, -20, -22, -18, 2, 6, -26, -18];

棒グラフを作成するには、2つのスケールが必要です。 x軸に沿ったバーの位置を計算するには、1つの定量的スケール(通常は 線形スケール )が必要です。 順序スケールy軸に沿ったバーの位置を計算します。

定量的スケールの場合、通常、最小値と最大値に基づいてデータのドメインを計算する必要があります。これを行う簡単な方法は、 d3.extent を使用することです。

var x = d3.scale.linear()
    .domain(d3.extent(data))
    .range([0, width]);

Nice 範囲をわずかに丸めるためのスケールも必要になる場合があります。別の例として、ゼロ値をキャンバスの中央に配置したい場合があります。その場合、最小値と最大値の大きい方を使用する必要があります。

var x0 = Math.max(-d3.min(data), d3.max(data));

var x = d3.scale.linear()
    .domain([-x0, x0])
    .range([0, width])
    .Nice();

または、必要なドメインをハードコーディングすることもできます。

var x = d3.scale.linear()
    .domain([-30, 30])
    .range([0, width]);

y軸の場合、 rangeRoundBands を使用して、垂直方向のスペースを各バーのバンドに分割します。これにより、バー間のパディングの量を指定することもできます。多くの場合、順序スケールは、名前や一意のIDなどの識別データとともに使用されます。ただし、データのインデックスと組み合わせて順序尺度を使用することもできます。

var y = d3.scale.ordinal()
    .domain(d3.range(data.length))
    .rangeRoundBands([0, height], .2);

2つのスケールができたので、バーを表示するためのrect要素を作成できます。トリッキーな部分の1つは、SVGでは、rectが左上隅に基づいて配置されることです(xおよびy属性)。したがって、x-およびy-スケールを使用して計算する必要があります左上隅の位置。これは、関連付けられた値が正か負かによって異なります。値が正の場合、データ値はバーの右端を決定し、負の場合は左端を決定します。バーの。したがって、ここでの条件:

svg.selectAll(".bar")
    .data(data)
  .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d, i) { return x(Math.min(0, d)); })
    .attr("y", function(d, i) { return y(i); })
    .attr("width", function(d, i) { return Math.abs(x(d) - x(0)); })
    .attr("height", y.rangeBand());

最後に、軸を追加して目盛りを上に表示できます。塗りつぶしスタイル(またはグラデーション)を計算して、正の値と負の値の外観を区別することもできます。すべてを一緒に入れて:

54
mbostock