Python {Article022}

ようこそ「Python」へ...

生データを使用してMatplotlibのSubplotsで複数のグラフを表示する方法を学ぶには【Pandas+Matplotlib】

ここではMatplotlibのsubplots()メソッドを使用してFigure内に複数のグラフを作成する方法を解説します。 suplots()メソッドを使用するとFigure内に1, 2, 4個といった異なるグラフを作成することができます。 初めにアンケートデータを使用してプログラミング言語ごとの給料のグラフをFigure内に複数作成します。 次に厚労省が公開しているCOVID-19のデータを使用して累計感染者、累計死亡者など異なるグラフをFigure内に4個作成します。 最後にGAFAの株価と仮想通貨(暗号通貨)の価格のグラフをFigure内に複数作成します。

ここではVisula Studio Code(VSC)の「Python Interactive window」 を使用してJupter(IPython Notebook)のような環境で説明します。 VSCを通常の環境からインタラクティブな環境に切り換えるにはコードを記述するときコメント「# %%」を入力します。 詳しい、操作手順については「ここ」 を参照してください。 インタラクティブな環境では、Pythonの「print(), plt.show()」などを使う必要がないので掲載しているコードでは省略しています。 VSCで通常の環境で使用するときは、必要に応じて「print(), plt.show()」等を追加してください。

この記事では、Pandas、Matplotlibのライブラリを使用しますので 「記事(Article001) | 記事(Article002) | 記事(Article003) | 記事(Article004)」 を参照して事前にインストールしておいてください。 Pythonのコードを入力するときにMicrosoftのVisula Studio Codeを使用します。 まだ、インストールしていないときは「記事(Article001)」を参照してインストールしておいてください。

説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。

click image to zoom!
Salaries by Age
click image to zoom!
COVID-19
click image to zoom!
GAFA Stock[1]
click image to zoom!
GAFA Stock[2]
click image to zoom!
GAFA Stock[3]
click image to zoom!
GAFA Stock[4]
click image to zoom!
Crypto Prices

プログラミング言語ごとの給料をFigure内に複数作成する

