Rechartsを使った時系列データの折れ線グラフの作成手順紹介

時系列データグラフ

悩む人
Reactでグラフ作る方法がわからない。
Rechartsを使って時系列データの折れ線グラフを作りたいけど、どうしたらいいの?

そんな悩みに答えます。

React でグラフを作れるライブラリ「Recharts」で、時系列データの折れ線グラフを作る方法を紹介します。

この記事を読むことで、時系列データの折れ線グラフを作れるようになります。

本記事の狙い

  • Rechartsで時系列データの折れ線グラフを作れるようになる

Recharts, moment のインストール

グラフを作成するために Recharts をインストールします。
また、時系列データの時間の値を加工したいので、moment をインストールします。

npm で下記のようにインストールします。

npm install recharts moment

 

時系列データ折れ線グラフのサンプルコード

時系列データの折れ線グラフを描画できるサンプルコードを作成したので、下記の通り紹介します。

コピペするだけでとりあえずグラフが作れます。

以降で時系列データのデータ形式や記述方法を紹介します。

import React from 'react';
import {
    LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend,
} from 'recharts';
import moment from 'moment';

const data = [
    { time: "2020-10-29T00:39:11.934Z", val: 7 },
    { time: "2020-10-29T00:32:39.686Z", val: 10 },
    { time: "2020-10-29T00:19:21.722Z", val: 14 },
    { time: "2020-10-29T00:59:30.532Z", val: 19 },
    { time: "2020-10-29T00:21:05.784Z", val: 23 },
    { time: "2020-10-29T00:27:09.031Z", val: 25 },
    { time: "2020-10-29T00:24:10.445Z", val: 15 },
    { time: "2020-10-29T00:52:54.226Z", val: 22 },
    { time: "2020-10-29T00:15:53.244Z", val: 9 },
    { time: "2020-10-29T00:35:21.302Z", val: 5 },
    { time: "2020-10-29T00:34:53.843Z", val: 23 },
    { time: "2020-10-29T00:41:40.703Z", val: 24 },
    { time: "2020-10-29T00:32:38.129Z", val: 19 },
    { time: "2020-10-29T00:58:48.600Z", val: 17 },
    { time: "2020-10-29T00:04:32.791Z", val: 11 },
    { time: "2020-10-29T00:25:51.704Z", val: 20 },
    { time: "2020-10-29T00:58:59.329Z", val: 24 },
    { time: "2020-10-29T00:05:34.037Z", val: 25 },
    { time: "2020-10-29T00:51:06.128Z", val: 13 },
    { time: "2020-10-29T00:37:17.627Z", val: 8 },
    { time: "2020-10-29T00:02:40.281Z", val: 9 },
    { time: "2020-10-29T00:32:17.279Z", val: 23 },
    { time: "2020-10-29T00:04:06.762Z", val: 7 },
    { time: "2020-10-29T00:22:15.742Z", val: 15 },
    { time: "2020-10-29T00:00:28.198Z", val: 12 },
    { time: "2020-10-29T00:47:42.282Z", val: 23 },
    { time: "2020-10-29T00:38:57.798Z", val: 19 },
    { time: "2020-10-29T00:07:01.130Z", val: 19 },
    { time: "2020-10-29T00:05:31.092Z", val: 8 },
    { time: "2020-10-29T00:47:26.021Z", val: 10 },
    { time: "2020-10-29T00:38:24.590Z", val: 25 },
    { time: "2020-10-29T00:13:53.737Z", val: 10 },
    { time: "2020-10-29T00:54:56.662Z", val: 7 },
    { time: "2020-10-29T00:56:27.843Z", val: 10 },
    { time: "2020-10-29T00:26:09.775Z", val: 18 },
    { time: "2020-10-29T00:03:32.874Z", val: 19 },
    { time: "2020-10-29T00:33:18.165Z", val: 24 },
    { time: "2020-10-29T00:12:22.762Z", val: 17 },
    { time: "2020-10-29T00:11:54.368Z", val: 18 },
    { time: "2020-10-29T00:01:57.869Z", val: 24 },
    { time: "2020-10-29T00:49:28.721Z", val: 24 },
    { time: "2020-10-29T00:36:31.733Z", val: 7 },
    { time: "2020-10-29T00:58:19.009Z", val: 18 },
    { time: "2020-10-29T00:00:55.483Z", val: 20 },
    { time: "2020-10-29T00:34:08.795Z", val: 16 },
    { time: "2020-10-29T00:30:27.200Z", val: 18 },
    { time: "2020-10-29T00:47:49.359Z", val: 16 },
    { time: "2020-10-29T00:43:31.766Z", val: 7 },
    { time: "2020-10-29T00:13:49.771Z", val: 12 },
    { time: "2020-10-29T00:53:27.715Z", val: 9 }
]
const LineSample = () => {
    const convert = (data) => {
        const result = data.map((d) => {
            return {
                time: moment(d.time).format("YYYY-MM-DD HH:mm:ss"),
                val: d.val
            }
        })
        result.sort((a, b) => a.time < b.time ? -1 : 1)
        return result
    }

    return (
        <LineChart
            width={500}
            height={300}
            data={convert(data)}
            margin={{
                top: 30, right: 30, left: 20, bottom: 20,
            }}
        >
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis
                dataKey="time"
                domain={["dataMin", "dataMax"]}
                tickFormatter={(t) => moment(t).format("HH:mm:ss")}
                label={{
                    value: "日時", offset: -5, position: "insideBottomRight"
                }}
            />
            < YAxis label={{ value: "気温(℃)", angle: -90, position: "insideLeft" }} />
            <Tooltip />
            <Legend verticalAlign="bottom" />
            <Line type="monotone" dataKey="val" name="東京" stroke="#8884d8" dot={false} />
        </LineChart>
    );
}
export default LineSample

