pythonで時系列の線グラフを作る
Pythonを使って上のようなグラフを作る
前回はヒストグラムだったが今回は線グラフ
mecobalamin.hatenablog.com
元のデータは以下のようなCSV形式
Date, a, b, c, d 2020/11/24 16:42:20, 143, 101, 63, 2020/11/24 17:27:19, 137, 101, 65, 2020/11/25 06:31:48, 134, 90, 65, 2020/11/25 11:21:57, 142, 109, 67, 2020/11/25 14:06:42, 131, 94, 74, 2020/11/25 18:54:18, 120, 91, 69, 2020/11/25 20:42:53, 114, 78, 72, 2020/11/26 09:09:53, 113, 84, 76, 2020/11/26 09:17:28, 125, 70, 70, 1021.67 2020/11/26 16:12:06, 126, 89, 65, 1019.64 2020/11/27 06:37:47, 117, 81, 69, 1020.66 2020/11/27 13:31:37, 123, 88, 98, 1019.98 2020/11/27 14:22:03, 126, 86, 89, 1019.64 2020/11/27 17:58:24, 120, 86, 84, 1020.32 2020/11/27 19:35:42, 116, 81, 81, 1021
1行目はヘッダーで
2行目以降がデータになっている
データの型は
1列目に日付と時間、2-4列目は整数、
5列目は浮動小数点数である
スクリプトの流れはこのようにした
また、ファイルを読み込むクラスと
グラフを作成するクラスを定義した
クラスの作成にはこちらの記事を参考にした
Pythonのオブジェクト指向プログラミングを完全理解 - Qiita
1. 定数の定義
まず入力するCSVファイル名やディレクトリを定義する
出力する画像ファイルに日付を付けるため、
日付から数字の文字列を作成する
date_today = datetime.date.today() day_save_file = str(date_today.year) + str(date_today.month).zfill(2) + str(date_today.day).zfill(2)
zfill()は0埋めをするメソッド
2. 出力するディレクトリの作成
ReadFiles().get_current_path()
スクリプトのあるディレクトリに
グラフを保存するディレクトリを作成する
os.getcwd()、os.chdir()でスクリプトのあるディレクトリを
作業ディレクトリに変更する
ReadFiles().create_directories()
作業ディレクトリにグラフ画像を保存するディレクトリを作成するが
try文を使ってディレクトリの有無を確認している
3. CSVファイルの読み込み
ReadFiles().read_files()
CSVファイルの読み込みにも
try文を使ってファイルが開けなかった場合の
エラーコードを表示させている
ファイルの読み込みには
pandasのread_csv()を使って
CSVをDataFrameとして読み込む
4. 1列目の型変換
読み込んだデータの1列目は日付と時間だが
データの型は文字列になっている
print(type(df['Date'][1])) <class 'str'>
to_datetime()を使って型を変換する
df['Date'] = pd.to_datetime(df['Date'])
変換するとTimestampになる
print(type(df['Date'][1])) <class 'pandas._libs.tslibs.timestamps.Timestamp'>
5. グラフの作成
読み込んだDataFrameからグラフを作る
CreateGraphs(df).create_line_graph()
まだ理解がぼんやりしているが
CreateGraphs(df)でインスタンスを作成し、
create_line_graph()のメソッドを呼び出している
ということになるらしい
create_line_graph()でグラフを描画する
twinx()で左右に軸を描いている
plt.ylim()が2度で使われている
最初のが左のy軸で次のが右のy軸になる
plt.ylim()の次に実行する
ax1.plot()及びax2.plot()のylim()を変更している
同じコマンドなので理解に時間がかかった
plot()のあとに軸の書き換えをするのに慣れない
パラメータを決めて一度に図を描画するのではなく
コマンドを追加して次々に書き換えていく
なのでplot()コマンドを最後にするものだと
思い込んでいたがそうでもなかった
描画したグラフはpngファイルとして保存される
plt.savefig(path_output_dir + '\\' + output_graph_name)
スクリプト全文は以下のようになる
元のデータをpython_sample.csvとして
スクリプトと同じディレクトリに保存し
スクリプトを実効するとグラフを作れる
# -*- coding: utf-8 -*- import os, sys, datetime from pandas import Series, DataFrame import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates class ReadFiles: def __init__(self): pass def get_current_path(self): current_path = os.getcwd() current_path = os.chdir(os.path.dirname(os.path.abspath(__file__))) current_path = os.getcwd() return(current_path) def create_directories(self, path_to_dir): try: os.makedirs(path_to_dir) except FileExistsError: pass def read_files(self, path_to_file): print('open a csv file.') try: df = pd.read_csv(path_to_file) except Exception as e: print('cannot open file: ', path_to_file) print(str(e)) sys.exit(1) else: print('Success!') return(df) class CreateGraphs: def __init__(self, graph_data): self.graph_data = graph_data def create_line_graph(self): print('Create line plot') df = self.graph_data fig, ax1 = plt.subplots() plt.subplots_adjust(left=0.125, right=0.9, bottom=0.3, top=0.9) plt.ylim(50, 200) ax1.plot(df.index, df.iloc[:, 0], linestyle = '-', marker = 'o', color = 'r', label = df.columns[0]) ax1.plot(df.index, df.iloc[:, 1], linestyle = ':', marker = '.', color = 'b', label = df.columns[1]) ax1.plot(df.index, df.iloc[:, 2], linestyle = '--', marker = 's', color = 'y', label = df.columns[2]) ax2 = ax1.twinx() plt.ylim(1000, 1030) ax2.plot(df.index, df.iloc[:, 3], linestyle = ':', marker = '+', color = 'gray', label = df.columns[3]) locator = mdates.AutoDateLocator() formatter = mdates.DateFormatter('%m/%d') ax1.set_xticklabels(df.index, rotation = 90) ax1.xaxis.set_major_locator(locator) ax1.xaxis.set_major_formatter(formatter) handles1, labels1 = ax1.get_legend_handles_labels() handles2, labels2 = ax2.get_legend_handles_labels() ax1.legend(handles1 + handles2, labels1 + labels2, loc = 'upper left') if __name__ == '__main__': date_today = datetime.date.today() day_save_file = str(date_today.year) + str(date_today.month).zfill(2) + str(date_today.day).zfill(2) input_file_name = 'python_sample.csv' output_dir_name = 'graph' output_graph_name = day_save_file + '_graph_sample.png' path_input_file = ReadFiles().get_current_path() + '\\' + input_file_name path_output_dir = ReadFiles().get_current_path() + '\\' + output_dir_name + '\\' ReadFiles().create_directories(path_output_dir) df = ReadFiles().read_files(path_input_file) df['Date'] = pd.to_datetime(df['Date']) df = df.set_index('Date') CreateGraphs(df).create_line_graph() plt.savefig(path_output_dir + '\\' + output_graph_name) plt.close() print('Operation completed')