ここでは「stack overflow」が提供しているアンケートデータを加工して使用しています。 アンケートデータは「ここ」からダウンロードすることができます。 ダウンロードしたデータを加工する方法については別記事にて後日解説します。
  1. Matplotlibのsubplots()を使用しないでプログラミング言語ごとの給料の線グラフを作成する

    行4-5ではPythonのライブラリを取り込んでいます。 行8ではPandasのread_csv()メソッドでプログラミング言語別の給料データを取り込んでDataFrameに格納しています。 ここで取り込む給料データは「stack overflow」が公開しているアンケートデータを加工したものです。 行9-12では、DataFrameから「年齢」「全プログラミング言語の平均給料」「Python開発者の給料」「JavaScript開発者の給料」を取り込んで変数に格納しています。 行14ではMatplotlibのstyle_use()メソッドで「seaborn」のスタイルを設定しています。 スタイルの一覧は「style.availabel」を表示させることができます。 行15-17ではMatplotlibのplot()メソッドで線グラフを作成しています。 行19ではMatplotlibのlegend()メソッドで凡例を表示させています。 行20-22ではMatplotlibのtitle(), xlabel(), ylabel()メソッドでグラフのタイトル、X軸、Y軸のラベルを設定しています。 行23ではMatplotlibのtight_layout()メソッドでグラフが画面に収まるようにしています。 行24ではMatlotlibのshow(9メソッドでグラフを表示しています。
    # Article022_Matplotlib Subplots Part1.py
    # %%
    
    import pandas as pd
    from matplotlib import pyplot as plt
    
    # 1) Draw a line chart using plt
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    plt.plot(ages, py_salaries, label='Python')
    plt.plot(ages, js_salaries, label='JavaScript')
    plt.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    
    plt.legend()
    plt.title('Median Salary (USD) by Age')
    plt.xlabel('Ages')
    plt.ylabel('Median Salary (USD)')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図1
    図1は実行結果です。Figure内にプログラミング言語ごとの給料の線グラフが表示されています。 「All Devs」は「すべてのプログラミング言語の平均」の給料を意味します。
  2. Matplotlibのsubplots()メソッドを使用してプログラミング言語ごとの給料の線グラフをFigure内に1個作成する

    行9ではMatplotlibのsubplots()メソッドでfigureとsubplotのインスタンスを生成しています。 行11-13ではsubplotのplot()メソッドを使用して線グラフを作成しています。 行15-18では、subplotのlegend(), set_title(), set_xlabel(), set_ylabel()メソッドを使用して凡例、タイトル、X軸、Y軸のラベルを設定しています。 Matplotlibのlegend(), title(), xlabel(), ylabel()メソッドと異なるので注意してください。
    # 2) Draw a line chart using subplots()
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig, ax = plt.subplots()
    
    ax.plot(ages, py_salaries, label='Python')
    ax.plot(ages, js_salaries, label='JavaScript')
    ax.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    
    ax.legend()
    ax.set_title('Median Salary (USD) by Age')
    ax.set_xlabel('Ages')
    ax.set_ylabel('Median Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図2
    図2は実行結果です。図1のグラフと同じですが、ここではMatplotlibのsubplots()メソッドを使用してsubplotに線グラフを作成しています。 線グラフのタイトル、X軸、Y軸のラベル等はsubplot(ax)に対して設定しています。
  3. Matplotlibのsubplots()メソッドを使用してプログラミング言語ごとの給料の線グラフをFigure内に2個作成する

    行9ではMatplotlibのsubplots()メソッドでfigureと2個のsubplotのインスタンスを生成しています。 また、subplots()の引数に「sharex=True」を指定してX軸のxlabelとxticksを共有しています。
    # 3-1) nrow=2, col=1
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, sharex=True)
    
    ax1.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax2.plot(ages, py_salaries, label='Python')
    ax2.plot(ages, js_salaries, label='JavaScript')
    
    ax1.legend()
    ax1.set_title('Median Salary (USD) by Age')
    ax1.set_ylabel('Median Salary (USD)')
    
    ax2.legend()
    ax2.set_xlabel('Ages')
    ax2.set_ylabel('Median Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図3
    図3は実行結果です。Figure内に2個の線グラフが表示されています。 ここではX軸のxlabelとxticksを共有しています。
  4. Matplotlibのsubplots()メソッドを使用してプログラミング言語ごとの給料の線グラフをFigure内に4個作成する

    行9ではMatplotlibのsubplots()メソッドでfigureと4個のsubplotのインスタンスを生成しています。 また、subplots()の引数に「sharex=True」を指定してX軸のxlabelとxticksを共有しています。
    # 3-2) nrow=2, col=2
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, sharex=True)
    
    ax1.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax2.plot(ages, py_salaries, label='Python')
    ax3.plot(ages, js_salaries, label='JavaScript')
    ax4.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax4.plot(ages, py_salaries, label='Python')
    ax4.plot(ages, js_salaries, label='JavaScript')
    
    # Upper Left
    ax1.legend()
    ax1.set_title('All Devs Salary (USD) by Age')
    ax1.set_ylabel('All Devs Salary (USD)')
    
    # Upper Right
    ax2.legend()
    ax2.set_title('Python Salary (USD) by Age')
    ax2.set_ylabel('Python Salary (USD)')
    
    # Lower Left
    ax3.legend()
    ax3.set_title('JavaScript Salary (USD) by Age')
    ax3.set_xlabel('Ages')
    ax3.set_ylabel('JavaScript Salary (USD)')
    
    # Lower Right
    ax4.legend()
    ax4.set_title('Salary (USD) by Age')
    ax4.set_xlabel('Ages')
    ax4.set_ylabel('Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図4
    図4は実行結果です。Figure内に4個の線グラフが作成されています。 X軸のxlabelとxticksは共有しています。
  5. Matplotlibのsubplots()メソッドで2個のFigureを作成してそれぞれのFigure内に1個の線グラフを作成する

    行9-10ではMatplotlibのsubplots()メソッドで2個のfigureと2個のsubplotのインスタンスを生成しています。 行28-29ではfigureのsavefig()メソッドでグラフを保存しています。
    # 4) Draw line chart using different figures
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig1, ax1 = plt.subplots()
    fig2, ax2 = plt.subplots()
    
    ax1.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax2.plot(ages, py_salaries, label='Python')
    ax2.plot(ages, js_salaries, label='JavaScript')
    
    ax1.legend()
    ax1.set_title('All Devs Salary (USD) by Age')
    ax1.set_xlabel('Ages')
    ax1.set_ylabel('All Devs Salary (USD)')
    
    ax2.legend()
    ax2.set_title('Python/JavaScript Salary (USD) by Age')
    ax2.set_xlabel('Ages')
    ax2.set_ylabel('Python/JavaScript Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    fig1.savefig('data/png/article022/fig1.png')
    fig2.savefig('data/png/article022/fig2.png')
    click image to zoom!
    図5
    図5は実行結果です。2個のFigureにそれぞれ線グラフが作成されています。 ここではfigureのsavefig()メソッドを使用してそれぞれのFigureを保存しています。
  6. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Article022_Matplotlib Subplots Part1.py
    # %%
    
    import pandas as pd
    from matplotlib import pyplot as plt
    
    # 1) Draw a line chart using plt
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    plt.plot(ages, py_salaries, label='Python')
    plt.plot(ages, js_salaries, label='JavaScript')
    plt.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    
    plt.legend()
    plt.title('Median Salary (USD) by Age')
    plt.xlabel('Ages')
    plt.ylabel('Median Salary (USD)')
    plt.tight_layout()
    plt.show()
    
    # %%
    
    # 2) Draw a line chart using subplots()
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig, ax = plt.subplots()
    
    ax.plot(ages, py_salaries, label='Python')
    ax.plot(ages, js_salaries, label='JavaScript')
    ax.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    
    ax.legend()
    ax.set_title('Median Salary (USD) by Age')
    ax.set_xlabel('Ages')
    ax.set_ylabel('Median Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    
    # %%
    
    # 3) Draw line chart using subplots()  
    
    # 3-1) nrow=2, col=1
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, sharex=True)
    
    # using the variable ax for single a Axes
    # fig, ax = plt.subplots()
    # using the variable axs for multiple Axes
    # fig, axs = plt.subplots(2, 2)
    # using tuple unpacking for multiple Axes
    # fig, (ax1, ax2) = plt.subplots(1, 2)
    # fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
    
    ax1.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax2.plot(ages, py_salaries, label='Python')
    ax2.plot(ages, js_salaries, label='JavaScript')
    
    ax1.legend()
    ax1.set_title('Median Salary (USD) by Age')
    #ax1.set_xlabel('Ages')
    ax1.set_ylabel('Median Salary (USD)')
    
    ax2.legend()
    #ax2.set_title('Median Salary (USD) by Age')
    ax2.set_xlabel('Ages')
    ax2.set_ylabel('Median Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    
    # %%
    
    # 3-2) nrow=2, col=2
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, sharex=True)
    
    ax1.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax2.plot(ages, py_salaries, label='Python')
    ax3.plot(ages, js_salaries, label='JavaScript')
    ax4.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax4.plot(ages, py_salaries, label='Python')
    ax4.plot(ages, js_salaries, label='JavaScript')
    
    # Upper Left
    ax1.legend()
    ax1.set_title('All Devs Salary (USD) by Age')
    #ax1.set_xlabel('Ages')
    ax1.set_ylabel('All Devs Salary (USD)')
    
    # Upper Right
    ax2.legend()
    ax2.set_title('Python Salary (USD) by Age')
    #ax2.set_xlabel('Ages')
    ax2.set_ylabel('Python Salary (USD)')
    
    # Lower Left
    ax3.legend()
    ax3.set_title('JavaScript Salary (USD) by Age')
    ax3.set_xlabel('Ages')
    ax3.set_ylabel('JavaScript Salary (USD)')
    
    # Lower Right
    ax4.legend()
    ax4.set_title('Salary (USD) by Age')
    ax4.set_xlabel('Ages')
    ax4.set_ylabel('Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    
    # %%
    
    # 4) Draw line chart using different figures
    
    df = pd.read_csv('data/csv/article022/data.csv')
    ages = df['Age']
    dev_salaries = df['All_Devs']
    py_salaries = df['Python']
    js_salaries = df['JavaScript']
    
    plt.style.use('seaborn')
    fig1, ax1 = plt.subplots()
    fig2, ax2 = plt.subplots()
    
    ax1.plot(ages, dev_salaries, color='#444444', linestyle='--', label='All Devs')
    ax2.plot(ages, py_salaries, label='Python')
    ax2.plot(ages, js_salaries, label='JavaScript')
    
    ax1.legend()
    ax1.set_title('All Devs Salary (USD) by Age')
    ax1.set_xlabel('Ages')
    ax1.set_ylabel('All Devs Salary (USD)')
    
    ax2.legend()
    ax2.set_title('Python/JavaScript Salary (USD) by Age')
    ax2.set_xlabel('Ages')
    ax2.set_ylabel('Python/JavaScript Salary (USD)')
    
    plt.tight_layout()
    plt.show()
    fig1.savefig('data/png/article022/fig1.png')
    fig2.savefig('data/png/article022/fig2.png')
    
    # %%
    

COVID-19に関する各種グラフを作成して状況を分析する

ここではCOVID-19のデータを使用して累計発症者の積み上げ面グラフ、累計発症人の円グラフ、 累計発症者の水平棒グラフ、年齢別累計死亡者のヒストグラムを作成します。
  1. Matplotlibのstackplot()で累計発症者の積み上げ面グラフを作成する関数を定義する

    行5-14ではPythonのライブラリを取り込んでいます。 行15ではPythonの警告メッセージを抑止しています。 行18-79では累計感染者の積み上げ面グラフを作成する関数「plot_stack()」を定義しています。 積み上げ面グラフの解説については「記事(Article019)」を参照してください。
    # Article022_Matplotlib Subplots Part2 COVID-19.py
    # %%
    
    # Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # -------------------------------------------------------------------- Plot Stack
    def plot_stack(ax):     # plot stackplot(): Tokyo, Osaka, Aichi
        # 1) Load a csv file 
        csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined_v2.csv'   
        raw = pd.read_csv(csv_file, parse_dates=['date'])
    
        # 2) Create a modified CSV file  
        df = raw.copy()
        prefs = ['Tokyo','Osaka', 'Kyoto','Hyogo','Aichi', 'Saitama','Kanagawa','Chiba']
    
        for pref in prefs:
            filter_by =  filter_by = (df['prefecture'] == pref)     
            dfx = df[filter_by] 
            pref = pref.lower()
            dfx.rename(columns={
                'total_cases': f'total_cases_{pref}',
                'total_deaths': f'total_deaths_{pref}',
                'total_severe_cases': f'total_severe_cases_{pref}'
                }, inplace=True)
            dfx = dfx[['date', f'total_cases_{pref}', f'total_deaths_{pref}', f'total_severe_cases_{pref}']]
            dfx.set_index('date')
            if pref == 'tokyo':
                dfall = dfx
            else:    
                dfall = pd.merge(dfall, dfx)
    
        csv_file = 'data/csv/covid-19/japan/combined_v2(1).csv' 
        dfall.to_csv(csv_file, index=False)    
        df = dfall.copy()
    
        # 3) Draw a simple stack chart : new cases (tokyo, osaka, aichi)
    
        blue = '#008fd5'
        red = '#fc4f30'
        yellow = '#e5ae37'
        green = '#6d904f'
        colors = [red, blue, green]
    
        last_date = df['date'].max() 
        filter_by = (df['date'] == last_date)
        dfx = df[filter_by]
        tokyo_total_cases = dfx.total_cases_tokyo.values[0].round(0)
        osaka_total_cases = dfx.total_cases_osaka.values[0].round(0)
        aichi_total_cases = dfx.total_cases_aichi.values[0].round(0)
        labels = [
            f'東京({tokyo_total_cases:,})', 
            f'大阪({osaka_total_cases:,})', 
            f'愛知({aichi_total_cases:,})' 
        ]
    
        filter_by = (df['date'] >= '2020-07-01') 
        dfx = df[filter_by]  
        ax.stackplot(dfx.date, 
            dfx.total_cases_tokyo, dfx.total_cases_osaka, dfx.total_cases_aichi,
            labels=labels, colors=colors) 
       
        date_format = mpl_dates.DateFormatter('%Y/%m/%d')
        ax.xaxis.set_major_formatter(date_format)
        ax.margins(x=0)   
        plt.sca(ax)  # Use the pyplot interface to change just one subplot...  
        ax.set_ylabel('人数')
        ax.set_title('COVID-19 累計発症者 (東京/大阪/愛知)\n(2020-2021)')
        ax.legend(loc='upper left')
    click image to zoom!
    図6
    図6はVisual Studio Codeの画面です。plot_stack()関数では累計発症者の積み上げ面グラフを作成します。
  2. Matplotlibのpie()で累計発症人の円グラフを作成する関数を定義する

    行2-49では円グラフを作成する関数「plot_pie()」を定義しています。 円グラフの解説については「記事(Article013)」を参照してください。
    # -------------------------------------------------------------------- Plot Pie
    def plot_pie(ax):   # Plot pie (Tokyo, Osaka, Kanagawa, Saitama, Aichi)
        # 1) Load the csv file cases 
        csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined_v2.csv'
        raw = pd.read_csv(csv_file, parse_dates=['date'])
        df = raw.copy()   
        
        # 2) Draw a pie chart for new_cases
        # Get to see which prefectures have the most cases currently
        desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
        desc_prefs
        # Generate lables and values for the pie chart
        labels = []
        values = []
        pref_count = 5  
        other_total = 0
        for pref in desc_prefs.index:
            if pref_count > 0:
                labels.append(pref)
                values.append(desc_prefs[pref])
                pref_count -= 1
            else:
                other_total += desc_prefs[pref]
        labels.append("Other")
        values.append(other_total)
    
        wedge_dict = {
            'edgecolor': 'black', 
            'linewidth': 2    
        }
    
        explode = (0, 0, 0, 0.1, 0, 0)  
    
        ax.pie(
            values, 
            labels=labels, 
            explode=explode, 
            autopct='%1.1f%%', 
            textprops={'color':'black'},
            wedgeprops=wedge_dict)
    
        ax.set_title('COVID-19 累計発症者\n(上位5県)', color='black')
    
        ax.legend(
            fontsize=16,
            labels=['東京','大阪','神奈川','埼玉','愛知','その他'] ,   
            loc='center right',
            bbox_to_anchor=(1, 0, 0.5, 1)
        )
    click image to zoom!
    図7
    図7はVisual Studio Codeの画面です。plot_pie()関数では累計発症者の円グラフを作成します。
  3. Matplotlibのbarh()で累計発症者の水平棒グラフを作成する関数を定義する

    行2-28では水平棒グラフを作成する関数「plot_barh()」を定義しています。 棒グラフの解説については「記事(Article015)」を参照してください。
    # -------------------------------------------------------------------- Plot Bar(Horizontal)
    def plot_barh(ax):      # Plot Horizontal Bar Chart
        # 1) Load the csv files 
        csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined_v2.csv'
        raw = pd.read_csv(csv_file, parse_dates=['date'])    
        df = raw.copy()
    
        # Get to see which prefectures have the most cases currently
        last_date = df['date'].max()
        filter_by = (df['date'] == last_date)
        dfx = df[filter_by]
        dfx.sort_values(by='total_cases', ascending=False, inplace=True)
        dfx.reset_index(inplace=True)
        dfx.drop(dfx[dfx.index > 9].index, inplace=True)    # select top 10 prefectures
        dfx.sort_values(by='total_cases', ascending=True, inplace=True)
    
        total = dfx['total_cases'].sum()
        rows = dfx.shape[0] - 1
        for index, row in dfx.iterrows():
            ax.barh(row.prefecture, row.total_cases)
            if index == 0:  # first prefecture (Tokyo)
                ax.text(row.total_cases, rows - index, f'{row.total_cases:,}' + str(' ({:.1%})'.format(row.total_cases / total)), ha='right', fontsize=10)
            else:
                ax.text(row.total_cases, rows - index, f'{row.total_cases:,}' + str(' ({:.1%})'.format(row.total_cases / total)), fontsize=10)
    
        ax.set_ylabel('都道府県')
        ax.set_xlabel('累計発症者数')
        ax.set_title('COVID-19 累計発症者\n(上位10県)')
    click image to zoom!
    図8
    図8はVisual Studio Codeの画面です。plot_barh()関数では累計発症者の水平棒グラフを作成します。
  4. Matplotlibのhist()で年齢別累計死亡者のヒストグラムを作成する関数を定義する

    行2-27ではヒストグラムを作成する関数「plot_histogram()」を定義しています。 ヒストグラムの解説については「記事(Article020)」を参照してください。
    # -------------------------------------------------------------------- Plot Histogram
    def plot_histogram(ax):     # Plot Histogram(Total Deatys by Ages)
        # 1) Read the csv file 
        csv_file ='https://money-or-ikigai.com/menu/python/article/data/covid-19/COVID-19_modified(byages).csv'
        df = pd.read_csv(csv_file)
    
        # 2) Plo Histogram with colors : change the color of each bar based on its y value
        ages = df['age']
        bins = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    
        N, bins, patches = ax.hist(ages, bins=bins, edgecolor='black', log=True)
    
        fracs = N / N.max()
        norm = colors.Normalize(fracs.min(), fracs.max())
        for thisfrac, thispatch in zip(fracs, patches):
            color = plt.cm.viridis(norm(thisfrac))
            thispatch.set_facecolor(color)
    
        median_age = 75
        color = '#fc4f30'
    
        ax.axvline(median_age, color=color, label='中央値(75歳)', linewidth=2)
    
        ax.legend()
        ax.set_title('COVID-19 年齢別累計死亡者ヒストグラム\n(2021/10/4)')
        ax.set_xlabel('年齢')
        ax.set_ylabel('累計死亡者') 
    click image to zoom!
    図9
    図9はVisual Studio Codeの画面です。plot_histgram()関数では年齢別累計死亡者のヒストグラムを作成します。
  5. 関数を呼び出して積み上げ面グラフ、円グラフ、水平棒グラフ、ヒストグラムを作成する

    行2ではMatplotlibのsubplots()メソッドで4個のsubplotのインスタンスを生成しています。 行7,9,11,13では関数を呼び出して積み上げ面グラフ、水平棒グラフ、円グラフ、ヒストグラムを作成しています。 行15ではfigureのtight_layout()メソッドでグラフが画面に収まるようにしています。 行16ではMatplotlibのshow()メソッドでグラフを表示しています。
    plt.rcParams['font.family'] = 'Meiryo' 
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(18,9)) # width(6.4), height(4.8)
    #fig.set_figwidth(18)   # default 6.4
    #fig.set_figheight(9)   # default 4.8
    
    # Upper Left
    plot_stack(ax1)
    # Upper Right
    plot_barh(ax2)
    # Lower Left
    plot_pie(ax3)
    # Lower Right
    plot_histogram(ax4)
    
    fig.tight_layout()
    plt.show()
    click image to zoom!
    図10
    図10は実行結果です。Figure内に4種類のグラフが作成されています。
  6. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Article022_Matplotlib Subplots Part2 COVID-19.py
    # %%
    
    # Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # -------------------------------------------------------------------- Plot Stack
    def plot_stack(ax):     # plot stackplot(): Tokyo, Osaka, Aichi
        # 1) Load a csv file 
        csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined_v2.csv'        
        raw = pd.read_csv(csv_file, parse_dates=['date'])
    
        # 2) Create a modified CSV file  
        df = raw.copy()
        prefs = ['Tokyo','Osaka', 'Kyoto','Hyogo','Aichi', 'Saitama','Kanagawa','Chiba']
    
        for pref in prefs:
            filter_by =  filter_by = (df['prefecture'] == pref)     
            dfx = df[filter_by] 
            pref = pref.lower()
            dfx.rename(columns={
                'total_cases': f'total_cases_{pref}',
                'total_deaths': f'total_deaths_{pref}',
                'total_severe_cases': f'total_severe_cases_{pref}'
                }, inplace=True)
            dfx = dfx[['date', f'total_cases_{pref}', f'total_deaths_{pref}', f'total_severe_cases_{pref}']]
            dfx.set_index('date')
            if pref == 'tokyo':
                dfall = dfx
            else:    
                dfall = pd.merge(dfall, dfx)
    
        csv_file = 'data/csv/covid-19/japan/combined_v2(1).csv' 
        dfall.to_csv(csv_file, index=False)    
        df = dfall.copy()
    
        # 3) Draw a simple stack chart : new cases (tokyo, osaka, aichi)
    
        blue = '#008fd5'
        red = '#fc4f30'
        yellow = '#e5ae37'
        green = '#6d904f'
        colors = [red, blue, green]
    
        last_date = df['date'].max() 
        filter_by = (df['date'] == last_date)
        dfx = df[filter_by]
        tokyo_total_cases = dfx.total_cases_tokyo.values[0].round(0)
        osaka_total_cases = dfx.total_cases_osaka.values[0].round(0)
        aichi_total_cases = dfx.total_cases_aichi.values[0].round(0)
        labels = [
            f'東京({tokyo_total_cases:,})', 
            f'大阪({osaka_total_cases:,})', 
            f'愛知({aichi_total_cases:,})' 
        ]
    
        filter_by = (df['date'] >= '2020-07-01') 
        dfx = df[filter_by]  
        ax.stackplot(dfx.date, 
            dfx.total_cases_tokyo, dfx.total_cases_osaka, dfx.total_cases_aichi,
            labels=labels, colors=colors) 
        
        #fig.autofmt_xdate()    # DO NOT USE 
        date_format = mpl_dates.DateFormatter('%Y/%m/%d')
        ax.xaxis.set_major_formatter(date_format)
    
        ax.margins(x=0)   
        plt.sca(ax)  # Use the pyplot interface to change just one subplot... 
        ax.set_ylabel('人数')
        ax.set_title('COVID-19 累計発症者 (東京/大阪/愛知)\n(2020-2021)')
        ax.legend(loc='upper left')
       
    
    # -------------------------------------------------------------------- Plot Pie
    def plot_pie(ax):   # Plot pie (Tokyo, Osaka, Kanagawa, Saitama, Aichi)
        # 1) Load the csv file cases 
        csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined_v2.csv'
        raw = pd.read_csv(csv_file, parse_dates=['date'])
        df = raw.copy()   
        
        # 2) Draw a pie chart for new_cases
        # Get to see which prefectures have the most cases currently
        desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
        desc_prefs
        # Generate lables and values for the pie chart
        labels = []
        values = []
        pref_count = 5   # 5+1=6
        other_total = 0
        for pref in desc_prefs.index:
            if pref_count > 0:
                labels.append(pref)
                values.append(desc_prefs[pref])
                pref_count -= 1
            else:
                other_total += desc_prefs[pref]
        labels.append("Other")
        values.append(other_total)
    
        wedge_dict = {
            'edgecolor': 'black', 
            'linewidth': 2    
        }
    
        explode = (0, 0, 0, 0.1, 0, 0)  
    
        ax.pie(
            values, 
            labels=labels, 
            explode=explode, 
            autopct='%1.1f%%', 
            textprops={'color':'black'},
            wedgeprops=wedge_dict)
    
        ax.set_title('COVID-19 累計発症者\n(上位5県)', color='black')
    
        ax.legend(
            fontsize=16,
            labels=['東京','大阪','神奈川','埼玉','愛知','その他'] ,   
            loc='center right',
            bbox_to_anchor=(1, 0, 0.5, 1)
        )
         
    # -------------------------------------------------------------------- Plot Bar(Horizontal)
    def plot_barh(ax):      # Plot Horizontal Bar Chart
        # 1) Load the csv files 
        csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined_v2.csv'
        raw = pd.read_csv(csv_file, parse_dates=['date'])    
        df = raw.copy()
    
        # Get to see which prefectures have the most cases currently
        last_date = df['date'].max()
        filter_by = (df['date'] == last_date)
        dfx = df[filter_by]
        dfx.sort_values(by='total_cases', ascending=False, inplace=True)
        dfx.reset_index(inplace=True)
        dfx.drop(dfx[dfx.index > 9].index, inplace=True)    # select top 10 prefectures
        dfx.sort_values(by='total_cases', ascending=True, inplace=True)
    
        total = dfx['total_cases'].sum()
        rows = dfx.shape[0] - 1
        for index, row in dfx.iterrows():
            ax.barh(row.prefecture, row.total_cases)
            if index == 0:  # first prefecture (Tokyo)
                ax.text(row.total_cases, rows - index, f'{row.total_cases:,}' + str(' ({:.1%})'.format(row.total_cases / total)), ha='right', fontsize=10)
            else:
                ax.text(row.total_cases, rows - index, f'{row.total_cases:,}' + str(' ({:.1%})'.format(row.total_cases / total)), fontsize=10)
    
        ax.set_ylabel('都道府県')
        ax.set_xlabel('累計発症者数')
        ax.set_title('COVID-19 累計発症者\n(上位10県)')
    
    # -------------------------------------------------------------------- Plot Histogram
    def plot_histogram(ax):     # Plot Histogram(Total Deatys by Ages)
        # 1) Read the csv file 
        csv_file ='https://money-or-ikigai.com/menu/python/article/data/covid-19/COVID-19_modified(byages).csv'
        df = pd.read_csv(csv_file)
    
        # 2) Plo Histogram with colors : change the color of each bar based on its y value
        ages = df['age']
        bins = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    
        N, bins, patches = ax.hist(ages, bins=bins, edgecolor='black', log=True)
    
        fracs = N / N.max()
        norm = colors.Normalize(fracs.min(), fracs.max())
        for thisfrac, thispatch in zip(fracs, patches):
            color = plt.cm.viridis(norm(thisfrac))
            thispatch.set_facecolor(color)
    
        median_age = 75
        color = '#fc4f30'
    
        ax.axvline(median_age, color=color, label='中央値(75歳)', linewidth=2)
    
        ax.legend()
        ax.set_title('COVID-19 年齢別累計死亡者ヒストグラム\n(2021/10/4)')
        ax.set_xlabel('年齢')
        ax.set_ylabel('累計死亡者') 
     
    
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(18,9)) # width(6.4), height(4.8)
    #fig.set_figwidth(18)   # default 6.4
    #fig.set_figheight(9)   # default 4.8
    
    # Upper Left
    plot_stack(ax1)
    # Upper Right
    plot_barh(ax2)
    # Lower Left
    plot_pie(ax3)
    # Lower Right
    plot_histogram(ax4)
    
    fig.tight_layout()
    plt.show()
    

GAFAの株価の線グラフをFigure内に4個作成する

ここではYahoo!Financeの株価を取り込んでGAFAの株価をFigure内に4個作成します。 Yahoo!FianceからGAFAの株価を取り込むにはPandasのDataReaderを使用します。 Figure内に4個の線グラフを作成するにはMatplotlibのsubplots()メソッドで4個のsubplotを生成することにより実装します。
  1. Yahoo!FinanceからGAFAの株価を取り込む

    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()           # Remove Symbols and reset date index                  
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    click image to zoom!
    図11
    図11はVisual Studio Code(VSC)の画面です。右側のインタラクティブウィンドウから「df.info()」と「df.head(4)」を入力してDataFrameの情報を表示しています。
  2. 株価の線グラフを作成する関数「plot_line()」を定義する

    def plot_line(dfx, ax, symbol, color, price):  # plot line char for GAFA
        # Draw a line chart            
        label = symbols_mapping[symbol]
        labelx = label + f' (USD$ {price:,.2f})'
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'GAFA Stock Prices\n({label})')
        ax.legend(loc='upper left')
    click image to zoom!
    図12
    図12はVisual Studio Code(VSC)の画面です。
  3. Subplotを4個生成してFigure内に4個の線グラフを作成する

    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo' 
    plt.style.use('fivethirtyeight')       
    
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
        nrows=2, ncols=2, 
        sharex=True,
        figsize=(18,9)) # width(6.4), height(4.8)
    
    axs = [ax1, ax2, ax3, ax4]
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    # Draw a line chart for GAFA
    for i, symbol in enumerate(symbols):
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]    
        plot_line(dfx, axs[i], symbols[i], colors[i], price)              
     
    fig.tight_layout()
    plt.show()
    click image to zoom!
    図13-1
    図13-1はVisual Studio Code(VSC)の画面です。
    click image to zoom!
    図13-2
    図13-2はFigureを保存した画像です。Figure内に4個の線グラフが表示されています。
  4. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Article022_Matplotlib Subplots Part3 Stock(1).py
    # %%
    
    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()           # Remove Symbols and reset date index                  
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    
    # %%
    def plot_line(dfx, ax, symbol, color, price):  # plot line char for GAFA
        # Draw a line chart            
        label = symbols_mapping[symbol]
        labelx = label + f' (USD$ {price:,.2f})'
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'GAFA Stock Prices\n({label})')
        ax.legend(loc='upper left')
    
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')        # 'fivethirtyeight' 'ggplot'
    
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
        nrows=2, ncols=2, 
        sharex=True,
        figsize=(18,9)) # width(6.4), height(4.8)
    
    axs = [ax1, ax2, ax3, ax4]
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    # Draw a line chart for GAFA
    for i, symbol in enumerate(symbols):
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]    
        plot_line(dfx, axs[i], symbols[i], colors[i], price)              
     
    fig.tight_layout()
    plt.show()
    
    # %%
    
    

