時系列のためのカスタム目盛りフォーマッター

Beginner

This tutorial is from open-source community. Access the source code

はじめに

金融時系列などの日次データをプロットする際、週末などデータが存在しない日を省略したい場合がよくあります。これにより、データが存在しない日に余分なスペースを持たず、規則的な間隔でデータをプロットすることができます。この実験では、「インデックスフォーマッター」を使用して目的のプロットを実現する方法を学びます。

VM のヒント

VM の起動が完了した後、画面の左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。

Jupyter Notebook の読み込みには数秒かかる場合があります。Jupyter Notebook の制限により、操作の検証は自動化できません。

学習中に問題がある場合は、Labby にお問い合わせください。セッション終了後にフィードバックを提供してください。すぐに問題を解決いたします。

必要なライブラリとデータのインポート

まず、必要なライブラリであるmatplotlibnumpy、およびmatplotlib.cbookをインポートする必要があります。また、mpl-data/sample_dataディレクトリから、日付、始値、高値、安値、終値、出来高、調整後終値のフィールドを持つ yahoo csv データから numpy レコード配列を読み込む必要があります。レコード配列は、日付列に日単位 ('D') の np.datetime64 として日付を格納します。このデータを使って金融時系列をプロットします。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cbook as cbook

## Load data from sample_data directory
r = cbook.get_sample_data('goog.npz')['price_data'].view(np.recarray)
r = r[:9]  ## get the first 9 days

週末にデフォルトのギャップがあるデータのプロット

まず、matplotlib のplot関数を使って、週末にデフォルトのギャップがあるデータをプロットします。また、日次データのギャップを白い点線で強調表示します。

## Plot data with gaps on weekends
fig, ax1 = plt.subplots(figsize=(6, 3))
ax1.plot(r.date, r.adj_close, 'o-')

## Highlight gaps in daily data
gaps = np.flatnonzero(np.diff(r.date) > np.timedelta64(1, 'D'))
for gap in r[['date', 'adj_close']][np.stack((gaps, gaps + 1)).T]:
    ax1.plot(gap.date, gap.adj_close, 'w--', lw=2)
ax1.legend(handles=[ml.Line2D([], [], ls='--', label='Gaps in daily data')])

ax1.set_title("Plotting Data with Default Gaps on Weekends")
ax1.xaxis.set_major_locator(DayLocator())
ax1.xaxis.set_major_formatter(DateFormatter('%a'))

カスタムインデックスフォーマッターの作成

データを 0、1、... len(data) までのインデックスに対してプロットするために、カスタムインデックスフォーマッターを作成します。このフォーマッターは、目盛りを整数ではなく日付にフォーマットします。

## Create custom index formatter
fig, ax2 = plt.subplots(figsize=(6, 3))
ax2.plot(r.adj_close, 'o-')

## Format x-axis as times
def format_date(x, _):
    try:
        ## convert datetime64 to datetime, and use datetime's strftime:
        return r.date[round(x)].item().strftime('%a')
    except IndexError:
        pass

ax2.set_title("Creating Custom Index Formatter")
ax2.xaxis.set_major_formatter(format_date)  ## internally creates FuncFormatter

フォーマッターにコール可能オブジェクトを使用する

.Axis.set_major_formatter に関数を渡す代わりに、__call__ を実装するクラスのインスタンスなど、他のコール可能オブジェクトを使用することができます。このステップでは、目盛りを日付にフォーマットする MyFormatter クラスを作成します。

## Use a callable for formatter
class MyFormatter(Formatter):
    def __init__(self, dates, fmt='%a'):
        self.dates = dates
        self.fmt = fmt

    def __call__(self, x, pos=0):
        """Return the label for time x at position pos."""
        try:
            return self.dates[round(x)].item().strftime(self.fmt)
        except IndexError:
            pass

ax2.xaxis.set_major_formatter(MyFormatter(r.date, '%a'))

グラフの表示

ここでは、matplotlib のshow関数を使ってグラフを表示します。

plt.show()

まとめ

この実験では、週末にギャップのない金融時系列をプロットするためにカスタムインデックスフォーマッターをどのように使用するかを学びました。また、関数の代わりにフォーマッターにコール可能オブジェクトをどのように使用するかも学びました。これらの技術を使うことで、日次データのより視覚的に魅力的なプロットを作成できます。