時系列データグラフ

作成されるグラフ

 

グラフに渡すデータ形式

グラフに渡すデータ形式は、オブジェクトを要素した配列です。
オブジェクトの中身は、最低限、横軸と縦軸に使用するため、2つのプロパティがあればOKです。
表示する値の折れ線を増やしたい場合には、縦軸用のプロパティを増やせばOKです。

今回の場合、時系列の気温の値を表示するため、下記の形式にしています。
Key名は任意です。
何かしらの時系列データを取得して、グラフに渡す際は、この形式に変換して渡してあげてください。

key value
横軸用のプロパティ time 日時
縦軸用のプロパティ val 気温の値

データ形式

const data = [
{ time: "2020-10-29T00:39:11.934Z", val: 7 },
{ time: "2020-10-29T00:32:39.686Z", val: 10 }, 
{ time: "2020-10-29T00:19:21.722Z", val: 14 }
]

実際のデータの中身

値ごとに時間軸が異なるデータを渡す場合、折れ線は一応描画されますが、
マウスカーソルを当てたときに表示されるツールチップで値と時間がズレた状態になります。
渡すデータは、同じ時間軸で揃えた方がいいかもしれません。

 

サンプルコードの解説

上記のコードの使い方、記述方法を筆者の知っている限りで解説します。
より詳しく知りたい方は、公式ページをご参照ください。
https://recharts.org/en-US/api/LineChart

  • 折れ線グラフ本体
  • グリット線
  • 横軸
  • 縦軸
  • ツールチップ
  • 凡例
  • 折れ線
  • 変換処理

折れ線グラフ本体

        <LineChart
            width={500}
            height={300}
            data={convert(data)}
            margin={{
                top: 30, right: 30, left: 20, bottom: 20,
            }}
        >
...
        </LineChart>

LineChartコンポーネントが折れ線グラフを描画するためのものです。
これを親コンポーネントとして、子コンポーネントに細々した描画設定を定義します。

LineChartコンポーネントの属性(プロパティ)の意味は下記の通りです。

属性名 意味
width グラフの幅。ピクセル値
height グラフの高さ。ピクセル値
data 描画のためのオブジェクトを要素に持つ配列データ。
margin グラフの周りの余白サイズ。ピクセル値

LineChartの属性情報

本コードでは、width, height, を公式サンプルコードのデフォルトのまま、marginはテキトーに決めています。
dataには、生の時系列データを一度変換処理を通して、渡すようにしています。
(ここが適切な位置かは微妙なので、吟味したい方は頑張ってください。)

 

グリット線

<CartesianGrid strokeDasharray="3 3" />

CartesianGridコンポーネントは、グラフにグリット線を描画するためのものです。

strokeDasharray属性の説明は公式ページに見当たらないのですが、
グリット線を点線にして、線の長さと空白の長さを指定できるようです。

属性名 意味
strokeDasharray 点線の線の長さと空白の長さを指定できます。
1番目の数値が線の長さ、2番目の数値が空白の長さ

CartesianGridの属性情報

本コードでは、strokeDasharrayを公式サンプルコードのデフォルトのままにしています。

 

横軸

<XAxis
    dataKey="time"
    domain={["dataMin", "dataMax"]}
    tickFormatter={(t) => moment(t).format("HH:mm:ss")}
    label={{
        value: "日時", offset: -5, position: "insideBottomRight"
    }}
/>

XAxisコンポーネントは、横軸の描画を設定するものです。

XAxisコンポーネントの属性(プロパティ)の意味は下記の通りです。