GAFAの株価, MA20/MA60, Median, Volumeの4種類のグラフをFigure内に表示する

ここではYahoo!FinanceからGAFAの株価を取り込んで株価、MA(移動平均)、Median(中央値)、Volume(取引高)の4種類のグラフをFigure内に表示します。 Yahoo!FianceからGAFAの株価を取り込むにはPandasのDataReaderを使用します。 Figure内に4個の線グラフを作成するにはMatplotlibのsubplots()メソッドで4個のsubplotを生成することにより実装します。
  1. Yahoo!FinanceからGAFAの株価を取り込む

    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()           # Remove Symbols and reset date index                  
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    click image to zoom!
    図14
    図14はVisual Studio Code(VSC)の画面です。 右側のインタラクティブウィンドウから「df.info()」と「df.head(4)」を入力してDataFrameの構造と内容を表示しています。
  2. GAFAの株価の線グラフを作成する関数「plot_line()」を定義する

    def plot_line(df, ax, symbol):  
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]      
        color = 'green'                
        symbolx = symbols_mapping[symbol]
        labelx = symbolx + f' (USD$ {price:,.2f})'
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx} Stock Price\n(2019 - 2021)')
        ax.legend(loc='upper left')
    click image to zoom!
    図15
    図15はVisual Studio Codeの画面です。
  3. GAFAのMA20/MA60(Moving Average:移動平均)の線グラフを作成する関数「plot_moving_average()」を定義する

    def plot_moving_averages(df, ax, symbol): 
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        dfx['MA20'] = dfx['Open'].rolling(20).mean()
        dfx['MA60'] = dfx['Open'].rolling(60).mean()
        symbolx = symbols_mapping[symbol]
    
        ax.plot(dfx.Date, dfx.Close, color='black', alpha=0.5, linewidth=1, label=symbolx)
        ax.plot(dfx.Date, dfx.MA20, color='red', linestyle='dashed', linewidth=2, label='MA20')  
        ax.plot(dfx.Date, dfx.MA60, color='blue', linestyle='dashed', linewidth=2, label='MA60')   
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)    
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx} Moving Averages [20,60] \n(2019 - 2021)')
        ax.legend(loc='best')
    click image to zoom!
    図16
    図16はVisual Studio Codeの画面です。
  4. GAFAのMedian(中央値)の線グラフを作成する関数「plot_line_filled()」を定義する

    def plot_line_filled(df, ax, symbol):  
        filter_by = (df['Symbols'] == symbol) & (df['Date'] > '2021-01-01')
        dfx = df[filter_by] 
        median = dfx.Close.median()
        median_Close = np.repeat(median, len(dfx.Close))
        symbolx = symbols_mapping[symbol]    
    
        ax.plot(dfx.Date, dfx.Close, linewidth=1)
        ax.plot(dfx.Date, median_Close, color='#444444', linestyle='dashed', linewidth=1, label='Median')  
    
        ax.fill_between(dfx.Date, dfx.Close, median_Close, 
            where=(dfx.Close > median_Close),
            interpolate=True,
            alpha=0.25, label='Above Median')
        ax.fill_between(dfx.Date, dfx.Close, median_Close, 
            where=(dfx.Close <= median_Close),
            interpolate=True,
            alpha=0.25, label='Below Median')    
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)  
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx} Median\n(2021)')
        ax.legend(loc='best')
    click image to zoom!
    図17
    図17はVisual Studio Codeの画面です。
  5. GAFAのVolume(取引高)の棒グラフを作成する関数「plot_volume()」を定義する

    def plot_volume(df, ax, symbol):  
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        symbolx = symbols_mapping[symbol]
        
        ax.bar(dfx.Date, dfx.Volume, label=symbolx)      
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45) 
        ax.set_ylabel('Volume')
        ax.set_title(f'{symbolx} Volume\n(2019 - 2021)')
        ax.legend(loc='upper left')
    click image to zoom!
    図18
    図18はVisual Studio Codeの画面です。
  6. Subplotを生成してFigure内に4種類のグラフを作成する

    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    plt.style.use('fivethirtyeight')       
    
    # Get symbols
    symbols = ['GOOGL','AMZN','FB','AAPL']
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
        nrows=2, ncols=2, 
        sharex=False,
        figsize=(18,9)) # width(6.4), height(4.8)
    
    axs = [ax1, ax2, ax3, ax4]
    
    # Plot 0-Google, 1-Amazon, 2-Facebook, 3-Apple
    i = 1
    plot_line(df, ax1, symbols[i])
    plot_line_filled(df, ax2, symbols[i]) 
    plot_moving_averages(df, ax3, symbols[i]) 
    plot_volume(df, ax4, symbols[i]) 
    
    fig.tight_layout()
    plt.show()
    click image to zoom!
    図19
    図19はVisual Studio Codeの画面です。 Figure内に4種類のグラフが表示されています。
  7. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Article022_Matplotlib Subplots Part3 Stock(2).py
    # Tip1: https://www.analyticsvidhya.com/blog/2021/07/stock-prices-analysis-with-python/
    # Tip2: https://www.machinelearningplus.com/plots/top-50-matplotlib-visualizations-the-master-plots-python/
    
    # %%
    
    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()           # Remove Symbols and reset date index                  
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    
    # ---------------------------------- Plot Price
    def plot_line(df, ax, symbol):  
    
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == symbol) & (df['Date'] > '2021-01-01')
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]      
        color = 'green'                
        symbolx = symbols_mapping[symbol]
        labelx = symbolx + f' (USD$ {price:,.2f})'
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx} Stock Price\n(2019 - 2021)')
        ax.legend(loc='upper left')
    
    # ---------------------------------- Plot Moving Averages
    def plot_moving_averages(df, ax, symbol):  
    
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == symbol) & (df['Date'] > '2021-01-01')
        dfx = df[filter_by] 
        dfx['MA20'] = dfx['Open'].rolling(20).mean()
        dfx['MA60'] = dfx['Open'].rolling(60).mean()
        symbolx = symbols_mapping[symbol]
    
        ax.plot(dfx.Date, dfx.Close, color='black', alpha=0.5, linewidth=1, label=symbolx)
        ax.plot(dfx.Date, dfx.MA20, color='red', linestyle='dashed', linewidth=2, label='MA20')  
        ax.plot(dfx.Date, dfx.MA60, color='blue', linestyle='dashed', linewidth=2, label='MA60')   
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)    
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx} Moving Averages [20,60] \n(2019 - 2021)')
        ax.legend(loc='best')
    
    # ---------------------------------- Plot Line filled between median
    def plot_line_filled(df, ax, symbol):  
    
        #filter_by = (df['Symbols'] == symbol)
        filter_by = (df['Symbols'] == symbol) & (df['Date'] > '2021-01-01')
        dfx = df[filter_by] 
        median = dfx.Close.median()
        median_Close = np.repeat(median, len(dfx.Close))
        symbolx = symbols_mapping[symbol]    
    
        ax.plot(dfx.Date, dfx.Close, linewidth=1)
        ax.plot(dfx.Date, median_Close, color='#444444', linestyle='dashed', linewidth=1, label='Median')  
    
        ax.fill_between(dfx.Date, dfx.Close, median_Close, 
            where=(dfx.Close > median_Close),
            interpolate=True,
            alpha=0.25, label='Above Median')
        ax.fill_between(dfx.Date, dfx.Close, median_Close, 
            where=(dfx.Close <= median_Close),
            interpolate=True,
            alpha=0.25, label='Below Median')    
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)  
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx} Median\n(2021)')
        ax.legend(loc='best')
       
    # ---------------------------------- Plot Volume
    def plot_volume(df, ax, symbol):  
    
        filter_by = (df['Symbols'] == symbol)
        # filter_by = (dfx['Symbols'] == symbol) & (dfx['Date'] > '2021-01-01')
        dfx = df[filter_by] 
        symbolx = symbols_mapping[symbol]
        
        ax.bar(dfx.Date, dfx.Volume, label=symbolx)      
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45) 
        ax.set_ylabel('Volume')
        ax.set_title(f'{symbolx} Volume\n(2019 - 2021)')
        ax.legend(loc='upper left') 
    
    # Main 
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    plt.style.use('fivethirtyeight')       
    
    # Get symbols
    symbols = ['GOOGL','AMZN','FB','AAPL']
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
        nrows=2, ncols=2, 
        sharex=False,
        figsize=(18,9)) # width(6.4), height(4.8)
    
    axs = [ax1, ax2, ax3, ax4]
    
    # Plot 0-Google, 1-Amazon, 2-Facebook, 3-Apple
    i = 1
    plot_line(df, ax1, symbols[i])
    plot_line_filled(df, ax2, symbols[i]) 
    plot_moving_averages(df, ax3, symbols[i]) 
    plot_volume(df, ax4, symbols[i]) 
    
    fig.tight_layout()
    plt.show()
    
    # %%
    

