時系列プロットはじめました〜python編〜

# はじめに
この記事は[MicroAd Advent Calendar 2019](https://qiita.com/advent-calendar/2019/microad)の22日目の記事です。

# やりたいこと
ログデータを可視化するときに、時系列プロットは非常に有用な手段です。
今までは横軸の日付を適当に数字で置き換えてプロットして逃げてきた、そんな人生を送ってきました。
しかし今は違います。横軸を時系列にして、上手にプロットできるようになったのです！
ということで、その話を備忘録としてまとめたいと思います。
なおここで作成したグラフは**最低限**のオプションしか使用しておりません。

# 方法
`matplotlib.dates` を使うといい感じでプロットできます。
コード例を以下に挙げます。

## 日毎
```python
import io
import pandas as pd
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()


def main():
    data = """date,value
    2018-12-01,15
    2018-12-02,30
    2018-12-03,25
    2018-12-04,18
    2018-12-05,9
    2018-12-06,22
    2018-12-07,34
    2018-12-08,33
    2018-12-09,28
    2018-12-10,22
    2018-12-11,26
    2018-12-12,31"""
    df = pd.read_csv(io.StringIO(data), parse_dates=[0])

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.plot(df['date'], df['value'])

    ##以下をカスタマイズする
    daysFmt = mdates.DateFormatter('%Y-%m-%d')
    ax.xaxis.set_major_formatter(daysFmt)
    fig.autofmt_xdate()

    plt.show()


if __name__ == '__main__':
    main()
```
このコードで出来上がった図は以下の通りです。
![qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317873/55f347c7-6cab-e297-58df-3662e1e64e8b.png)

ちょっと表示方法を変えてみるときは、

```python
    daysFmt = mdates.DateFormatter('%Y-%m-%d')
```
ここをいじれば大丈夫です。

```python
    daysFmt = mdates.DateFormatter('%m/%d')
```
上記のように変えると、x軸のラベルは以下のように表示されます。
![qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317873/f697d312-4705-f2b2-833e-730fd729ab9b.png)

## 日時毎
データをちょっと変えて日時毎にやってみます。

```python

import io
import pandas as pd
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()


def main():
    data = """date,value
        2018-12-01 00,15
        2018-12-01 01,30
        2018-12-01 02,25
        2018-12-01 03,18
        2018-12-01 04,9
        2018-12-01 05,22
        2018-12-01 06,34
        2018-12-01 07,33
        2018-12-01 08,28
        2018-12-01 09,22
        2018-12-01 10,26
        2018-12-01 11,31"""
    df = pd.read_csv(io.StringIO(data), parse_dates=[0])

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.plot(df['date'], df['value'])

    ##以下をカスタマイズする
    daysFmt = mdates.DateFormatter('%m/%d %H:%M')
    ax.xaxis.set_major_formatter(daysFmt)
    fig.autofmt_xdate()

    plt.show()


if __name__ == '__main__':
    main()
```
得られた図は以下の通り。
![qiita3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317873/338b7a44-610d-be5e-6190-d9c2ad91da50.png)

## 目盛りの頻度変更
目盛りの頻度を変えたい場合には、以下の二行を付け加えます。

```python
    daysLoc = mdates.HourLocator(byhour=None, interval=3, tz=None)
    ax.xaxis.set_major_locator(daysLoc)
```

これで目盛りの頻度が変わります。
![qiita4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317873/ee27238e-e0b7-a613-a854-38d6602547a5.png)
随分寂しい図になってしまいました。
今回は`interval`で設定しましたが、`interval`オプションを削除して`byhour=range(2, 12, 3)`で設定しても全く同じ結果を得ることができます。
ここで使用した`HourLocater`以外にも`MonthLocator, WeekdayLocator, DayLocator, MonthLocator, MinuteLocator, SecondLocator`などたくさんあるそうです。

## 軸ラベルの回転
軸ラベルが長すぎてはみ出してしまう！という場合には回転させることができます。
以下の二行を付け加えることでそれが可能です。

```python
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=45)
```
得られた図はこの通り。
![qiita5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317873/01272d44-b792-9a8b-6063-8cbf71b359e1.png)
確かにラベルの角度が代わっていることが確認できます。

# 最後に
自分が時系列プロットする際に必要だった**最低限**のオプションをまとめました。
状況に応じてもっと分かりやすいグラフを作成してください！
可視化ができたので、次は時系列解析ですね...

# 参考資料
[matplotlib.dates(公式ドキュメント)](https://matplotlib.org/3.1.1/api/dates_api.html)
[matplotlibで時系列データをプロットする際の軸の設定＋おまけ](https://qiita.com/ground0state/items/c6f0b0923ecb29103e42)
[Python matplotlib 時系列グラフ（時間軸の設定）](https://qiita.com/damyarou/items/19f19658b618fd05b3b6)
[matplotlib.datesで時系列データのグラフの軸目盛の設定をする]
(https://bunseki-train.com/setting_ticks_by_matplotlib_dates/)