Python {Article014}

ようこそ「Python」へ...

生データを使用してMatplotlibでグラフ(線グラフ)を作成する方法を学ぶには【Pandas+Matplotlib】

ここではWebサイトで公開されて生データを使用してPandas+Matplotlibで線グラフを作成する方法を解説します。 最初に厚労省のWebサイトからCOVID-19のデータをダウンロードしてMatplotlibで線グラフを作成する方法を説明します。 次に、Yahoo! FinanceからGAFAの株価をダウンロードして線グラフを作成する方法も説明します。 最後に、Yahoo! Financeから仮想通貨(暗号通貨)のビットコイン、イーサリアム等の価格をダウンロードして線グラフを作成する方法も説明します。 株価と仮想通貨(暗号通貨)についてはMplfinanceを使用してロウソク足チャートを作成する方法についても説明します。

厚労省のWebサイトからCOVIC-19のデータをダウンロードするにはPandasのread_csv()メソッドを使用します。 read_csv()の引数にCSVファイルのURLを指定すると手動でダウンロードすることなく完全に自動化できます。 なお、COVIC-19のデータは「記事(Article013)」で作成しています。 事前に「記事(Article013)」で解説している手順でCSVファイルを作成しておいてください。

Yahoo! FinanceのWebサイトから株価や仮想通貨(暗号通貨)の価格をダウンロードするにはPandasのDataReaderを使用します。 DataReader()で株価をダウンロードするには引数に企業のティッカーシンボル(Apple▶AAPL)、開始日、終了日を指定します。

Yahoo! FinanceのWebサイトから仮想通貨(暗号通貨)の価格をダウンロードする場合も株価と同様PandasのDataReaderを使用します。 ビットコインの価格をダウンロードするにはDataReader()の引数に「BTC-JPY」「BTC-USD」のように指定します。 つまり、日本円に換算するときは「BTC-JPY」、米ドルに換算するときは「BTC-USD」のように指定します。 株価も仮想通貨(暗号通貨)の価格をダウンロードするのも完全に自動化できますので手動でダウンロードする必要はありません。

ここでは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!
Article Summary 目次
click image to zoom!
COVID-19[1] 累計感染者
click image to zoom!
COVID-19[2] 曜日別感染者
click image to zoom!
COVID-19[3]累計重症者
click image to zoom!
COVID-19[4]累計死亡者
click image to zoom!
COVID-19[5]曜日別死亡者
click image to zoom!
GAFA Stock
click image to zoom!
Amazon Stock
click image to zoom!
Crypto
click image to zoom!
Bitcoin
click image to zoom!
Binance Crypto
click image to zoom!
Stock Line chart
click image to zoom!
Stock Candlestick chart
click image to zoom!
Stock Fill area chart
click image to zoom!
Stock Stacked bar chart
click image to zoom!
Crypto Line chart
click image to zoom!
Crypto Candlestick chart
click image to zoom!
Crypto Fill area chart
click image to zoom!
Crypto Stacked bar chart
click image to zoom!
Difference Between Exchanges
click image to zoom!
Real Time Line chart


◆まずは簡単な線グラフを作成してみる

  1. Pythonのプラグラム内で用意したデータを使って簡単な線グラフを作成する

    Visual Studio Codeを起動したら以下のコードを入力して実行[Ctrl+Enter]します。 行2-8ではPythonのライブラリを取り込んでいます。 行9では警告メッセージが表示されないように抑止しています。 行13ではmatplotlibで日本語が使えるように日本語のフォント「Meiryo」を設定しています。 行15-16では線グラフのX軸、Y軸の値を定義しています。 行18ではmatplotlibのplot()メソッドで線グラフを作成しています。 行21のコメント「# %%」を入力してインタラクティブ環境に切り換えることを忘れないでください。
    # 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 numpy as np
    import warnings
    warnings.simplefilter('ignore')  
    
    # Draw a single line chart (Tokyo)
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    
    plt.plot(date_x, tokyo_y)
    
    plt.show()
    click image to zoom!
    図1
    図1は実行結果です。matplotlibはX軸、Y軸の値を指定するだけで簡単に線グラフが作成できます。
  2. 線グラフにオプションを追加する

    行6ではmatplotlibのfigure()メソッドで図のサイズを設定しています。 行10ではX軸のラベル(日付)が斜めに表示されるようにしています。 行12ではY軸のラベルを設定しています。 行13ではグラフのタイトルを設定しています。 行14では凡例「東京」が中央の左端に表示されるように設定しています。
    #Add options (figsize, xticks, label, ylabel, title, legend)
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    
    plt.figure(figsize=(12,5))
    
    plt.plot(date_x, tokyo_y, label='東京')
    
    plt.xticks(rotation=45)
    #plt.xlabel('日付(年/月)')
    plt.ylabel('感染者数')
    plt.title('COVID-19 新規感染者')
    plt.legend(loc='upper left')
    plt.show()
    click image to zoom!
    図2
    図2は実行結果です。線グラフにタイトル、凡例、Y軸のラベルが表示されています。 また、X軸の日付が斜めに表示されています。
  3. 3本の線グラフを作成する

    行6-7では大阪と埼玉のY軸の値を追加しています。 行12-13では大阪と埼玉の線グラフを作成しています。 行19ではmatplotlibのgrid()メソッドでグラフにグリッドを追加しています。 行20ではmatplotlibのtight_layout()メソッドでNOTE-PCなどを使用した場合にもグラフが綺麗に表示されるようにしています。
    # Add osaka, saitama
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    osaka_y = [80,100,110,230,290,220,150,300,280]
    saitama_y = [70,100,200,250,260,200,150,330,280]
    
    plt.figure(figsize=(12,5))
    
    plt.plot(date_x, tokyo_y, label='東京')
    plt.plot(date_x, osaka_y, label='大阪')
    plt.plot(date_x, saitama_y, label='埼玉')
    
    plt.xticks(rotation=45)
    plt.ylabel('感染者数')
    plt.title('COVID-19 新規感染者')
    plt.legend(loc='upper left')
    plt.grid(True)
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図3
    図3は実行結果です。線グラフに大阪と埼玉が追加されました。 さらに図にグリッドが表示されています。
  4. 線グラフにスタイルを適用する

    行3ではmatplotlibのstyle.use()メソッドでスタイル「fivethirtyeight」を適用させています。 図を保存するときは行21のコメントを外してください。
    # Add style
    
    plt.style.use('fivethirtyeight')    # plt.style.available
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    osaka_y = [80,100,110,230,290,220,150,300,280]
    saitama_y = [70,100,200,250,260,200,150,330,280]
    
    plt.figure(figsize=(12,5))
    
    plt.plot(date_x, tokyo_y, label='東京')
    plt.plot(date_x, osaka_y, label='大阪')
    plt.plot(date_x, saitama_y, label='埼玉')
    
    plt.xticks(rotation=45)
    plt.ylabel('感染者数')
    plt.title('COVID-19 新規感染者')
    plt.legend(loc='upper left')
    plt.tight_layout()
    #plt.savefig('plot.png')
    plt.show()
    click image to zoom!
    図4-1
    図4-1は実行結果です。線グラフに「fivethirtyeight」のスタイルが適用されました。 スタイルの一覧を表示するにはインタラクティブ・ウィンドウから「plt.style.available」を入力します。
    click image to zoom!
    図4-2
    図4-2は「plt.style.available」の実行結果です。 スタイルを「'ggplot'」などに変更して色々試してみてください。
  5. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Mapplotlib Line Chart Part1
    # %%
    # 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 numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    
    # Draw single line chart (Tokyo)
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    
    plt.plot(date_x, tokyo_y)
    
    plt.show()
    # %%
    
    # Add figsize, xticks, label, ylabel, title, legend
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    
    plt.figure(figsize=(12,5))
    plt.plot(date_x, tokyo_y, label='東京')
    plt.xticks(rotation=45)
    #plt.xlabel('日付(年/月)')
    plt.ylabel('感染者数')
    plt.title('COVID-19 新規感染者')
    plt.legend(loc='upper left')
    plt.show()
    # %%
    
    # Add osaka, saitama
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    osaka_y = [80,100,110,230,290,220,150,300,280]
    saitama_y = [70,100,200,250,260,200,150,330,280]
    
    plt.figure(figsize=(12,5))
    
    plt.plot(date_x, tokyo_y, label='東京')
    plt.plot(date_x, osaka_y, label='大阪')
    plt.plot(date_x, saitama_y, label='埼玉')
    
    plt.xticks(rotation=45)
    #plt.xlabel('日付(年/月)')
    plt.ylabel('感染者数')
    plt.title('COVID-19 新規感染者')
    plt.legend(loc='upper left')
    plt.grid(True)
    plt.tight_layout()
    plt.show()
    # %%
    
    # Add style
    
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    #plt.style.use('ggplot')    # 'fivethirtyeight' 'ggplot'
    
    date_x = ['2021/1','2021/2','2021/3','2021/4','2021/5','2021/6','2021/7','2021/8','2021/9']
    tokyo_y = [100,120,130,250,300,250,180,350,300]
    osaka_y = [80,100,110,230,290,220,150,300,280]
    saitama_y = [70,100,200,250,260,200,150,330,280]
    
    plt.figure(figsize=(12,5))
    
    plt.plot(date_x, tokyo_y, label='東京')
    plt.plot(date_x, osaka_y, label='大阪')
    plt.plot(date_x, saitama_y, label='埼玉')
    
    plt.xticks(rotation=45)
    #plt.xlabel('日付(年/月)')
    plt.ylabel('感染者数')
    plt.title('COVID-19 新規感染者')
    plt.legend(loc='upper left')
    plt.tight_layout()
    #plt.savefig('plot.png')
    plt.show()
    
    # %%
    