GAFAの株価, EXP12/EXP26, MACD/Signalの3種類のグラフをFigure内に表示する

NOTE:
MACD(マックディー)とは「Moving Average Convergence Divergence」の略で、移動平均線を応用したテクニカルチャートとして開発されました。 MACDは、MACDラインとシグナルラインの2本のラインを用いて相場を読む手法です。 長短2つの移動平均の差を1本のラインで表したMACDラインと、MACDラインの値をさらにある期間で平均したシグナルラインを組み合わせて売買のタイミングを計ります。 MACDチャートは、2本の線のみで表されるため、売買のサインが見やすく、使いやすいチャートのひとつです。

POINT:
MACDの見方のポイントは、(1)価格の変化に敏感なMACDラインが、変化に緩やかに反応するシグナルラインを下から上に突き抜けたときが買い、(2)MACDラインがシグナルラインを上から下に突き抜けたときが売り、の2つが売買のタイミングとして一般的によく用いられています。 もともと移動平均線をベースに開発されているため、読み方も似ている部分がありますが、誤差が少ないとされています。
  1. Yahoo!FinanceからGAFAの株価を取り込む

    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()           # Remove Symbols and reset date index                  
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    click image to zoom!
    図20
    図20はVisual Studio Codeの画面です。
  2. 株価の線グラフを作成する関数「plot_price()」を定義する

    def plot_price(df, ax, symbol):  
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]      
        color = 'green'                
        symbolx = symbols_mapping[symbol]
        labelx = symbolx + f' (USD$ {price:,.2f})'
    
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx}\n(Stock Price)')
        ax.legend(loc='upper left')
    click image to zoom!
    図21
    図21はVisual Studio Codeの画面です。
  3. EXP12/EXP26の線グラフを作成する関数「plot_EMA()」を定義する

    EXP: Exponential Moving Average
    def plot_EMA(df, ax, symbol):  
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        exp12 = dfx['Close'].ewm(span=12, adjust=False).mean()
        exp26 = dfx['Close'].ewm(span=26, adjust=False).mean()
        symbolx = symbols_mapping[symbol]
    
        ax.plot(dfx.Date, dfx.Close, color='black', alpha=0.5, linewidth=1, label=symbolx)
        ax.plot(dfx.Date, exp12, color='red', linestyle='dashed', linewidth=2, label='EXP12')  
        ax.plot(dfx.Date, exp26, color='blue', linestyle='dashed', linewidth=2, label='EXP26')   
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)    
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx}\n(Exponential Moving Averages)')
        ax.legend(loc='best')
    click image to zoom!
    図22
    図22はVisual Studio Codeの画面です。
  4. MACD/Signalの線グラフ(+Histogram)を作成する関数「plot_MACD()」を定義する

    MACD: Moving Average Convergence Divergence
    def plot_MACD(df, ax, symbol):  
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by]   
        exp12 = dfx['Close'].ewm(span=12, adjust=False).mean()
        exp26 = dfx['Close'].ewm(span=26, adjust=False).mean()
        macd = exp12 - exp26
        signal = macd.ewm(span=9, adjust=False).mean()
        histogram = macd - signal    
    
        symbolx = symbols_mapping[symbol]            
    
        ax.plot(dfx.Date, macd, color='black', alpha=0.7, linewidth=2, label='MACD (EXP12-EXP26)')
        ax.plot(dfx.Date, signal, color='red', linestyle='dashed', linewidth=2, label='Signal')   
        ax.bar(dfx.Date, histogram, color='dimgray', alpha=1) 
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)    
        ax.set_ylabel('MACD vs Signal')
        ax.set_title(f'{symbolx}\n(Moving Average Convergence Divergence)')
        ax.legend(loc='upper left') 
    click image to zoom!
    図23
    図23はVisual Studio Codeの画面です。
  5. 株価, EXP12/EXP26, MACD/Signalの3種類のグラフをFigure内に表示する

    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    plt.style.use('fivethirtyeight')       
    
    # Get symbols
    symbols = ['GOOGL','AMZN','FB','AAPL']
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    fig, (ax1, ax2, ax3) = plt.subplots(
        nrows=3, ncols=1, 
        sharex=True,
        figsize=(18,9)) # width(6.4), height(4.8)
    
    axs = [ax1, ax2, ax3]
    
    # Plot 0-Google, 1-Amazon, 2-Facebook, 3-Apple
    i = 1
    plot_price(df, ax1, symbols[i])
    plot_EMA(df, ax2, symbols[i]) 
    plot_MACD(df, ax3, symbols[i]) 
    
    fig.tight_layout()
    plt.show()
    click image to zoom!
    図24
    図24はFigure内に株価、EXP12/EXP26, MACD/Signalの3種類(+Histogram)のグラフが表示されている画像です。
  6. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Article022_Matplotlib Subplots Part3 Stock(3).py
    
    # %%
    
    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()           # Remove Symbols and reset date index                  
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    
    # ---------------------------------- Plot Stock Price
    def plot_price(df, ax, symbol):  
    
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == symbol) & (df['Date'] > '2021-01-01')
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]      
        color = 'green'                
        symbolx = symbols_mapping[symbol]
        labelx = symbolx + f' (USD$ {price:,.2f})'
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx}\n(Stock Price)')
        ax.legend(loc='upper left')
    
    # ---------------------------------- Plot EMA(exponential moving average) 12-EMA, 26-EMA
    def plot_EMA(df, ax, symbol):  
    
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == symbol) & (df['Date'] > '2021-01-01')
        dfx = df[filter_by] 
        exp12 = dfx['Close'].ewm(span=12, adjust=False).mean()
        exp26 = dfx['Close'].ewm(span=26, adjust=False).mean()
        symbolx = symbols_mapping[symbol]
    
        ax.plot(dfx.Date, dfx.Close, color='black', alpha=0.5, linewidth=1, label=symbolx)
        ax.plot(dfx.Date, exp12, color='red', linestyle='dashed', linewidth=2, label='EXP12')  
        ax.plot(dfx.Date, exp26, color='blue', linestyle='dashed', linewidth=2, label='EXP26')   
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)    
        ax.set_ylabel('Closing Price (USD)')
        ax.set_title(f'{symbolx}\n(Exponential Moving Averages)')
        ax.legend(loc='best')
    
    # ---------------------------------- Plot MACD(Moving Average Convergence Divergence)
    def plot_MACD(df, ax, symbol):  
    
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == symbol) & (df['Date'] > '2021-01-01')
        dfx = df[filter_by]   
        exp12 = dfx['Close'].ewm(span=12, adjust=False).mean()
        exp26 = dfx['Close'].ewm(span=26, adjust=False).mean()
        macd = exp12 - exp26
        signal = macd.ewm(span=9, adjust=False).mean()
        histogram = macd - signal    
    
        symbolx = symbols_mapping[symbol]            
        labelx = symbols_mapping[symbol]
    
        ax.plot(dfx.Date, macd, color='black', alpha=0.7, linewidth=2, label='MACD (EXP12-EXP26)')
        ax.plot(dfx.Date, signal, color='red', linestyle='dashed', linewidth=2, label='Signal')   
        ax.bar(dfx.Date, histogram, color='dimgray', alpha=1) 
    
        ax.margins(x=0) 
        ax.tick_params(labelrotation=45)    
        ax.set_ylabel('MACD vs Signal')
        ax.set_title(f'{symbolx}\n(Moving Average Convergence Divergence)')
        ax.legend(loc='upper left') 
       
    # Main 
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    plt.style.use('fivethirtyeight')       
    
    # Get symbols
    symbols = ['GOOGL','AMZN','FB','AAPL']
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    fig, (ax1, ax2, ax3) = plt.subplots(
        nrows=3, ncols=1, 
        sharex=True,
        figsize=(18,9)) # width(6.4), height(4.8)
    
    axs = [ax1, ax2, ax3]
    
    # Plot 0-Google, 1-Amazon, 2-Facebook, 3-Apple
    i = 1
    plot_price(df, ax1, symbols[i])
    plot_EMA(df, ax2, symbols[i]) 
    plot_MACD(df, ax3, symbols[i]) 
    
    fig.tight_layout()
    plt.show()
    
    # %%
    