属性名 意味
dataKey 横軸で使用するデータのkey名を指定
domain 横軸の表示幅を指定。
dataMinは最小値, dataMaxは最大値です。
tickFormatter 横軸の表示形式を指定。
上記のように値を受け取ってmomentで表示形式を指定して返しています。
指定しない場合、表示形式は値のままになります。
label 横軸のラベルを指定。
valueには、任意のラベル名を指定
offsetは、positionを基準にラベルを移動させるピクセル値を指定(多分)
正の値で上に移動、負の値で下に移動します。
positionは、ラベルの初期位置を指定。
指定の種類は公式ページ参照
https://recharts.org/en-US/api/Label

XAxisの属性情報

本コードでは、横軸に使用するプロパティとして、timeを使いたいため、dataKeyでtimeを指定しています。
domainは、テキトーです。
tickFormatterは、横軸の表示形式を時間のみしたかったので、上記のように変換しています。
labelは、とりあえずつけて、実際の表示を確認しながら微調整して決めています。
調整しないと、凡例の位置と被ってしまうので、うまく調整してください。

 

縦軸

<YAxis label={{ value: "気温(℃)", angle: -90, position: "insideLeft" }} />

YAxisコンポーネントは、縦軸の描画を設定するものです。

YAxisコンポーネントの属性(プロパティ)の意味は下記の通りです。

属性名 意味
label 縦軸のラベルを指定。
valueには、任意のラベル名を指定
angleは、ラベルの表示方向を角度で指定
0が通常の状態、90が右が上の状態、180が下が上の状態、-90が左が上の状態です。
positionは、ラベルの初期位置を指定。
指定の種類は公式ページ参照
https://recharts.org/en-US/api/Label

YAxisの属性情報

本コードでは、縦軸に使用するプロパティとして、labelのみ使用しています。
横軸のように表示形式を設定したい場合には、dataKeyやdomainを使用すると良いでしょう。
labelは、とりあえずつけて、実際の表示を確認しながら微調整して決めています。

 

ツールチップ

<Tooltip />

Tooltipコンポーネントは、グラフのデータにマウスカーソルを当てた際に表示されるツールチップを設定するものです。
ツールチップの表示形式を変えたい場合は、content属性に任意の形式を作成して指定すればいいのですが、
結構めんどうくさいです。
どうしても変更したい場合は、各自ググってください。

本コードでは、ツールチップを表示するだけにしています。

 

凡例

<Legend verticalAlign="bottom" />

Legendコンポーネントは、グラフの凡例を設定するものです。

Legendコンポーネントの属性(プロパティ)の意味は下記の通りです。

属性名 意味
verticalAlign 凡例の表示位置を指定
topは上部、middleは中部、bottomは下部の位置になります。

Legendの属性情報

本コードでは、凡例を下部に表示しています。

折れ線

<Line type="monotone" dataKey="val" name="東京" stroke="#8884d8" dot={false} />

Lineコンポーネントは、折れ線の描画を設定するものです。
折れ線の数を増やしたい場合は、このコンポーネントを増やしたい数分、置いてください。

Lineコンポーネントの属性(プロパティ)の意味は下記の通りです。

属性名 意味
type 折れ線のデザインを指定
たくさんあるので、直感的に良いと思ったものを選んでください。
https://recharts.org/en-US/api/Line
dataKey 折れ線で使用するデータのkey名を指定
name 折れ線の名称を指定
stroke 折れ線の色を指定。
カラーコード、又は、RGBで指定できます。
dot 折れ線に値に丸印のつけるかつけないかを指定。
デフォルトは表示、false指定で消せます。

Lineの属性情報

本コードでは、下記のように指定しています。
typeは、公式サンプルコードのデフォルトのままです。
dataKeyでは、折れ線に使用するプロパティとして、val(気温の値)を使いたいため、valを指定しています。
nameは、東京の気温と想定したので「東京」と指定しています。
strokeは、公式サンプルコードのデフォルトのままです。
dotは、データ数が多いと丸印だらけになるので、falseで消しています。

 

変換処理

const convert = (data) => {
    const result = data.map((d) => {
        return {
            time: moment(d.time).format("YYYY-MM-DD HH:mm:ss"),
            val: d.val
        }
    })
    result.sort((a, b) => a.time < b.time ? -1 : 1)
    return result
}

時系列データをグラフに渡す前に変換処理を作っています。

元々の時系列データの日時の値が、「YYYY-MM-DDTHH:mm:ss.sssZ」になっているので、
momentで、「YYYY-MM-DD HH:mm:ss」に変換しています。
変換した後は、日時に値を基に昇順にソートしています。

 

まとめ

  • Reactアプリでグラフを描画したい場合は、Rechartsを使用する。
  • 時系列データの折れ線グラフは、上記サンプルコードを参考にすればOK
  • グラフに渡すデータ形式に合わせて、時系列データを渡す必要がある
  • サンプルコードの内容は上記解説を参照すればOK

Reactで時系列データを折れ線グラフで描画したいときには、本記事が参考になれば幸いです。

以上です。
読んでくださった方ありがとうございました。

 

-React
-, , ,

© 2020 tako-xyz