解析エンジニアの自動化 blog

コツコツと自動化した方法を残す blog

Python の matplotlib の描画速度を計測した



こんにちは。
仕事の自動化にやりがいと達成感を感じるガッくんです。


この記事の目次



背景・目的


Python で色々な分析結果をグラフにしたいのですが、 matplotlib の描画スピードがとても遅かったので、どんな使い方をすれば良いのか検証しました。



動作環境


Windows 7
・winpython 64bit 3.4.4



入力データ

読み込むデータは Excel で作成しました。

Excel の 10,48,576 行を全て使いました。

Data1 〜 Data5 は以下の関係性を持たせています。

Data1 = No. / 10,000
Data2 = cos(radians(Data1))
Data3 = sin(radians(Data1))
Data4 = 2*cos(radians(Data1))
Data5 = 2*sin(radians(Data1))

そして、 Excel から csv 出力したファイルを作成しました。

図1 入力データ



プログラム

2つのソースコードを準備しました。

ソースコード
dask で csv ファイルを読み込んで matplotlib でグラフを描画するプログラム

ソースコード
dask で csv ファイルを読み込んで dask.dataframe を numpy 配列に変換してから matplotlib でグラフを描画するプログラム

2つのソースコードは matplotlib に入れる値が dask.dataframe か numpy 配列かの違いがあります。

ソースコード

dask で csv ファイルを読み込んで matplotlib でグラフを描画するプログラム


###############################################################################
# グラフの描画時間を計測するプログラム
###############################################################################
# インポート
from time import time
import dask.dataframe as dd
import matplotlib.pyplot as plt
 
# 時間計測関数
def calc_time(func):
    start = time()
    r = func()
    return{'value':r, 'time':time()-start}
 
# 表題行 + 1,048,575 行のデータ
file_dir  = 'C:\\Users\\UserName\\Desktop\\'
file_name = 'driven_test'
 
# ファイル読み込み
ddf = calc_time(lambda:dd.read_csv(file_dir + file_name + '.csv', header=0,
                                   names=('No.', 'Date', 'Data1', 'Data2', 'Data3', 'Data4', 'Data5')))
print('データ読込時間 : ' + str(ddf['time']) + ' sec')
all_time = ddf['time']
 
# グラフの描画
graph = calc_time(lambda:plt.plot(ddf['value']['No.'], ddf['value']['Data2']))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
graph = calc_time(lambda:plt.plot(ddf['value']['No.'], ddf['value']['Data3']))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
graph = calc_time(lambda:plt.plot(ddf['value']['No.'], ddf['value']['Data4']))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
graph = calc_time(lambda:plt.plot(ddf['value']['No.'], ddf['value']['Data5']))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
# 画像の出力
output = calc_time(lambda:plt.savefig(file_dir + file_name + '0.0.jpg', bbox_unches="tight"))
print('グラフ出力時間 : ' + str(output['time']) + ' sec')
all_time += output['time']
 
print('合計時間 : ' + str(all_time) + ' sec')



ソースコード

dask で csv ファイルを読み込んで dask.dataframe を numpy 配列に変換してから matplotlib でグラフを描画するプログラム


###############################################################################
# グラフの描画時間を計測するプログラム
###############################################################################
# インポート
from time import time
import dask.dataframe as dd
import numpy as np
import matplotlib.pyplot as plt
 
# 時間計測関数
def calc_time(func):
    start = time()
    r = func()
    return{'value':r, 'time':time()-start}
 
# 表題行 + 1,048,575 行のデータ
file_dir  = 'C:\\Users\\UserName\\Desktop\\'
file_name = 'driven_test'
 
# ファイル読み込み
ddf = calc_time(lambda:dd.read_csv(file_dir + file_name + '.csv', header=0,
                                   names=('No.', 'Date', 'Data1', 'Data2', 'Data3', 'Data4', 'Data5')))
print('データ読込時間 : ' + str(ddf['time']) + ' sec')
all_time = ddf['time']
 
ex = calc_time(lambda:np.array(ddf['value']))
print('データ変換時間 : ' + str(ex['time']) + ' sec')
all_time += ex['time']
 
graph = calc_time(lambda:plt.plot(ex['value'][0:,0], ex['value'][0:,3]))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
graph = calc_time(lambda:plt.plot(ex['value'][0:,0], ex['value'][0:,4]))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
graph = calc_time(lambda:plt.plot(ex['value'][0:,0], ex['value'][0:,5]))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
graph = calc_time(lambda:plt.plot(ex['value'][0:,0], ex['value'][0:,6]))
print('グラフ作成時間 : ' + str(graph['time']) + ' sec')
all_time += graph['time']
 
# 画像の出力
output = calc_time(lambda:plt.savefig(file_dir + file_name + '0.1.jpg', bbox_unches="tight"))
print('グラフ出力時間 : ' + str(output['time']) + ' sec')
all_time += output['time']
 
print('合計時間 : ' + str(all_time) + ' sec')



結果

numpy 配列に変換する処理に時間をさいても dask で csv ファイルを読み込んで dask.dataframe を numpy 配列に変換してから matplotlib でグラフを描画するプログラムのほうが速い結果となりました。

値の処理計算も numpy 配列が速いですし、当たり前といえば当たり前の結果でした。

作成したグラフももちろん同じモノが出来上がりました。

ソースコード①の結果


In [1]: runfile('C:/WinPython-64bit-3.4.4.6Qt5/settings/.spyder-py3/graph0.0.py', wdir='C:/WinPython-64bit-3.4.4.6Qt5/settings/.spyder-py3')
データ読込時間 : 0.01200103759765625 sec
グラフ作成時間 : 3.650207996368408 sec
グラフ作成時間 : 3.7332139015197754 sec
グラフ作成時間 : 3.2911880016326904 sec
グラフ作成時間 : 3.101177930831909 sec
グラフ出力時間 : 0.8210470676422119 sec
合計時間 : 14.608835935592651 sec


図2 ソースコード①のグラフ


ソースコード②の結果


In [1]: runfile('C:/WinPython-64bit-3.4.4.6Qt5/settings/.spyder-py3/graph0.1.py', wdir='C:/WinPython-64bit-3.4.4.6Qt5/settings/.spyder-py3')
データ読込時間 : 0.01100015640258789 sec
データ変換時間 : 1.9661130905151367 sec
グラフ作成時間 : 0.18301010131835938 sec
グラフ作成時間 : 0.13800787925720215 sec
グラフ作成時間 : 0.1370079517364502 sec
グラフ作成時間 : 0.14200782775878906 sec
グラフ出力時間 : 0.4520261287689209 sec
合計時間 : 3.0291731357574463 sec


図3 ソースコード②のグラフ



コメント

本来であればデータの読み込みからグラフを描画する間にデータの加工や分析処理が入ると思います。

なので、データの加工や分析処理を考えるとデータは読み込んだら numpy 配列に変換して持っておくのが良さそうだということが分かりました。



以上