Python の標準モジュールtkinter でアプリを作る第二弾です。
作りたい機能は、打ち込まれたデータを読み取り、それを前処理してモデルに渡し、出力を表示するというものでした。
実務では、打ち込むデータが多いので、先にエクセルに入力してもらってエクセルからデータを取得して計算した方が作業が楽な雰囲気が出ています。
今回は、以下の機能を実装したいと思います。
- エクセルからデータを読み込む
- 読み込んだデータを計算する
- 計算結果を画面に表示する
計算部分は簡単でも複雑でも構造は同じなので、今回の記事中では簡単な計算にしておきます。
使用するデータ
Rに標準で入っているDavisデータを使用します。
個のデータは性別、身長、体重、再測定した身長、体重から構成されています。
以下のようにまとめられています。
データ 測定結果のグラフ
身長や体重の測定結果には、明らかに入力ミスと思われるデータもありますが、今回は最終行のデータを最新データと見なして使うので、気にしないことにします。
実際に使う時にはそのようなデータには警告を出すようにしたいものです。
アプリの実装
python のtkinter で実装します。前回の記事のものをベースにしていきます。
エクセルからデータを読み込む
エクセルデータを読み込むのはpandas で以下のように書けます。
1 2 3 4 5 6 7 8 |
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です。
1 |
bmi = int(x["weight"]/((x["height"]/100) **2)) |
計算結果を画面に表示する
計算ボタンを押すと、エクセルデータからBMIを計算し、BMI, 身長, 体重を表示するアプリを作ります。
tkinter のtreeview を使って、ボタンが押された時に上記3つのデータが出てくるようにします。
その名の通り、tree構造を持ったテキストを表示するライブラリですが、家計簿みたいに表示する事も出来るみたいです。以下を参考にしました。
treeview を使う部分は以下のように書けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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 で、データを挿入しています。変数の詳細については、公式の説明を見てください。
以上の処理をまとめると、以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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 を使った