Python の標準モジュールtkinter でアプリを作る第二弾です。
作りたい機能は、打ち込まれたデータを読み取り、それを前処理してモデルに渡し、出力を表示するというものでした。
実務では、打ち込むデータが多いので、先にエクセルに入力してもらってエクセルからデータを取得して計算した方が作業が楽な雰囲気が出ています。
今回は、以下の機能を実装したいと思います。
- エクセルからデータを読み込む
- 読み込んだデータを計算する
- 計算結果を画面に表示する
計算部分は簡単でも複雑でも構造は同じなので、今回の記事中では簡単な計算にしておきます。
使用するデータ
Rに標準で入っているDavisデータを使用します。
個のデータは性別、身長、体重、再測定した身長、体重から構成されています。
以下のようにまとめられています。
身長や体重の測定結果には、明らかに入力ミスと思われるデータもありますが、今回は最終行のデータを最新データと見なして使うので、気にしないことにします。
実際に使う時にはそのようなデータには警告を出すようにしたいものです。
アプリの実装
python のtkinter で実装します。前回の記事のものをベースにしていきます。
エクセルからデータを読み込む
エクセルデータを読み込むのはpandas で以下のように書けます。
import pandas as pd
file_name ="Davis.xlsx"
data = pd.ExcelFile(file_name)
sheet_name = data.sheet_names
sheet1 = data.parse(sheet_name=sheet_name[0])
x = sheet1.tail(1)
これでx に最新データ(最終行データ)が格納されます。ただし、Davis データはアプリと同じディレクトリにDavis.xlsx で保存されているとします。
1
エクセルデータは、シートを成分とするベクトルとして読み込まれます。そして、ベクトルの成分がシートに対応し、Dataframe として読み込まれています。
分ける必要も無いのにシート分けされてるエクセルデータも扱うことが出来ます。
読み込んだデータを計算する
実際には事前に作ってあるモデルから予測値を取得しますが、前処理から書くとコードが長いので、慎重と体重からBMIを計算するとします。
計算式はBMI = 体重(kg)/(身長(m) )^2です。
bmi = int(x["weight"]/((x["height"]/100) **2))
計算結果を画面に表示する
計算ボタンを押すと、エクセルデータからBMIを計算し、BMI, 身長, 体重を表示するアプリを作ります。
tkinter のtreeview を使って、ボタンが押された時に上記3つのデータが出てくるようにします。
その名の通り、tree構造を持ったテキストを表示するライブラリですが、家計簿みたいに表示する事も出来るみたいです。以下を参考にしました。
treeview を使う部分は以下のように書けます。
colname = ["BMI", "身長", "体重"]
tree = ttk.Treeview(self)
tree["columns"] = colname
tree["show"] = "headings"
for i,_ in enumerate(colname):
tree.column(i, width=75)
tree.heading(i,text=colname[i])
tree_data=(bmi, int(x["height"].values), int(x["weight"].values) )
tree.insert("","end",values= tree_data )
tree.grid()
tree[“columns”] で列が何列あるか指定しています。for文でデータを入れる場所の大きさと、列名を指定しています。最後に、tree.insert で、データを挿入しています。変数の詳細については、公式の説明を見てください。
以上の処理をまとめると、以下になります。
class App(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.tree = None
self.grid()
self.create_widgets()
def create_widgets(self):
#計算ボタン
self.calc = tk.Button(self)
self.calc["text"] = "計算"
self.calc["command"] = self.calc_BMI
#lambda :self.preprocess(self.master.clipboard_get() )
self.calc.grid(row=1, columns=1, padx=5, pady=5, columnspan = 2)
"""""
#キャンセルボタン
self.quit = tk.Button(self, text="キャンセル")
self.quit["command"] = self.master.destroy
self.quit.grid(row=2, columns=1, padx=5, pady=5)
"""
def calc_BMI(self):
if not self.tree == None:
self.tree.destroy()
file_name ="Davis.xlsx"
data = pd.ExcelFile(file_name)
sheet_name = data.sheet_names
sheet1 = data.parse(sheet_name=sheet_name[0])
colname = ["BMI", "身長", "体重"]
x= sheet1.tail(1)
bmi = int(x["weight"]/((x["height"]/100) **2))
self.tree = ttk.Treeview(self)
self.tree["columns"] = colname
self.tree["show"] = "headings"
for i,_ in enumerate(colname):
self.tree.column(i, width=75)
self.tree.heading(i,text=colname[i])
tree_data=(bmi, int(x["height"].values), int(x["weight"].values) )
self.tree.insert("","end",values= tree_data )
self.tree.grid()
root = tk.Tk()
root.geometry("640x480")
app=App(master=root)
app.mainloop()
計算ボタンを押すと、calc_BMIが実行されます。calc_BMI でtree_viewが生成され、
実行して、計算ボタンを押すと以下のような画面になります。2
まとめ
- エクセルからデータを読みこんだ
- 計算結果を表示するために、ttk.treeview を使った