GAFAのローソク足チャートにVolume, EXP12, EXP26, MACD, Signal, Histogramを追加して表示する

  1. Yahoo!FinanceからGAFAの株価を取り込む

    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()                        
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    df = df.set_index('Date')
    filter_by = (df.index >= '2021-05-01')   # 2021-05-01, 2021-08-01
    df = df[filter_by]
    click image to zoom!
    図25
    図25はVisual Studio Codeの画面です。
  2. EXP12, EXP26, MACD, Signal, Histogramを計算する

    symbols = ['GOOGL','AMZN','FB','AAPL']
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    # 0-Google, 1-Amazon, 2-Facebook, 3-Apple
    i=0 
    symbol = symbols[i]
    symbolx = symbols_mapping[symbol]
    
    filter_by = (df['Symbols'] == symbol)
    df = df[filter_by] 
    
    # Caluculate exp12, exp26, macd, signal, histogram
    exp12 = df['Close'].ewm(span=12, adjust=False).mean()
    exp26 = df['Close'].ewm(span=26, adjust=False).mean()
    macd = exp12 - exp26
    signal = macd.ewm(span=9, adjust=False).mean()
    histogram = macd - signal
    click image to zoom!
    図26
    図26はVisual Studio Codeの画面です。
  3. ローソク足チャートにVolume, EXP12, EXP26, MACD, Signal, Histogramを追加して表示する

    style = mpf.make_mpf_style(base_mpf_style='yahoo',rc={'figure.facecolor':'lightgray'})
    
    apds = [
        mpf.make_addplot(exp12,color='lime'),
        mpf.make_addplot(exp26,color='cyan'),
        mpf.make_addplot(histogram,type='bar',width=0.7,panel=1, color='dimgray',alpha=1,secondary_y=False),
        mpf.make_addplot(macd,panel=1,color='fuchsia',secondary_y=True),
        mpf.make_addplot(signal,panel=1,color='blue',secondary_y=True),
    ]
    
    mpf.plot(
        df,
        type='candle',
        addplot=apds,
        figscale=1.1,
        figratio=(8,5),
        title= f'\n{symbolx} Price in USD (2021)',
        style=style,
        datetime_format='%m/%d',  # '%Y/%m/%d', '%m/%d'
        volume=True,
        volume_panel=2,
        panel_ratios=(6,3,2)
    )
    
    mpf.show()
    click image to zoom!
    図27
    図27はmplfinanceのplot()メソッドでローソク足チャートを作成した画面です。 plot()の引数に「type='candle'」を指定しているのでローソク足チャートが表示されています。 さらに、引数「volume=True」を指定しているので取引高の棒グラフも表示されています。 引数「addplot=apds」ではmplfinanceのmake_addplot()メソッドで追加した5種類のグラフ(EXP12, EXP26, MACD, Signal, Histogram)を同時に表示しています。
  4. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Article022_Matplotlib Subplots Part3 Stock(8).py
    # %%
    
    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    df = df.stack().reset_index()                        
    csv_file = 'data/csv/article022/stock.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load stock data from the csv file
    csv_file = 'data/csv/article022/stock.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    df = df.set_index('Date')
    filter_by = (df.index >= '2021-05-01')   # 2021-05-01, 2021-08-01
    df = df[filter_by]
    
    # %%
    
    symbols = ['GOOGL','AMZN','FB','AAPL']
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    # 0-Google, 1-Amazon, 2-Facebook, 3-Apple
    i=0 
    symbol = symbols[i]
    symbolx = symbols_mapping[symbol]
    
    filter_by = (df['Symbols'] == symbol)
    df = df[filter_by] 
    
    # Caluculate exp12, exp26, macd, signal, histogram
    exp12 = df['Close'].ewm(span=12, adjust=False).mean()
    exp26 = df['Close'].ewm(span=26, adjust=False).mean()
    macd = exp12 - exp26
    signal = macd.ewm(span=9, adjust=False).mean()
    histogram = macd - signal
    
    # Draw a chart
    style = mpf.make_mpf_style(base_mpf_style='yahoo',rc={'figure.facecolor':'lightgray'})
    #style = mpf.make_mpf_style(base_mpf_style='classic',rc={'figure.facecolor':'lightgray'})
    
    apds = [
        mpf.make_addplot(exp12,color='lime'),
        mpf.make_addplot(exp26,color='cyan'),
        mpf.make_addplot(histogram,type='bar',width=0.7,panel=1, color='dimgray',alpha=1,secondary_y=False),
        mpf.make_addplot(macd,panel=1,color='fuchsia',secondary_y=True),
        mpf.make_addplot(signal,panel=1,color='blue',secondary_y=True),
    ]
    
    mpf.plot(
        df,
        type='candle',
        addplot=apds,
        figscale=1.1,
        figratio=(8,5),
        title= f'\n{symbolx} Price in USD (2021)',
        style=style,
        datetime_format='%m/%d',  # '%Y/%m/%d', '%m/%d'
        volume=True,
        volume_panel=2,
        panel_ratios=(6,3,2)
    )
    
    mpf.show()
    # %%
    

