patorashのブログ

方向性はまだない

c3.jsでスタックバーチャートをパーセント表示にする

またまたc3.jsネタです。

c3.jsでスタックバーをするのは簡単で、そのスタックバーの軸を100%にするように表示するのも簡単です。dataのところでstack: { normalize: true }とすればできます。

しかし、それだとチャートは%表示になるのですが、ツールチップに表示されるのは実数です😥

f:id:patorash:20200608024545p:plain
実数ではなく、%が知りたい

そこで、今回はこれを割合表示(%表示)にしてみます。

また、前回のと合わせて、ラベル中央に%表記してみます。前回の記事はこちら。

patorash.hatenablog.com

コード

まず、CodePenで書いたコードを載せておきます。プレビューを見てもらえばわかるかと思いますが、%表記になっています。

See the Pen c3-stacked-bar-chart-label-middle-percentage by patorash (@patorash) on CodePen.

解説

c3.jsでは、パイチャート等は%表示する方法があるらしいのですが、なぜかスタックバーチャートにはありません。なので、自力で実装していきます。

labelsのformatの指定を関数にして上書きする

labels:formatは通常はフォーマットを指定するだけですが、関数を取ることもできます。そこで、関数を使って割合を算出して出力させます。

labels: {
  format: (v, id, i, j) => {
    const sum = Object.values(json[i]).reduce((sum, value) => { 
      return sum + value;
    }, 0);
    return d3.format('.1%')(v/sum);
  }
}

関数の引数のvは実数、idはx軸のラベル(item0やitem1等だったはず)、iはループの何番目(item0ならば0, item1なら1等)か、jはiのループ内の更に何番目か(item0のdata1なら0, data2なら1等)を表します。

今回は単純に割合を知りたいので、item0, item1, ..., item4のそれぞれの合計値を取得し、それで実数を割ることで割合を出したいので、変数jsonからループ番目毎に値だけの配列を取得し、reduceで合計値を求めるようにしました。

最後に、d3.format('.1%')(v/sum)とすることで、小数点一桁までを出すようにしています。

これで、ラベルのほうを%表示にすることができました。ツールチップはまだなので、ツールチップも設定していきます。

tooltipのformat指定を関数にして上書きする

ツールチップのほうはめちゃくちゃ簡単です。なぜならば、引数に既にratioがあるからです。先ほどと同じように、d3.format('.1%')(raito)とするだけです。labelsのほうにも最初からratioがあればいいのに!!😅

tooltip: {
  format: {
    value: (value, ratio) => d3.format('.1%')(ratio)
  }
},

なにはともあれ、これでスタックバーチャートの表記が%表記になりました💪

f:id:patorash:20200608032356p:plain
%表記になったスタックバーチャート

検索用の文字を最後に残しておきます。

  • d3.js
  • stacked bar chart
  • percentage