環境システム株式会社公式HP

〒660-0083 兵庫県尼崎市道意町7-1-3
尼崎リサーチ・インキュベーションセンター512

アイコン06-6657-5130

アイコンsales@hydrolab.co.jp

お問い合わせ

アイコン06-6657-5130

アイコンsales@hydrolab.co.jp

お問い合わせ

蛇使いな彼女BLOG

【第48回】 PysimpleGUIを使ったアプリケーション作成

2021.12.17

こんにちは、皆さん♪
今日は簡単なGUIアプリケーションを作ってみたいと思います!

GUI?何それ?って人のために一応解説をすると、GUI(グラフィカルユーザーインターフェース)とはコンピューターに処理をさせる際に、パソコンの画面にアイコンやウィンドウ、ボタンなどを表示させ、マウスで操作できるようにした形式のことです。

プログラミング知識のない人でも簡単に扱えるような形式、つまり一般的なアプリケーションの事です(*^_^*)

今まで紹介したコードの中にファイル選択操作やダイアログ表示によく使っている ですがtkinterのコーディングルールが優しくないので、それより使いやすいPySimpleGUIを紹介しますね!

今回は以下のようなcsvファイルを読み込んで、この項目(列)ごとに時系列グラフを描いて保存するというアプリケーションです。

このcsvデータですが、前回から紹介しているbs4を使ってhtmlファイルをcsvに変換したものです。
【全コード掲載--fig: carbon12-1(全文)】

コード全体は長いので、前半後半に分けて解説していこうかと思います。
前半部分はライブラリのインポートと、上のcsvの項目を1つ1つ図化するコードです。ポイントごとに解説をしていきます(^^)

13行目の以下の記述
plt.rcParams['font.family'] =
'Meiryo'
ですが、一括でmatplotlib のフォント指定を行います。
日本語をフォローしているフォントを指定してやることで、matplotlib で日本語表記が豆腐に文字化けするのを防げます。

また関数のplot_fig()の引数、filepath,Pathですがこれは後半のGUIで受け取った入力を受け取ります。
それを踏まえて中身を見ていきます。

センテンス(1)

# 読み込んだデータを図化する処理
def plot_fig(filepath,Path):

df=pd.read_csv(filepath,delimiter=',',skipinitialspace=True,index_col=0,
header=0,parse_dates=True)
os.makedirs(Path+'result_fig',exist_ok=True)
AC=Path+'result_fig'


まず、read_csvでfilepathで受けたcsvデータを読み込みます。パラメータのparse_dates=Trueにすると系列データとして読み込みを行ってくれます。
次に、os.makedirs()で「result_fig」という名前の新規ディレクトリの作成を行います。
このディレクトリに作成した図を保存します。
パラメータのexist_ok=Trueにすると(デフォルトはFalseです)、すでに存在しているディレクトリを指定した場合に表示されるエラーを無視できます。

センテンス(2)

# 時系列グラフ
for n,k in enumerate(df.columns): # 項目毎にplot

fig, ax = plt.subplots(1,1,figsize=(12, 8), sharex=False)
cmap = plt.get_cmap("tab10")
#ax.set_title('{}'.format(df.columns[0]),fontsize=14)

d = mdates.date2num(df.index) # 時刻データを変換


csvデータの列ごとに図化処理を行います。
plt.subplots()で作成した白紙のグラフから、fig、axでグラフエリアとプロットエリアを別々に受けます。
cmapは系列の色分けに使うカラーセットです。今回は「tab10」の10色のセットを指定しました。
また、mdates.date2num()でpandasの時刻データをmatplotlib の日付に変換しておきます。
この作業を行わないとxラベルが日付表示にならなかったり、後の作業で詰まります💦

センテンス(3)

次に、以下のようにして日付ラベルのメモリ数を調整します。

[図解]

# x軸(日付の設定)
split_id=np.linspace(0,len(df.index)-1,10)
xticks=[int(Decimal(l).quantize(Decimal('1'),
rounding=ROUND_HALF_EVEN)) for l in split_id]
xtick_label=[dt.datetime.strftime(df.index[i],"%m/%d %H:%M") for i in xticks]



split_id=np.linspace(0,len(df.index)-1,10)
np.linspace()は開始から終了までを等間隔にしたときの配列を返します。
ここでは、0からスタートとしたときの時刻データの個数を10等分したときの配列。
つまりインデックスに当たります。

xticks=[int(Decimal(l).quantize(Decimal('1'),
rounding=ROUND_HALF_EVEN)) for l in split_id]
返ってきた配列はfloat型なので、Decimalを使って 1の位で四捨五入を行います。

xtick_label=[dt.datetime.strftime(df.index[i],"%m/%d %H:%M") for i in xticks]
日付データをdatetimeから文字列に変換しつつ、先ほど作成したインデックスにあてはめると、全体を10等分したラベルのできあがりです!

センテンス(4)

ax.set_ylabel(k,fontsize=14)
ax.set_xlabel('date',fontsize=14)

mv=int(df[k].max()+1)
ax.set_ylim(0, mv)
ax.plot(d, df[k].values,lw=1.5, color=cmap(n), label=k) # ax1 = axes[0,0]
ax.xaxis.set_major_locator(ticker.LinearLocator(numticks=10))
ax.set_xticklabels(xtick_label,rotation=0)
ax.legend()


センテンス(4)は見ての通り、グラフの描画と軸のラベル、凡例の表示設定等を行っています。
ax.xaxis.set_major_locator(ticker.LinearLocator(numticks=10))
この部分についてですが、major_locator で主目盛り(大目盛り)を振る位置を決めます。
どうやって位置を決めるかは()の中に記載します。ここではLinearLocatorによってx軸を10等分する位置に主目盛りを置いています。
センテンス(3)の目盛りラベルを探す際にもsplit_id=np.linspace(0,len(df.index)-1,10)で10等分していますよね(^^)
目盛りの数を自由に設定したいとき、目盛りのズレを最小限に抑えるためには、このように分割個数を同じにする必要があります。

センテンス(5)

k=k.replace('/','-')
fig.savefig(AC+"/{}.png".format(k), bbox_inches="tight", pad_inches=0.05)


最後にグラフの保存を行います。
Kは項目名ですが、単位に(μS/cm)など、「/」が入ったままだとパスの表記と被ってしまいエラーになるのでreplaceで置き換えます。
‘{}’.format()で変数に入っている文字列を{}の中に展開します。
bbox_inches="tight", pad_inches=0.05で余白の調整を行います。

長くなりましたが、これまでのおさらいも含めて図化の部分を説明しました☆
次回はお楽しみのGUI部分に移ります♪

pagetop