◆COVID-19(新型コロナ)の生データを使って線グラフを作成する

  1. COVID-19のCSVファイルを取り込む

    ここで使用するCSVファイル「combined.csv」は、 「 記事(Article013)」で作成しています。 「記事(Article013)」を参考に事前にCSVファイルを作成しておいてください。 ちなみに、COVID-19のデータは厚労省のWebサイトからURLを指定してダウンロードするので完全に自動化できます。

    NOTE: COVID-19のCSVデータを当サイトから直接ダウンロードするには?
    COVID-19のCSVファイル「combined.csv」を当サイトから直接ダウンロードするには行12をコメントにして行13のコメントを外してください。 これで記事(Article013)で作成したCSVファイルを当サイトからダウンロードすることができます。 このCSVファイルは2021/9/19に作成したものになります。最新のデータを使うには 「 記事(Article013)」を参考に作成してください。

    行2-8ではPythonのライブラリを取り込んでいます。 行9ではPythonの警告メッセージを抑止しています。 行12ではCOVID-19のCSVファイルのパスを定義しています。 CSVファイルのパスはご自分の環境にあわせて書き換えてください。 当サイトから取り込むときは行12をコメントにして行13のコメントを外してください。 行14ではPandasのread_csv()メソッドでCOVID-19のデータを取り込んでDataFrameに格納しています。 行17ではPandasのto_datetime()メソッドで DataFrameの列「date」をstr型からdatetime64型に変更しています。
    # 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 numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # Load the csv files 
    csv_file = 'data/csv/covid-19/japan/combined.csv'
    #csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined.csv'
    raw = pd.read_csv(csv_file) 
    
    # Convert str to datetime
    raw['date'] = pd.to_datetime(raw['date'])
    click image to zoom!
    図5
    図5はPandasのread_csv()メソッドでCOVID-19のCSVファイルを取り込んでDataFrameに格納した内容を表示しています。 ここでは、raw.info()メソッドでDataFrameの件数、列名等を表示しています。 raw.head(1)ではDataFrameの先頭行(レコード)を表示しています。
  2. 日別感染者の線グラフを作成する

    # Plot line chart for new_cases : 日別感染者 線グラフ
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_cases
    filter_by = (raw['file_id'] == 'new_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    kens = ['東京','大阪','神奈川']
    
    for pref in prefs:
        #filter_by = (df['prefecture'] == pref)
        filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]     
        grp = dfx.groupby('date')['new_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)    
    
    plt.xticks(rotation=45)
    plt.ylabel('感染者数')
    plt.title('COVID-19 日別感染者\n(2020/3 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図6
    図6はMatplotlibのplot()メソッドで線グラフを作成したときの画面です。 東京、大阪、神奈川の線グラフが表示されています。
  3. 累計感染者の線グラフを作成する

    # Plot a line chart for total_cases 累計感染者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_cases
    filter_by = (raw['file_id'] == 'new_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['東京','大阪','神奈川']
    kens_values = []
    for val in desc_prefs.values:
        kens_values.append(f'{kens.pop(0)}({str(int(val))})')
        if len(kens) == 0:
            break
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)  
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01')
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_cases'] = dfx['new_cases'] .cumsum()   
        grp = dfx.groupby('date')['total_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens_values.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('感染者数')
    plt.title('COVID-19 累計感染者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図7
    図7はMatplotlibのplot()メソッドで東京、大阪、神奈川の累計感染者の線グラフを作成している画面です。
  4. 曜日別感染者の線グラフを作成する

    # Plot line chart for new_cases by day of week 曜日別感染者 線グラフ
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_cases
    filter_by = (raw['file_id'] == 'new_cases')
    df = raw[filter_by]
    
    # Add a day of week
    df['day_of_week'] = df['date'].dt.dayofweek
    day_of_week  = ['月','火','水','木','金','土','日']
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    kens = ['東京','大阪','神奈川']
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]     
        grp = dfx.groupby('day_of_week')['new_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)         
    
    plt.xticks(grp.index, day_of_week)
    plt.ylabel('感染者数')
    plt.title('COVID-19 曜日別感染者\n(2020/1 - 2021/9)')
    plt.legend(loc='center right')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図8
    図8はMatplotlibのplot()メソッドで東京、大阪、神奈川の曜日別感染者の線グラフを作成している画面です。
  5. 日別重症者の線グラフを作成する

    # Plot a line chart severe_cases : 日別重症者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_severe_cases
    filter_by = (raw['file_id'] == 'new_severe_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most severe cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','神奈川']
    
    for pref in prefs:
        #filter_by = (df['prefecture'] == pref)
        filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by ]
        grp = dfx.groupby('date')['severe_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('重症者数')
    plt.title('COVID-19 日別重症者\n(2021/3 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図9
    図9はMatplotlibのplot()メソッドで東京、大阪、神奈川の日別重症者の線グラフを作成している画面です。
  6. 累計重症者の線グラフを作成する

    # Plot a line chart total_severe_cases : 累計重症者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_severe_cases
    filter_by = (raw['file_id'] == 'new_severe_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most severe cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','神奈川']
    kens_values = []
    for val in desc_prefs.values:
        kens_values.append(f'{kens.pop(0)}({str(int(val))})')
        if len(kens) == 0:
            break
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_severe_cases'] = dfx['severe_cases'] .cumsum()  
        grp = dfx.groupby('date')['total_severe_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens_values.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('重症者数')
    plt.title('COVID-19 累計重症者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図10
    図10はMatplotlibのplot()メソッドで東京、大阪、神奈川の累計重症者の線グラフを作成している画面です。
  7. 曜日別重症者の線グラフを作成する

    # Plot line chart for severe_cases by day of week : 曜日別重症者 線グラフ
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_server_cases
    filter_by = (raw['file_id'] == 'new_severe_cases')
    df = raw[filter_by]
    
    # Add a day of week
    df['day_of_week'] = df['date'].dt.dayofweek
    day_of_week  = ['月','火','水','木','金','土','日']
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    kens = ['大阪','東京','神奈川']
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]     
        grp = dfx.groupby('day_of_week')['severe_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)         
    
    plt.xticks(grp.index, day_of_week)
    plt.ylabel('重症者数')
    plt.title('COVID-19 曜日別重症者\n(2020/1 - 2021/9)')
    plt.legend(loc='center right')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図11
    図11はMatplotlibのplot()メソッドで東京、大阪、神奈川の曜日別重症者の線グラフを作成している画面です。
  8. 日別死亡者の線グラフを作成する

    # Plot a line chart for new_deaths : 日別死亡者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dateframe to tot_deaths
    filter_by = (raw['file_id'] == 'tot_deaths')
    df = raw[filter_by]
    
    # # Get to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)
    prefs = desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','北海道']
    
    for pref in prefs:
        #filter_by = (df['prefecture'] == pref)
        filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['new_deaths'] = dfx['total_deaths'].diff() 
        grp = dfx.groupby('date')['new_deaths'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('死亡者数')
    plt.title('COVID-19 日別死亡者\n(2021/3 - 2021/9)')
    plt.legend(loc='upper right')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図12
    図12はMatplotlibのplot()メソッドで東京、大阪、神奈川の日別死亡者の線グラフを作成している画面です。
  9. 累計死亡者の線グラフを作成する

    # Plot a line chart for total_deaths : 累計死亡者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Get to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','北海道']
    kens_values = []
    for val in desc_prefs.values:
        kens_values.append(f'{kens.pop(0)}({str(int(val))})')
        if len(kens) == 0:
            break
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        grp = dfx.groupby('date')['total_deaths'].sum()    
        plt.plot(grp.index, grp.values, label=kens_values.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('死亡者数')
    plt.title('COVID-19 累計死亡者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図13
    図13はMatplotlibのplot()メソッドで東京、大阪、神奈川の累計死亡者の線グラフを作成している画面です。
  10. 曜日別死亡者の線グラフを作成する

    # Plot line chart for new_cases by day of week : 曜日別死亡者 線グラフ
    
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dateframe to tot_deaths
    filter_by = (raw['file_id'] == 'tot_deaths')
    df = raw[filter_by]
    
    # Add a day of week
    dw_mapping = {
        0: '0-月', 
        1: '1-火', 
        2: '2-水', 
        3: '3-木', 
        4: '4-金',
        5: '5-土', 
        6: '6-日'
    } 
    df['day_of_week'] = df['date'].dt.weekday.map(dw_mapping)
    
    # Get to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)
    prefs = desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','北海道']
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['new_deaths'] = dfx['total_deaths'].diff() 
        grp = dfx.groupby('day_of_week')['new_deaths'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    #plt.xticks(rotation=45)
    plt.ylabel('死亡者数')
    plt.title('COVID-19 曜日別死亡者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper right')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図14
    図14はMatplotlibのplot()メソッドで東京、大阪、神奈川の曜日別死亡者の線グラフを作成している画面です。
  11. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Mapplotlib Line Chart Part2 COVID-19  
    # %%
    # 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 numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    
    # Load the csv files 
    
    csv_file = 'data/csv/covid-19/japan/combined.csv'
    #csv_file = 'https://money-or-ikigai.com/menu/python/article/data/covid-19/combined.csv'
    raw = pd.read_csv(csv_file) 
    
    # Convert str to datetime
    raw['date'] = pd.to_datetime(raw['date'])
    
    # %%
    
    # Plot line chart for new_cases : 日別感染者 線グラフ
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_cases
    filter_by = (raw['file_id'] == 'new_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    kens = ['東京','大阪','神奈川']
    
    for pref in prefs:
        #filter_by = (df['prefecture'] == pref)
        filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]     
        grp = dfx.groupby('date')['new_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)    
    
    plt.xticks(rotation=45)
    plt.ylabel('感染者数')
    plt.title('COVID-19 日別感染者\n(2020/3 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot a line chart for total_cases 累計感染者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_cases
    filter_by = (raw['file_id'] == 'new_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['東京','大阪','神奈川']
    kens_values = []
    for val in desc_prefs.values:
        kens_values.append(f'{kens.pop(0)}({str(int(val))})')
        if len(kens) == 0:
            break
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)  
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01')
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_cases'] = dfx['new_cases'] .cumsum()   
        grp = dfx.groupby('date')['total_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens_values.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('感染者数')
    plt.title('COVID-19 累計感染者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot line chart for new_cases by day of week 曜日別感染者 線グラフ
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_cases
    filter_by = (raw['file_id'] == 'new_cases')
    df = raw[filter_by]
    
    # Add a day of week
    #df['day_of_week'] = df['date'].dt.dayofweek
    dw_mapping = {
        0: '0-月', 
        1: '1-火', 
        2: '2-水', 
        3: '3-木', 
        4: '4-金',
        5: '5-土', 
        6: '6-日'
    } 
    df['day_of_week'] = df['date'].dt.weekday.map(dw_mapping)
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    kens = ['東京','大阪','神奈川']
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]     
        grp = dfx.groupby('day_of_week')['new_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)         
    
    #plt.xticks(rotation=45)
    #plt.xlabel(['Mon','Tue','Wed','Thu','Fri','Sat','Sun'])
    plt.ylabel('感染者数')
    plt.title('COVID-19 曜日別感染者\n(2020/1 - 2021/9)')
    plt.legend(loc='center right')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot a line chart severe_cases : 日別重症者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_severe_cases
    filter_by = (raw['file_id'] == 'new_severe_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most severe cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','神奈川']
    
    for pref in prefs:
        #filter_by = (df['prefecture'] == pref)
        filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by ]
        grp = dfx.groupby('date')['severe_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('重症者数')
    plt.title('COVID-19 日別重症者\n(2021/3 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot a line chart total_severe_cases : 累計重症者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_severe_cases
    filter_by = (raw['file_id'] == 'new_severe_cases')
    df = raw[filter_by]
    
    # Get to see which prefectures have the most severe cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','神奈川']
    kens_values = []
    for val in desc_prefs.values:
        kens_values.append(f'{kens.pop(0)}({str(int(val))})')
        if len(kens) == 0:
            break
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_severe_cases'] = dfx['severe_cases'] .cumsum()  
        grp = dfx.groupby('date')['total_severe_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens_values.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('重症者数')
    plt.title('COVID-19 累計重症者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot line chart for severe_cases by day of week : 曜日別重症者 線グラフ
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dataframe to new_server_cases
    filter_by = (raw['file_id'] == 'new_severe_cases')
    df = raw[filter_by]
    
    # Add a day of week
    #df['day_of_week'] = df['date'].dt.dayofweek
    dw_mapping = {
        0: '0-月', 
        1: '1-火', 
        2: '2-水', 
        3: '3-木', 
        4: '4-金',
        5: '5-土', 
        6: '6-日'
    } 
    df['day_of_week'] = df['date'].dt.weekday.map(dw_mapping)
    
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    kens = ['大阪','東京','神奈川']
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]     
        grp = dfx.groupby('day_of_week')['severe_cases'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)         
    
    #plt.xticks(rotation=45)
    #plt.xlabel(['Mon','Tue','Wed','Thu','Fri','Sat','Sun'])
    plt.ylabel('重症者数')
    plt.title('COVID-19 曜日別重症者\n(2020/1 - 2021/9)')
    plt.legend(loc='center right')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot a line chart for new_deaths : 日別死亡者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dateframe to tot_deaths
    filter_by = (raw['file_id'] == 'tot_deaths')
    df = raw[filter_by]
    
    # # Get to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)
    prefs = desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','北海道']
    
    for pref in prefs:
        #filter_by = (df['prefecture'] == pref)
        filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['new_deaths'] = dfx['total_deaths'].diff() 
        grp = dfx.groupby('date')['new_deaths'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('死亡者数')
    plt.title('COVID-19 日別死亡者\n(2021/3 - 2021/9)')
    plt.legend(loc='upper right')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot a line chart for total_deaths : 累計死亡者 線グラフ
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # # Get to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)
    prefs =  desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','北海道']
    kens_values = []
    for val in desc_prefs.values:
        kens_values.append(f'{kens.pop(0)}({str(int(val))})')
        if len(kens) == 0:
            break
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        grp = dfx.groupby('date')['total_deaths'].sum()    
        plt.plot(grp.index, grp.values, label=kens_values.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    plt.xticks(rotation=45)
    plt.ylabel('死亡者数')
    plt.title('COVID-19 累計死亡者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot line chart for new_cases by day of week : 曜日別死亡者 線グラフ
    
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Filter dateframe to tot_deaths
    filter_by = (raw['file_id'] == 'tot_deaths')
    df = raw[filter_by]
    
    # Add a day of week
    #df['day_of_week'] = df['date'].dt.dayofweek
    dw_mapping = {
        0: '0-月', 
        1: '1-火', 
        2: '2-水', 
        3: '3-木', 
        4: '4-金',
        5: '5-土', 
        6: '6-日'
    } 
    df['day_of_week'] = df['date'].dt.weekday.map(dw_mapping)
    
    # Get to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)
    prefs = desc_prefs.index[0:3]  # Select 3 prefectures
    
    kens = ['大阪','東京','北海道']
    
    for pref in prefs:
        filter_by = (df['prefecture'] == pref)
        #filter_by = (df['prefecture'] == pref) & (df['date'] >= '2021-03-01') 
        dfx = df[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['new_deaths'] = dfx['total_deaths'].diff() 
        grp = dfx.groupby('day_of_week')['new_deaths'].sum()    
        plt.plot(grp.index, grp.values, label=kens.pop(0))
        #plt.plot(grp.index, grp.values, label=pref)
    
    #plt.xticks(rotation=45)
    plt.ylabel('死亡者数')
    plt.title('COVID-19 曜日別死亡者\n(2020/1 - 2021/9)')
    plt.legend(loc='upper right')
    plt.tight_layout()
    plt.show()
    # %%
    

◆株価(GAFA)の生データを使って線グラフを作成する

  1. GAFAの株価をダウンロードしてCSVファイルに保存する

    行3-11ではPythonのライブラリを取り込んでいます。 ライブラリをまだインストールしていないときはPythonの「pip」で事前にインストールしておいてください。 行12ではPythonの警告メッセージを抑止しています。 行15-16ではYahoo! Financeから取得する株価の開始日と終了日を定義しています。 終了日を当日までにするには「end = dt.datetime.now()」のように書き換えてください。

    行17ではPandasのDataReader()メソッドで株価を取り込んでPandasのDataFrameに格納しています。 DataReader()の引数1には企業のティッカーシンボルを指定します。 ここではGAFAのシンボルを指定しています。 引数2には株価の取り込み先を指定します。ここではYahoo! Financeを指定しています。 引数3, 4では株価の開始日と終了日を指定します。 行18ではDataFrameのstack()メソッドでDataFrameに格納されているデータ(PIVOT形式)を通常の形式に変換しています。 PandasのDataReader()で取得した株価のデータはPIVOT形式で格納されています。 今回のケースではGAFAの株価が列として格納されています。 stack()はこれを列から行へ変換します。詳しくは図15-2を参照してください。 図15-2に列から行へ変換する前後のデータをExcelで表示しています。 DataFrameのreset_index()メソッドはPandasのindexを再作成しています。 行19ではCSVファイルのパスを定義しています。ご自分の環境にあわせてパスを書き換えてください。 行20ではPandasのto_csv()メソッドで株価のデータをCSVファイルに保存しています。
    # 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 mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')    
    
    # Load Data from Yahoo Finace
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime(2021, 9, 17)	        # 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/article014/stock.csv'
    df.to_csv(csv_file, index=False)
    click image to zoom!
    図15-1
    図15-1はインタラクティブ・ウィンドウから「df.info()」と「df.head(3)」でDataFrameの内容を表示しています。 df.info()ではDataFrameのレコード件数と列名(データ型)が表示されます。 df.head(3)ではDataFrameの先頭から3件のレコードが表示されます。
    click image to zoom!
    図15-2
    図15-2ではDataReader()で取り込んだ株価のデータとDataFrameのstack()メソッドでデータを列から行に変換した後のデータを比較しています。 これでstack()の機能が理解できると思います。
  2. GAFAの株価の線グラフを作成する

    # Load stock data from the csv file
    csv_file = 'data/csv/article014/stock.csv'
    df = pd.read_csv(csv_file)
    df['Date'] = pd.to_datetime(df['Date']) # Convert str to datetime
    
    # Plot line chart 
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')        # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    
    # Draw a line chart
    for symbol in symbols:
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == pref) & (df['Date'] >= '2021-01-01') 
        dfx = df[filter_by]             
        #plt.plot(dfx.Date, dfx.Close, label=symbol)   
        label = symbols_mapping[symbol]
        plt.plot(dfx.Date, dfx.Close, label=label)  
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices')
    plt.title('GAFA Stock Prices\n(GAFA株価)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図16

  3. MplfinanceでAmazon(株価)の線グラフを作成する

    # Plot simple line chart using mplfinance
    filter_by = (df['Symbols'] == 'AMZN')  # Amazon
    dfx = df[filter_by] 
    dfx = dfx.set_index('Date')
    
    style  = mpf.make_mpf_style(rc={'font.family':'Meiryo'})
    
    mpf.plot(dfx, 
        type='line', 
        datetime_format='%Y/%m/%d',
        title ='Amazon株価 ',
        ylabel='価格',
        style=style
        )
    click image to zoom!
    図17

  4. 線グラフに出来高を追加する

    # Add volume 
    mpf.plot(dfx, 
        type='line', volume=True,
        datetime_format='%Y/%m/%d',
        title ='Amazon株価 ',
        ylabel='価格',
        ylabel_lower='ボリューム',
        style=style
        )
    click image to zoom!
    図18

  5. 線グラフをロウソク足チャートに変える

    # Draw candlestic chart
    
    mpf.plot(dfx['2020-08':'2020-09'], 
        type='candle', volume=True,
        datetime_format='%Y/%m/%d',
        title ='Amazon株価 ',
        ylabel='価格',
        ylabel_lower='ボリューム',
        style=style
        )
    click image to zoom!
    図19

  6. ロウソク足チャートに移動平均線(20日)を追加する

    # Add Moving Average 
    
    mpf.plot(dfx['2020-03':'2020-09'], 
        type='candle', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Amazon株価',
        ylabel='価格',
        ylabel_lower='ボリューム',
        style=style
        )
    click image to zoom!
    図20

  7. ロウソク足チャートにスタイルを追加する

    # Add Style 
    
    rcpdict = { 'font.family' : 'Meiryo' }
    style = mpf.make_mpf_style(base_mpf_style='yahoo', rc=rcpdict)
    
    mpf.plot(dfx['2020-03':'2020-09'], 
        type='candle', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Amazon株価',
        ylabel='価格',
        ylabel_lower='ボリューム',
        figratio=(20,12),    
        tight_layout=False,
        style=style
        )
    click image to zoom!
    図21

  8. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    # 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 mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    # %%
    
    # Load Data from Yahoo Finace
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime(2021, 9, 19)	        # end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    csv_file = 'data/csv/article014/stock_before_Stack.csv'
    df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    df = df.stack().reset_index()           # Remove Symbols and reset date index 
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    csv_file = 'data/csv/article014/stock.csv'
    df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    # %%
    
    # Load stock data from the csv file
    csv_file = 'data/csv/article014/stock.csv'
    df = pd.read_csv(csv_file)
    #print(df.info())       
    df['Date'] = pd.to_datetime(df['Date']) # Convert str to datetime
    #print(df.info())  
    # Date	Symbols	Adj Close	Close	High	Low	Open	Volume
    #print(df.head(5))
    
    # Plot line chart 
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    symbols_mapping = {
        'GOOGL': 'Google', 
        'AMZN': 'Amazon', 
        'FB': 'Facebook', 
        'AAPL': 'Apple' 
    } 
    # Draw a line chart
    for symbol in symbols:
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == pref) & (df['Date'] >= '2021-01-01') 
        dfx = df[filter_by]             
        #plt.plot(dfx.Date, dfx.Close, label=symbol)   
        label = symbols_mapping[symbol]
        plt.plot(dfx.Date, dfx.Close, label=label)  
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices')
    plt.title('GAFA Stock Prices\n(GAFA株価)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    # %%
    
    # Plot simple line chart using mplfinance
    filter_by = (df['Symbols'] == 'AMZN')  # Amazon
    dfx = df[filter_by] 
    dfx = dfx.set_index('Date')
    
    style  = mpf.make_mpf_style(rc={'font.family':'Meiryo'})
    
    mpf.plot(dfx, 
        type='line', 
        datetime_format='%Y/%m/%d',
        title ='Amazon株価 ',
        ylabel='価格',
        style=style
        )
    
    # %%
    
    # Add volume 
    mpf.plot(dfx, 
        type='line', volume=True,
        datetime_format='%Y/%m/%d',
        title ='Amazon株価 ',
        ylabel='価格',
        ylabel_lower='ボリューム',
        style=style
        )
    
    # %%
    
    # Draw candlestic chart
    
    mpf.plot(dfx['2020-08':'2020-09'], 
        type='candle', volume=True,
        datetime_format='%Y/%m/%d',
        title ='Amazon株価 ',
        ylabel='価格',
        ylabel_lower='ボリューム',
        style=style
        )
    
    # %%
    
    # Add Moving Average 
    
    mpf.plot(dfx['2020-03':'2020-09'], 
        type='candle', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Amazon株価',
        ylabel='価格',
        ylabel_lower='ボリューム',
        style=style
        )
    
    # %%
    
    # Add Style 
    
    rcpdict = { 'font.family' : 'Meiryo' }
    style = mpf.make_mpf_style(base_mpf_style='yahoo', rc=rcpdict)
    
    mpf.plot(dfx['2020-03':'2020-09'], 
        type='candle', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Amazon株価',
        ylabel='価格',
        ylabel_lower='ボリューム',
        figratio=(20,12),    
        tight_layout=False,
        style=style
        )
    
    # %%
    

◆仮想通貨(暗号通貨)(BTC,ETC,LTC,XRP)の生データを使って線グラフを作成する

  1. 仮想通貨(暗号通貨)の価格データをダウンロードしてCSVファイルに保存する

    # 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 mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    
    # Load Data from Yahoo Finace
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime(2021, 9, 19)	        # end = dt.datetime.now()
    crypto = ['BTC-JPY', 'ETC-JPY', 'LTC-JPY', 'XRP-JPY', 'SC-JPY']
    df = web.DataReader(crypto, 'yahoo', start=start, end=end)
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    csv_file = 'data/csv/article014/crypto_before_Stack.csv'
    df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    df = df.stack().reset_index()           # Remove Symbols and reset date index 
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    csv_file = 'data/csv/article014/crypto.csv'
    df.to_csv(csv_file, index=False)
    click image to zoom!
    図22

  2. 仮想通貨(暗号通貨)の価格の線グラフを作成する

    # Load crypto data from the csv file
    csv_file = 'data/csv/article014/crypto.csv'
    df = pd.read_csv(csv_file)    
    df['Date'] = pd.to_datetime(df['Date']) # Convert str to datetime
    # Date	Symbols	Adj Close	Close	High	Low	Open	Volume
    
    # Plot line chart 
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    
    # Draw a line chart
    
    plt.yscale('log')
    
    for symbol in symbols:
        filter_by = (df['Symbols'] == symbol)
        dfx = df[filter_by]             
        plt.plot(dfx.Date, dfx.Close, label=symbol)    
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices')
    plt.title('Crypto Prices\n(仮想通貨(暗号通貨))')
    plt.legend(loc='upper left')
    plt.tight_layout()
    #plt.savefig('data/png/ex7.png')
    plt.show()
    click image to zoom!
    図23

  3. Mplfinanceでビットコイン(BTC-JPY)の線グラフを作成する

    # Plot simple line chart using mplfinance
    filter_by = (df['Symbols'] == 'BTC-JPY')  # Bitcoin 
    dfx = df[filter_by] 
    dfx = dfx.set_index('Date')
    
    style  = mpf.make_mpf_style(rc={'font.family':'Meiryo'})
    
    mpf.plot(dfx, 
        type='line', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Bitcoin 価格 ',
        ylabel='価格(円)',
        ylabel_lower='ボリューム',
        style=style
        )
    click image to zoom!
    図24

  4. Mplfinanceでビットコイン(BTC-JPY)のロウソク足チャートを作成する

    # Draw candle chart 
    
    rcpdict = { 'font.family' : 'Meiryo' }
    style = mpf.make_mpf_style(base_mpf_style='yahoo', rc=rcpdict)
    
    mpf.plot(dfx['2020-03':'2020-09'], 
        type='candle', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Bitcoin 価格',
        ylabel='価格(円)',
        ylabel_lower='ボリューム',
        figratio=(20,12),    # 20,12 or 45,30
        tight_layout=False,
        style=style  #,savefig=('data/png/ex8.png')
        )
    click image to zoom!
    図25

  5. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    # 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 mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    
    # Load Data from Yahoo Finace
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime(2021, 9, 19)	        # end = dt.datetime.now()
    crypto = ['BTC-JPY', 'ETC-JPY', 'LTC-JPY', 'XRP-JPY', 'SC-JPY']
    df = web.DataReader(crypto, 'yahoo', start=start, end=end)
    csv_file = 'data/csv/article014/crypto_before_Stack.csv'
    df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    df = df.stack().reset_index()           # Remove Symbols and reset date index 
    csv_file = 'data/csv/article014/crypto.csv'
    df.to_csv(csv_file, index=False)       
    
    # %%
    
    # Load crypto data from the csv file
    csv_file = 'data/csv/article014/crypto.csv'
    df = pd.read_csv(csv_file)   
    df['Date'] = pd.to_datetime(df['Date']) # Convert str to datetime
    # Date	Symbols	Adj Close	Close	High	Low	Open	Volume
    # Plot line chart 
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    
    # Draw a line chart
    plt.yscale('log')
    
    for symbol in symbols:
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == pref) & (df['Date'] >= '2021-01-01') 
        dfx = df[filter_by]             
        plt.plot(dfx.Date, dfx.Close, label=symbol)    
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices')
    plt.title('Crypto Prices\n(仮想通貨(暗号通貨))')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.savefig('data/png/ex8.png')
    plt.show()
    
    # %%
    
    # Plot simple line chart using mplfinance
    filter_by = (df['Symbols'] == 'BTC-JPY')  # Bitcoin 
    dfx = df[filter_by] 
    dfx = dfx.set_index('Date')
    
    style  = mpf.make_mpf_style(rc={'font.family':'Meiryo'})
    
    mpf.plot(dfx, 
        type='line', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Bitcoin 価格 ',
        ylabel='価格(円)',
        ylabel_lower='ボリューム',
        style=style
        )
    
    # %%
    
    # Draw chandle chart 
    
    rcpdict = { 'font.family' : 'Meiryo' }
    style = mpf.make_mpf_style(base_mpf_style='yahoo', rc=rcpdict)
    
    mpf.plot(dfx['2020-03':'2020-09'], 
        type='candle', volume=True, mav=(20),
        datetime_format='%Y/%m/%d',
        title ='Bitcoin 価格',
        ylabel='価格(円)',
        ylabel_lower='ボリューム',
        figratio=(20,12),    # 20,12 or 45,30
        tight_layout=False,
        style=style  # ,savefig=('data/png/ex9.png')
        )
    
    # %%
    

◆応用1【ストック編】

  1. GAFAの株価をさまざまな種類のグラフで表示する

    ここでは応用編としてGAFAの株価をLine chart, Candlestick chart, Fill area of line chart, Stacked bar chartなどで表示します。

    click image to zoom!
    Stock Line chart
    click image to zoom!
    Stock Candlestick chart
    click image to zoom!
    Stock Fill area chart
    click image to zoom!
    Stock Stacked bar chart

    
    # Article014_Matplotlib Line Chart Part3 Stock (2).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.dates as mpl_dates
    import matplotlib.style as style
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    
    # 1) Load Data from Yahoo Finace
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    df = web.DataReader(['GOOGL','AMZN','FB','AAPL'], 'yahoo', start=start, end=end)
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    #csv_file = 'data/csv/article014/stock_before_Stack.csv'
    #df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    df = df.stack().reset_index()           # Remove Symbols and reset date index 
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    csv_file = 'data/csv/article014/stock.csv'
    df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    # %%
    
    # 2) Load stock data from the csv file
    #csv_file = 'data/csv/article014/stock.csv'
    #df = pd.read_csv(csv_file)
    #print(df.info())       
    df['Date'] = pd.to_datetime(df['Date']) # Convert str to datetime
    #print(df.info())  
    # Date	Symbols	Adj Close	Close	High	Low	Open	Volume
    #df = df.set_index('Date')
    #print(df.head(5))
    
    # 3) Plot line chart 
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    # Get price for last date
    last_date = df['Date'].max()    # 2021-09-28
    filter_by = (df['Symbols'] == 'GOOGL')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    google_price = dfx.Close.values[0].round(2)
    
    filter_by = (df['Symbols'] == 'AMZN')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    amazon_price = dfx.Close.values[0].round(2)
    
    filter_by = (df['Symbols'] == 'FB')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    facebook_price = dfx.Close.values[0].round(2)
    
    filter_by = (df['Symbols'] == 'AAPL')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    apple_price = dfx.Close.values[0].round(2)
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    symbols_mapping = {
        'GOOGL': f'Google(${google_price:,.2f})', 
        'AMZN': f'Amazon(${amazon_price:,.2f})', 
        'FB': f'Facebook(${facebook_price:,.2f})', 
        'AAPL': f'Apple(${apple_price:,.2f})' 
    } 
    # Draw a line chart
    for symbol in symbols:
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == pref) & (df['Date'] >= '2019-01-01') 
        dfx = df[filter_by]              
        label = symbols_mapping[symbol]
        plt.plot(dfx.Date, dfx.Close, label=label)  
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices (USD)')
    plt.title('GAFA Stock Prices\n(Line chart)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    #plt.savefig('data/png/ex6.png')
    plt.show()
    
    # %%
    
    # 4) Plot a candle chart using mplfinance
    filter_by = (df['Symbols'] == 'AMZN')  # Amazon
    dfx = df[filter_by] 
    dfx = dfx.set_index('Date')
    
    style  = mpf.make_mpf_style(rc={'font.family':'Meiryo'})
    
    rcpdict = { 'font.family' : 'Meiryo' }
    style = mpf.make_mpf_style(base_mpf_style='yahoo', rc=rcpdict)
    
    mpf.plot(dfx['2021-05':'2021-09'],          # '2020-03':'2020-09'
        type='candle', volume=True, mav=(20),
        datetime_format='%m/%d',             # '%Y/%m/%d' or '%m/%d'
        title ='Amazon Stock Prices\n(Candlestick chart)',
        ylabel='Closing Prices (USD)',
        ylabel_lower='Volume',
        figratio=(45,30),    # 20,12
        tight_layout=False,
        style=style  #,savefig=('data/png/ex7.png')
        )
    
    
    # %%
    
    # 5) Plot a line chart and fill area
    
    filter_by = (df['Symbols'] == 'AMZN')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    
    median = dfx.Close.median()
    median_Close = np.repeat(median, len(dfx.Close))
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    plt.plot(dfx.Date, dfx.Close, linewidth=1, label='Amazon')
    plt.plot(dfx.Date, median_Close, color='#444444', linestyle='dashed', linewidth=1, label='Median(中央値)')  
    
    plt.fill_between(dfx.Date, dfx.Close, median_Close, 
        where=(dfx.Close > median_Close),
        interpolate=True,
        alpha=0.25, label='Above Median(中央値以上)')
    
    plt.fill_between(dfx.Date, dfx.Close, median_Close, 
        where=(dfx.Close <= median_Close),
        interpolate=True,
        alpha=0.25, label='Below Median(中央値以下)')    
    
    plt.margins(x=0)
    
    plt.gcf().autofmt_xdate()
    #date_format = mpl_dates.DateFormatter('%Y/%m/%d')
    date_format = mpl_dates.DateFormatter('%m/%d')
    plt.gca().xaxis.set_major_formatter(date_format)
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices (USD)')
    plt.title('Amazon Stock Prices\n(Fill area of line chart)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    #plt.savefig('data/png/ex6.png')
    plt.show()
    
    # %%
    
    # 6) Plot a stack chart for Amazon, Google, Apple
    
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))          #  12,5
    
    filter_by = (df['Symbols'] == 'AMZN')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    amazon_Close = dfx.Close.values  
    
    filter_by = (df['Symbols'] == 'GOOGL')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    google_Close = dfx.Close.values
    
    filter_by = (df['Symbols'] == 'AAPL')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    apple_Close = dfx.Close.values
    
    filter_by = (df['Symbols'] == 'FB')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    facebook_Close = dfx.Close.values
    
    blue = '#008fd5'
    red = '#fc4f30'
    yellow = '#e5ae37'
    green = '#6d904f'
    
    labels = ['Amazon','Google']
    colors = [red, blue]
    
    # plt.stackplot(dfx.Date, amazon_Close,
    #     labels='Amazon', colors=red)
    
    plt.stackplot(dfx.Date, amazon_Close, google_Close,
        labels=labels, colors=colors)    
    
    plt.gcf().autofmt_xdate()
    #date_format = mpl_dates.DateFormatter('%Y/%m/%d')
    date_format = mpl_dates.DateFormatter('%m/%d')
    plt.gca().xaxis.set_major_formatter(date_format)
    
    #plt.yscale('log')
    
    plt.margins(x=0)
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices (USD)')
    plt.title('Amazon vs Google\n(Stacked bar chart)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    
    # %%
    
    

◆応用2【仮想通貨(暗号通貨)編】

  1. 仮想通貨(暗号通貨)の価格をさまざまな種類のグラフで表示する

    ここでは応用編としてBitcoinなどの仮想通貨(暗号通貨)の価格をLine chart, Candlestick chart, Fill area of line chart, Stacked bar chartなどで表示します。

    click image to zoom!
    Crypto Line chart
    click image to zoom!
    Crypto Candlestick chart
    click image to zoom!
    Crypto Fill area chart
    click image to zoom!
    Crypto Stacked bar chart

    
    
    # 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.dates as mpl_dates
    import matplotlib.style as style
    import mplfinance as mpf                # pip install mplfinance
    import datetime as dt
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    
    # 1) Load Data from Yahoo Finace
    start = dt.datetime(2019, 1, 1)
    end = dt.datetime.now()
    crypto = ['BTC-JPY', 'ETC-JPY', 'LTC-JPY', 'XRP-JPY', 'SC-JPY']
    df = web.DataReader(crypto, 'yahoo', start=start, end=end)
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    #csv_file = 'data/csv/article014/stock_before_Stack.csv'
    #df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    df = df.stack().reset_index()           # Remove Symbols and reset date index 
    #print(df.info())
    #print(df.head(3))                       #print(df.tail(3))
    csv_file = 'data/csv/article014/crypto.csv'
    df.to_csv(csv_file, index=False)        #df.to_csv(csv_file)
    
    # %%
    
    # 2) Load stock data from the csv file
    #csv_file = 'data/csv/article014/crypto.csv'
    #df = pd.read_csv(csv_file)
    #print(df.info())       
    df['Date'] = pd.to_datetime(df['Date']) # Convert str to datetime
    #print(df.info())  
    # Date	Symbols	Adj Close	Close	High	Low	Open	Volume
    #df = df.set_index('Date')
    #print(df.head(5))
    
    # 3) Plot line chart 
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,8))  # 12,5
    
    # Get price for last date
    last_date = df['Date'].max()    # 2021-09-28
    filter_by = (df['Symbols'] == 'BTC-JPY')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    btc_Close = int(dfx.Close.values[0].round(0))
    
    filter_by = (df['Symbols'] == 'ETC-JPY')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    etc_Close = int(dfx.Close.values[0].round(0))
    
    filter_by = (df['Symbols'] == 'LTC-JPY')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    ltc_Close = int(dfx.Close.values[0].round(0))
    
    filter_by = (df['Symbols'] == 'XRP-JPY')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    xrp_Close = int(dfx.Close.values[0].round(0))
    
    filter_by = (df['Symbols'] == 'SC-JPY')  & (df['Date'] == last_date)
    dfx = df[filter_by]
    sc_Close = int(dfx.Close.values[0].round(0))
    
    # Get symbols
    symbols = df['Symbols'].unique().tolist()
    symbols_mapping = {
        'BTC-JPY': f'Bitcoin(\\{btc_Close:,})', 
        'ETC-JPY': f'Ethereum Classic(\\{etc_Close:,})', 
        'LTC-JPY': f'Litecoin(\\{ltc_Close:,})', 
        'XRP-JPY': f'Ripple(\\{xrp_Close:,})',
        'SC-JPY': f'Siacoin(\\{sc_Close:,})'     
    } 
    # Draw a line chart
    for symbol in symbols:
        filter_by = (df['Symbols'] == symbol)
        #filter_by = (df['Symbols'] == pref) & (df['Date'] >= '2019-01-01') 
        dfx = df[filter_by]              
        label = symbols_mapping[symbol]
        plt.plot(dfx.Date, dfx.Close, label=label)  
    
    plt.yscale('log')
    
    plt.margins(x=0)
    
    plt.legend(bbox_to_anchor =(0.26, 1.18), ncol = 1)
    #plt.legend(bbox_to_anchor =(0.95, 1.18), ncol = 1)
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices (JPY)')
    plt.title('CryptoCurrency Prices\n(Line chart)')
    #plt.legend(loc='upper left')
    plt.tight_layout()
    #plt.savefig('data/png/ex6.png')
    plt.show()
    
    # %%
    
    # 4) Plot a candle chart using mplfinance
    filter_by = (df['Symbols'] == 'BTC-JPY')  
    dfx = df[filter_by] 
    dfx = dfx.set_index('Date')
    
    style  = mpf.make_mpf_style(rc={'font.family':'Meiryo'})
    
    rcpdict = { 'font.family' : 'Meiryo' }
    style = mpf.make_mpf_style(base_mpf_style='yahoo', rc=rcpdict)
    
    mpf.plot(dfx['2021-05':'2021-09'],          # '2020-03':'2020-09'
        type='candle', volume=True, mav=(20),
        datetime_format='%m/%d',             # '%Y/%m/%d' or '%m/%d'
        title ='Bitcoin Prices\n(Candlestick chart)',
        ylabel='Closing Prices (JPY)',
        ylabel_lower='Volume',
        figratio=(45,30),    # 20,12
        tight_layout=False,
        style=style  #,savefig=('data/png/ex7.png')
        )
    
    
    # %%
    
    # 5) Plot a line chart and fill area
    
    filter_by = (df['Symbols'] == 'BTC-JPY')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    
    median = dfx.Close.median()
    median_Close = np.repeat(median, len(dfx.Close))
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))
    
    plt.plot(dfx.Date, dfx.Close, linewidth=1, label='Bitcoin')
    plt.plot(dfx.Date, median_Close, color='#444444', linestyle='dashed', linewidth=1, label='Median(中央値)')  
    
    plt.fill_between(dfx.Date, dfx.Close, median_Close, 
        where=(dfx.Close > median_Close),
        interpolate=True,
        alpha=0.25, label='Above Median')
    
    plt.fill_between(dfx.Date, dfx.Close, median_Close, 
        where=(dfx.Close <= median_Close),
        interpolate=True,
        alpha=0.25, label='Below Median')    
    
    plt.margins(x=0)
    
    plt.gcf().autofmt_xdate()
    #date_format = mpl_dates.DateFormatter('%Y/%m/%d')
    date_format = mpl_dates.DateFormatter('%m/%d')
    plt.gca().xaxis.set_major_formatter(date_format)
    
    plt.legend(bbox_to_anchor =(1.00, 1.18), ncol = 1)
    #plt.legend(bbox_to_anchor =(0.95, 1.18), ncol = 1)
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices (JPY)')
    plt.title('Bitcoin Prices\n(Fill area of line chart)')
    #plt.legend(loc='upper right')
    plt.tight_layout()
    #plt.savefig('data/png/ex6.png')
    plt.show()
    
    # %%
    
    # 6) Plot a stack chart for 
    
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')    # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(12,5))          #  12,5
    
    filter_by = (df['Symbols'] == 'BTC-JPY')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    btc_Close = dfx.Close.values  
    
    filter_by = (df['Symbols'] == 'ETC-JPY')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    etc_Close = dfx.Close.values
    
    filter_by = (df['Symbols'] == 'LTC-JPY')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    ltc_Close = dfx.Close.values
    
    filter_by = (df['Symbols'] == 'XRP-JPY')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    xrp_Close = dfx.Close.values
    
    filter_by = (df['Symbols'] == 'SC-JPY')  & (df['Date'] >= '2021-01-01')
    dfx = df[filter_by]
    sc_Close = dfx.Close.values
    
    blue = '#008fd5'
    red = '#fc4f30'
    yellow = '#e5ae37'
    green = '#6d904f'
    
    labels = ['Ethereum Classic','Litecoin']
    colors = [red, blue]
    
    # plt.stackplot(dfx.Date, amazon_Close,
    #     labels='Amazon', colors=red)
    
    plt.stackplot(dfx.Date, etc_Close, ltc_Close,
        labels=labels, colors=colors)    
    
    plt.gcf().autofmt_xdate()
    #date_format = mpl_dates.DateFormatter('%Y/%m/%d')
    date_format = mpl_dates.DateFormatter('%m/%d')
    plt.gca().xaxis.set_major_formatter(date_format)
    
    #plt.yscale('log')
    
    plt.margins(x=0)
    
    plt.xticks(rotation=45)
    plt.ylabel('Closeing Prices (JPY)')
    plt.title('Ethereum Classic vs Litecoin\n(Stacked bar chart)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    
    # %%
    
    

◆応用3【仮想通貨(暗号通貨)の取引所間の価格差を見つけて売買するアービトラージ(裁定取引)を自動化するには】

  1. Part1: 取引所ごとの仮想通貨(暗号通貨)の最新価格を取得してCSVファイルに保存する

    ここでは「funnhub.com」が提供しているAPIを使用しています。 このAPIの使い方については「記事(Article021)」を参照してください。

    Part1では、まずcrypto_exchanges()メソッドを実行して仮想通貨(暗号通貨)の取引所の一覧を取得します。 次にcrypto_symbols()メソッドを実行してそれぞれの取引所が扱っている仮想通貨(暗号通貨)の一覧を取得してCSVファイルに保存します。 各取引所が扱っている仮想通貨(暗号通貨)はPandasのDataFrameのconcat()メソッドを実行して一元化します。

    仮想通貨(暗号通貨)は取引所が2箇所以上のものだけに絞り込みます。 仮想通貨(暗号通貨)を絞り込んだら、crypto_candles()メソッドを実行してそれぞれの取引所の最新の価格を取得してCSVファイルに保存します。 以下がこれらの処理を自動で行うPyothonのコードです。
    
    # Link: https://finnhub.io/
    # Link: https://finnhub.io/pricing   Free: 60 API calls /  1sec
    
    # Import the necessary libraries
    import glob, os, os.path
    import winsound
    import time
    import datetime
    import calendar
    import pandas as pd
    import finnhub  # pip install finnhub-python==2.4.5
    import warnings
    warnings.simplefilter('ignore')
    
    # 0) Delete all files in a folder
    
    mydir = 'data/csv/article021/exchange/'
    filelist = glob.glob(os.path.join(mydir, '*.csv'))
    for f in filelist:
        print(f'removing file {f}')
        os.remove(f)
    
    # 1) GET an API-key
    api_key = os.environ.get('FINNHUB_API_KEY')
    
    # 2) Setup client
    finnhub_client = finnhub.Client(api_key=api_key)
    
    # 3) Get Crypto Exchanges
    exchanges = finnhub_client.crypto_exchanges() # ['OKEX', 'GEMINI', 'BINANCE', 'COINBASE',...]
    
    dfx_exchanges = []
    
    for exchange in exchanges:
        symbols = finnhub_client.crypto_symbols(exchange)  # [{'description': 'Binance SOL/BNB', 'displaySymbol': 'SOL/BNB', 'symbol': 'BINANCE:SOLBNB'}]
        #print(symbols)  
        df = pd.DataFrame(symbols)
        filter_by = (df['symbol'].str.contains('USDT'))
        dfx = df[filter_by]    
        csv_file = f'data/csv/article021/symbols({exchange}).csv'
        dfx.to_csv(csv_file, index=False)
        dfx_exchanges.append(dfx)
    
    # Merge All Symbols    
    dfx_all = pd.concat(dfx_exchanges, ignore_index=True, axis=0)
    dfx_all.to_csv('data/csv/article021/symbols(ALL).csv', index=False)
    
    df = pd.read_csv('data/csv/article021/symbols(ALL).csv')
    
    dfx = df['displaySymbol'].value_counts().rename_axis('displaySymbol').reset_index(name='counts')
    dfx.to_csv('data/csv/article021/uniqueDisplaySymbol.csv', index=False)
    
    filter_by = (dfx['counts'] >= 2)
    dfx = dfx[filter_by]    # filter by counts >= 2 crypto
    
    
    # 4) Get Crypto Candles
    
    def get_crypto_candles(display_symbol, symbol):     # BTC_USDE, BINANCE:BTCUSDT   
        print(f'get_crypto_candles({display_symbol}, {symbol})')
    
        resolution = '1'    # 1, 5, 15, 30, 60, D, W, M   
        secs = 60
        cur_datetime = datetime.datetime.utcnow() - datetime.timedelta(seconds=secs)
        cur_timetuple = cur_datetime.utctimetuple()
        cur_timestamp = calendar.timegm(cur_timetuple)
        ts_from = cur_timestamp     # UNIX timestamp. Interval initial value
    
        cur_datetime = datetime.datetime.utcnow()
        cur_timetuple = cur_datetime.utctimetuple()
        cur_timestamp = calendar.timegm(cur_timetuple)
        ts_to = cur_timestamp       # UNIX timestamp. Interval initial value
      
        symbol1, symbol2 = symbol.split(':')   # BINANCE:BTCUSDT, COINBASE:BTC-USDT,... 
        symbol2 = symbol2.replace('-','').replace('_','')   
        # symbol1:BINANCE, symbol2:BTCUSDT
        try:
            # Crypto candles
            res = finnhub_client.crypto_candles(symbol, resolution, ts_from, ts_to)   
            #print(res)
        except Exception as e:
            print(f'crypto_candles({symbol},{resolution}) exception error: ', e)
        else:
            if res.get('s', 'no_data') == 'ok':
                if res.get('c') != None:
                    # Conver to Pandas DataFrame
                    dfz = pd.DataFrame(res)
                    # c(Close), h(High), l(Low), o(Open), s(Status), t(Time_Stamp), v(Volume)
                    dfz['exchange'] = symbol1    # add exchange : 'BINANCE',...
                    dfz['symbol'] = symbol2      # add symbol : 'BTCUSDT',...
                    dfz['date'] = dfz['t'].apply(lambda x: datetime.datetime.fromtimestamp(x))  # add column name and set date
                    csv_file = f'data/csv/article021/exchange/crypto({display_symbol}).csv'  # 'BTC_USDT',...
                    dfz.to_csv(csv_file, mode='a', header=False, index=False)    # append mode, no header       
    
            time.sleep(2)   # 2.0 secs
    
    
    #display_symbols = ['BTC/USDT','ETH/USDT', 'DOT/USDT', 'BCH/USDT', 'DOGE/USDT','XRP/USDT','LTC/USDT','LINK/USDT','EOS/USDT']
    display_symbols = dfx['displaySymbol'].values
    
    cnt = 0
    print('Startd While loop...')
    while True:
        print('while True loop... cnt=', cnt)    
        for display_symbol in display_symbols:  # BTC/USDT,...
            filter_by = (df['displaySymbol'] == display_symbol)
            dfy = df[filter_by] # filter exchanges Binance, COINBASE, Kucoin, OKEX, Poloniex
            symbols = dfy['symbol'].values
            display_symbol = display_symbol.replace('/','_')    # BTC/USDT => BTC_USDT
            for symbol in symbols:  # BINANCE:BTCUSDT, OKED:BTC-USDT, COINBASE:BTC-USDT,..
                #print(display_symbol, symbol)
                get_crypto_candles(display_symbol, symbol)
        cnt += 1
        # loop n times
        if cnt >= 0:
            break
    print('Ended While loop!')
    
    # Sound alarm when code finishes
    
    duration = 1000  # milliseconds
    freq = 400  # Hz 
    freqs = [196,220,233,247,262,277,294,311,330,349,370,392,415]
    winsound.Beep(freq, duration)
    
    for freq in freqs:
        winsound.Beep(freq, duration)
        time.sleep(0.5)
    
    
  2. Part2: 仮想通貨(暗号通貨)の取引所の価格差が大きい通貨上位20を水平棒グラフに表示する

    Part2では、まずPart1で作成したすべてのCSVファイル(各取引所の仮想通貨(暗号通貨)の最新の価格が保存されている)を取り込んでPandasのDataFrameに格納します。

    次に仮想通貨(暗号通貨)(2箇所以上の取引所の価格が含まれている)の最高値と最安値を計算します。そして、最高値と最安値の差額を計算します。 最後に差額の大きい順に並べ替えて上位20件の仮想通貨(暗号通貨)を水平棒グラフで表示します。 このグラフには「最高値の取引所」、「最高値の取引所」、そして「価格差」が降順に表示されます。

    後は、最安値の取引所でその仮想通貨(暗号通貨)を購入して最高値の取引所で売る処理を自動化します。 これで取引所間の価格差を利用したアビトラージトレード(裁定取引)が自動化できます。

    click image to zoom!
    Difference Between Exchanges

    
    # Link: https://finnhub.io/pricing   Free: 60 API calls / 1sec
    # Link: https://pbpython.com/pandas_transform.html   Pandas Groupby.transform()
    
    # Import the necessary libraries  
    from os import replace
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.dates as mpl_dates
    import matplotlib.style as style
    from matplotlib.animation import FuncAnimation
    import datetime as dt
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) Merge all crypto
    csv_file = 'data/csv/article021/uniqueDisplaySymbol.csv'    
    df = pd.read_csv(csv_file)  # displaySymbol,counts => BTC/USDT,5 
    filter_by = (df['counts'] >= 2)
    df = df[filter_by]    # filter by counts >= 2 crypto
    
    symbols = df['displaySymbol'].values    # ETH/USDT, DOT/USDT, BCH/USDT,...
    df_list = []
    err_cnt = 0
    for symbol in symbols:
        try:
            symbolx = symbol.replace('/','_')    # ETH/USDT => ETH_USDT
            csv_file = f'data/csv/article021/exchange/crypto({symbolx}).csv'  # crypto(ETH_USDT)
            header_list = ['close','high','low','open','status','time_stamp','volume','exchange','symbol','date']
            df = pd.read_csv(csv_file, names=header_list)
        except Exception as e:
            err_cnt += 1
            print(f'pd.read_csv({csv_file}) exception error: ', e)    
        else:    
            df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d %H:%M:%S')
            df_list.append(df)
    
    print('Number of exception occurred: ', '{:,}'.format(err_cnt))
    
    df = pd.concat(df_list, ignore_index=True, axis=0)
    
    # Fix symbol INCH-USDT => INCHUSDT
    df['symbol'] = df['symbol'].apply( lambda x: x.replace('-','').replace('_','') )
    
    # Sort by symbol(asc), exchange(asc), date(desc)
    df.sort_values(['symbol', 'exchange','date'], ascending=[True, True, False], inplace=True)
    dfx = df.groupby(['symbol','exchange']).first()
    dfx.reset_index(inplace=True)
    dfx['low']=0
    dfx['high']=0
    
    # Sort by symbol(asc), close(desc)
    dfx.sort_values(['symbol', 'close'], ascending=[True, False], inplace=True)
    
    # Update low, high
    dfx['low']  = dfx.groupby('symbol')['close'].transform('min')
    dfx['high'] = dfx.groupby('symbol')['close'].transform('max')
    
    dfx['high_exchange'] = dfx.groupby('symbol')['exchange'].transform('first')
    dfx['low_exchange'] = dfx.groupby('symbol')['exchange'].transform('last')
    
    dfx['high_symbol'] = dfx.groupby('symbol')['symbol'].transform('first')
    dfx['low_symbol'] = dfx.groupby('symbol')['symbol'].transform('last')
    
    dfx['price_diff'] = dfx['high'] - dfx['low']
    
    # Sort by price_diff(desc), symbol(asc), close(desc)
    dfx.sort_values(['price_diff', 'symbol', 'close'], ascending=[False, True, False], inplace=True)
    
    dfy = dfx.groupby(['symbol']).first()
    dfy.reset_index(inplace=True)
    
    # Sort by price_diff(desc)
    dfy.sort_values('price_diff', ascending=False, inplace=True)
    dfy.reset_index(inplace=True)
    
    dfz = dfy.drop(dfy[dfy.index >= 20].index)
    dfz.sort_values('price_diff', ascending=True, inplace=True)
    
    # Plot a horizontal bar chart
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo' 
    plt.style.use('fivethirtyeight')
    plt.figure(figsize=(15, 5)) # default width=6.4, hight=4.8 (15,5)
    
    rows = dfz.shape[0] - 1
    
    for index, row in dfz.iterrows():
        symbol = row['symbol']
        price = row['price_diff']
        low_exchange = row['low_exchange']
        high_exchange = row['high_exchange']
        #print(index, symbol, '{:.2f}'.format(price))
        plt.barh(symbol, price)
        plt.text(10, rows - index, 
            f'H({high_exchange}), L({low_exchange}), ' + '${:,.2f}'.format(price), 
            fontsize=10)      
    
    plt.ylabel('Crypto')
    plt.xlabel('Difference')
    plt.title('Price Differences Between Exchanges\n(USD)')
    plt.legend()
    plt.tight_layout()
    plt.show()
    

◆応用4【BinanceのAPIを使用して仮想通貨(暗号通貨)の価格をリアルタイムで表示するには】

  1. BinanceのAPIを使用してBTC/ETH/ADA/LTCの価格を1秒間隔でリアルタイムに表示する

    ここではBinanceが提供しているPythonのライブラリ「binance」を使用して仮想通貨(暗号通貨)の価格を取得して1秒間隔で線グラフに表示します。 BinanceのAPIを使用するには「API-KEY」と「API-SECRET-KEY」が必要になります。 これらの情報はBinanceにアカウントを作成すると無料で取得することができます。 BinanceのAPIを使用するには、「Client(api_key, api_secret, tld='us') 」を実行して「client」をセットアップします。 日本から使用するときは引数「tld='us'」を指定する必要があります。 デジタルの価格を取得するにはclientのget_historical_klines()メソッドを使用します。 このメソッドの引数1には仮想通貨(暗号通貨)のシンボル('BTCUSDT')、引数2に間隔('1m')、引数3には取得するデータの開始時刻('30 min ago UTC')を指定します。

    行2-3ではWindowsの環境変数に登録されているBinanceの「API_KEY」と「SECRET_KEY」を取得しています。 行6ではBinanceのAPIを使用するための「client」をセットアップしています。 行9ではget_historical_klines()メソッドで価格を取得しています。 get_historical_klines()の引数1には仮想通貨(暗号通貨)のシンボルを指定します。ここではBitcoinのシンボル「BTCUSDT」を指定しています。 引数2には価格を取得する間隔を指定しています。ここでは「1m」1分を指定しています。この場合、1分毎の価格が返されます。 引数3には価格を取得する開始時刻を指定します。ここでは「30 min ago UTC」を指定してUTC時間で今から30分前のデータから価格を取得しています。 例えば、現在の時刻が「17:30」だとすると「17:00」から「17:30」までの価格が1分刻みで返されます。 戻り値には「Date, Open, High, Low, Close, Volume,...」などが含まれます。
    # 1) GET Binance API-key / Secret Key
    api_key = os.environ.get('BINANCE_API_KEY')
    api_secret = os.environ.get('BINANCE_SECRET_KEY')
    
    # 2) Set up client
    client = Client(api_key, api_secret, tld='us') 
    
    # 3) Get price
    res = client.get_historical_klines('BTCUSDT', '1m', '30 min ago UTC')
    click image to zoom!
    Real Time Line chart

    
    
    
    # Import the necessary libraries  
    import os
    import time
    import pandas as pd
    from binance import Client # , ThreadedWebsocketManager, ThreadedDepthCacheManager # pip install python-binance
    import matplotlib.pyplot as plt
    import matplotlib.dates as mpl_dates
    import matplotlib.style as style
    from matplotlib.animation import FuncAnimation
    import datetime as dt
    from datetime import timedelta
    import calendar
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # 1) GET Binance API-key / Secret Key
    api_key = os.environ.get('BINANCE_API_KEY')
    api_secret = os.environ.get('BINANCE_SECRET_KEY')
    
    # 2) Set up client
    client = Client(api_key, api_secret, tld='us')  # tld='us' , testnet=True
    
    # Get crypto price via Binance API
    def get_crypto(symbol, interval, lookback):
        res = client.get_historical_klines(symbol, interval, lookback + ' min ago UTC')
        frame = pd.DataFrame(res)
        frame = frame.iloc[:,:6]
        frame.columns = ['Date','Open','High','Low','Close','Volume']
        frame = frame.set_index('Date')
        frame.index = pd.to_datetime(frame.index, unit='ms')        
        frame.index = frame.index + dt.timedelta(hours=9)   
        frame = frame.astype(float)
        return frame
    
    # Plot line chart
    def plot_line(dfx, ax, symbol, price):  # plot line char for Crypto              
        label = symbols_mapping[symbol]
        labelx = label + f' (USDT${price:,.2f})'
    
        ax.cla()
        ax.plot(dfx.index, dfx.Close, label=labelx)  
        ax.margins(x=0)      
        ax.tick_params(labelrotation=45)
        ax.set_ylabel('Closeing Price (USDT)')
        ax.set_title(f'Binance Cryptocurrency Price\n{dt.datetime.now().replace(microsecond=0)}')
        ax.legend(loc='upper left')
    
    def animate(i):   
        # Draw a line chart for BTC, ETC, ADA, LTC 
        for i, symbol in enumerate(symbols):
            #print(i, symbol)
            df = get_crypto(symbol, '1m', '30')
            time.sleep(1)
            dfx = df.tail(1)
            price = dfx['Close'].values[0]
            plot_line(df, axs[i], symbol, price)   
    
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  
    plt.style.use('seaborn')    # seaborn-ticks, seaborn-dark, seaborn-darkgrid, seaborn-whitegrid, classic      
    
    #fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(10,8)) # width(6.4), height(4.8)  18,9
    #axs = [ax1, ax2]
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, sharex=True, figsize=(14,7)) # width(6.4), height(4.8)  18,9
    axs = [ax1, ax2, ax3, ax4]
    
    #symbols = ['BTCUSDT', 'ETHUSDT'] 
    symbols = ['BTCUSDT', 'ETHUSDT', 'ADAUSDT', 'LTCUSDT'] 
    symbols_mapping = {
        'BTCUSDT': 'Bitcoin', 
        'ETHUSDT': 'Ethereum', 
        'ADAUSDT': 'Cardano', 
        'LTCUSDT': 'LiteCoin' 
    } 
    
    ani = FuncAnimation(fig, animate, interval=1000)    # blit=True DO NOT USE THIS!!!
     
    #fig.tight_layout() # DO NOT USE THIS!!!
    plt.show()