React.js用ライブラリRechartsでランキングチャートを作成する

[QiiTrend](http://qiita.com/tag1216/items/e65496b932ca6790268b)にランキングチャートを実装するためにRechartsでのやり方を調べてみました。

# Rechartsとは

Rechartsはチャートを表示するためのReactライブラリです。

[Recharts](http://recharts.org/)

線グラフや円グラフなど一般的なグラフは一通り用意されているので、Reactで簡単にチャートを表示できます。

QiiTrendではこれを使ってトレンドチャートを表示しています。

# ランキングチャートとは

正確な定義があるわけではないですが、ここではY軸が順位になっていて1位から下に向かって順位が下がっていくチャートのことを指しています。

例

- [2015年Qiitaランキング - Qiita Blog](http://blog.qiita.com/post/136855781724/qiita2015ranking)
- [Rank of top languages on GitHub.com over time](https://adtmag.com/articles/2015/08/20/~/media/ECG/adtmag/Images/2015/08/github_languages.jpg)

# 2019/02/25 追記

コメントで @minakawa-daiki さんに教えて頂いた `reversed` を使うことで簡単に出来ました。

[DEMO](https://codesandbox.io/embed/3r8l8xvm5p?fontsize=14)

```javascript:RankingChart.js
import React from "react";
import {
    CartesianGrid,
    Legend,
    Line,
    LineChart,
    Tooltip,
    XAxis,
    YAxis
} from "recharts";

const data = [
    { name: "2014", Ruby: 1, JavaScript: 2, Python: 3 },
    { name: "2015", Ruby: 2, JavaScript: 1, Python: 3 },
    { name: "2016", Ruby: 3, JavaScript: 1, Python: 2 },
    { name: "2017", Ruby: 3, JavaScript: 2, Python: 1 }
];

const RankingChart = () => {
    return (
        <LineChart width={600} height={300} data={data}>
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis dataKey="name" />
            <YAxis
                type="number"
                reversed
                padding={{ top: 5, bottom: 5 }}
                interval={1}
                domain={[1, 3]}
            />
            <Line dataKey="JavaScript" stroke="#88ee88" />
            <Line dataKey="Ruby" stroke="#ee8888" />
            <Line dataKey="Python" stroke="#8888ee" />
            <Tooltip />
            <Legend />
        </LineChart>
    );
};
```

どうやらこの記事を書いたすぐ後に`reversed`が追加されたようです。

https://github.com/recharts/recharts/commit/99a6d70550c49c18d03630648fbed2f512ed97cc#diff-09b9103c2de981bf928da6b98409156d


---
以下は、2017/03/05に記載した内容です。

# 結論

最初に結論を書いておきますが、Rechartsでランキングチャートを表示するには特殊な対応が必要でした。

以下が実装例です。

http://jsfiddle.net/esg4vmpe/

```js:
const {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend} = Recharts;
const data = [
      {name: '', 1: 1, 2:2, 3:3},
      {name: '2014', Ruby: 1, JavaScript: 2, Python: 3},
      {name: '2015', Ruby: 2, JavaScript: 1, Python: 3},
      {name: '2016', Ruby: 3, JavaScript: 1, Python: 2},
      {name: '2017', Ruby: 3, JavaScript: 2, Python: 1},
];
const SimpleLineChart = React.createClass({
	render () {
  	return (
    	<LineChart width={600} height={300} data={data}
            margin={{top: 5, right: 30, left: 20, bottom: 5}}>
       <XAxis dataKey="name"/>
       <YAxis type="category" padding={{top: 5, bottom: 5}}/>
       <CartesianGrid strokeDasharray="3 3"/>
       <Tooltip/>
       <Legend />
       <Line dataKey="3" stroke="#ffffff" style={{display: "none"}}/>
       <Line dataKey="2" stroke="#ffffff" style={{display: "none"}}/>
       <Line dataKey="1" stroke="#ffffff" style={{display: "none"}}/>
       <Line dataKey="JavaScript" stroke="#88ee88" />
       <Line dataKey="Ruby" stroke="#ee8888"/>
       <Line dataKey="Python" stroke="#8888ee" />
      </LineChart>
    );
  }
})

ReactDOM.render(
  <SimpleLineChart />,
  document.getElementById('container')
);
```

# 解説

Rechatsに限らず一般的なチャートではY軸は小さい値が下、大きい値が上になります。(以下、昇順と表記します)
ランキングチャートではこれを逆(以下、降順)にしなければなりません。

RechartsではYAxisというReactコンポーネントでY軸の設定を行います。
YAxisにはticks,domainなどでtickの値や範囲を設定しますが、ここを降順に設定してもチャートは降順になりませんでした。
どうやら内部で値を昇順に表示するようにしているようです。

```js:domainやticksではダメだった
<YAxis domain={[3, 0]} ticks={[3, 2, 1]}/>
```

http://jsfiddle.net/hqpgpqzu/


そこで、Y軸を数値ではなくカテゴリーとして扱うように変更します。
カテゴリーとは、例えば売上チャートの「商品」や「店舗」のように文字列で表すデータのことです。

```js:Y軸のタイプをカテゴリーにする
<YAxis type="category"/>
```
http://jsfiddle.net/e2L2q7f9/

これで昇順になることはなくなったのですが、これだけだとデータの定義順序に依存してしまうようです。
仕方がないのでダミーデータを追加してこれを最初に表示します。

```js:ダミーデータを追加する
const data = [
      {name: '', 1: 1, 2:2, 3:3},
      :
];
const SimpleLineChart = React.createClass({
       :
       <Line dataKey="3" stroke="#ffffff" style={{display: "none"}}/>
       <Line dataKey="2" stroke="#ffffff" style={{display: "none"}}/>
       <Line dataKey="1" stroke="#ffffff" style={{display: "none"}}/>
```

これでなんとか降順で表示することができました。。。

![image](https://qiita-image-store.s3.amazonaws.com/0/35192/c683f914-53c3-d4ec-8892-800a15df4561.png)

# 最後に

Rechartsに限らない話ですが、予め想定されたチャートは簡単に綺麗に出来るけどちょっと特殊なことをやろうとすると途端に行き詰まる、というのがチャートライブラリではありがちです。

他にもQiiTrendでこれから実装しようとしていたことでRechartsでは難しい点がいくつか見つかりました。

QiiTrendの初期構築ではチャートにそれほど比重を置いていなかったので、Rechartsで簡単にチャートを実装できたことは非常に有益でした。
しかし今後機能を拡充することを考えると、D3.jsのような柔軟なライブラリに移行したほうが良さそうです。

D3の「全部自分で描かなきゃいけないけどなんでもできる」という設計思想は結構重要なんだと改めて気付かされました。