仮想通貨(暗号通貨)(BTC,ETC,ADA,XRP)の線グラフをFigure内に4個作成する

  1. Yahoo!Financeから仮想通貨(暗号通貨)の価格を取り込む

    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    crypto = ['BTC-JPY', 'ETC-JPY', 'ADA-JPY', 'XRP-JPY']
    df = web.DataReader(crypto, 'yahoo', start=start, end=end)
    df = df.stack().reset_index()        
    csv_file = 'data/csv/article022/crypto.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load crypto data from the csv file
    csv_file = 'data/csv/article022/crypto.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    click image to zoom!
    図28
    図28はVisual Studio Codeの画面です。
  2. 価格の線グラフを作成する関数「plot_line()」を定義する

    def plot_line(dfx, ax, symbol, color, price):  # plot line char for Crypto(BTC,ETC,ADA,XRP)
        # Draw a line chart            
        label = symbols_mapping[symbol]
        labelx = label + f' (\\{price:,.0f})'
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closeing Price (JPY)')
        ax.set_title(f'Cryptocurrency Prices\n({label})')
        ax.legend(loc='upper left')
    click image to zoom!
    図29
    図29はVisual Studio Codeの画面です。
  3. Subplotを4個生成してFigure内に4個の線グラフを作成する

    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    plt.style.use('fivethirtyeight')       
    
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
        nrows=2, ncols=2, 
        sharex=True,
        figsize=(18,9)) 
    
    axs = [ax1, ax2, ax3, ax4]
    
    symbols = ['BTC-JPY', 'ETC-JPY', 'ADA-JPY', 'XRP-JPY']
    symbols_mapping = {
        'BTC-JPY': 'Bitcoin', 
        'ETC-JPY': 'Ethereum', 
        'ADA-JPY': 'Cardano', 
        'XRP-JPY': 'Ripple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    # Draw a line chart for BTC, ETC, ADA, XRP
    for i, symbol in enumerate(symbols):
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]
        plot_line(dfx, axs[i], symbols[i], colors[i], price)            
    
    fig.tight_layout()
    plt.show()
    click image to zoom!
    図30
    図30はVisual Studio Codeの画面です。 Figure内に4個の線グラフが表示されています。
  4. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Article022_Matplotlib Subplots Part4 Crypto(1).py
    # %%
    
    # 0) Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import matplotlib.dates as mpl_dates
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    from matplotlib import colors
    from matplotlib.ticker import PercentFormatter
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Load Data from Yahoo Finace and Save it to a csv file
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    crypto = ['BTC-JPY', 'ETC-JPY', 'ADA-JPY', 'XRP-JPY']
    df = web.DataReader(crypto, 'yahoo', start=start, end=end)
    df = df.stack().reset_index()           # Remove Symbols and reset date index 
    csv_file = 'data/csv/article022/crypto.csv'
    df.to_csv(csv_file, index=False)
    
    # 2) Load crypto data from the csv file
    csv_file = 'data/csv/article022/crypto.csv'
    df = pd.read_csv(csv_file, parse_dates=['Date'])
    
    # %%
    def plot_line(dfx, ax, symbol, color, price):  # plot line char for Crypto(BTC,ETC,ADA,XRP)
        # Draw a line chart            
        label = symbols_mapping[symbol]
        labelx = label + f' (\\{price:,.0f})'
        ax.plot(dfx.Date, dfx.Close, color, label=labelx)  
    
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closeing Price (JPY)')
        ax.set_title(f'Cryptocurrency Prices\n({label})')
        ax.legend(loc='upper left')
    
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    plt.style.use('fivethirtyeight')       
    
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
        nrows=2, ncols=2, 
        sharex=True,
        figsize=(18,9)) 
    
    axs = [ax1, ax2, ax3, ax4]
    
    symbols = ['BTC-JPY', 'ETC-JPY', 'ADA-JPY', 'XRP-JPY']
    symbols_mapping = {
        'BTC-JPY': 'Bitcoin', 
        'ETC-JPY': 'Ethereum', 
        'ADA-JPY': 'Cardano', 
        'XRP-JPY': 'Ripple' 
    } 
    
    colors = ['-g','-c','-b','-r']
    # '-g'   # solid green
    # '--c') # dashed cyan
    # '-.b') # dashdot blue
    # ':r'); # dotted red
    
    # Draw a line chart for BTC, ETC, ADA, XRP
    for i, symbol in enumerate(symbols):
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by] 
        dfy = dfx.tail(1)
        price = dfy['Close'].values[0]
        plot_line(dfx, axs[i], symbols[i], colors[i], price)            
    
    fig.tight_layout()
    plt.show()
    
    # %%