データ処理を行う方はcsvファイルを元にグラフを作成する方が多いと思います。グラフ作成アプリ自体は多くありますが、自分の好みに応じて体裁を設定可能なものがなかったので作成してみました。Windowsの方は、exeファイルを用いれば追加の環境設定は不要です。
実行ファイル
実行ファイル(.exe)をzip化したものになります。exe化には「cx_Freeze」を用いました。exeファイルはGoogle driveのリンクを貼ります。buildファイルがzip圧縮されたものなので、お使いのWindows環境で展開してください。(環境によっては上手く動作しない場合もあります。その場合はpythonのexe化の記事を参考にしてアプリを作成してみてください。)
(作成したアプリへのリンクはこちら)
テストデータとして用いた「tabledata.csv」も載せておきます。
操作例
Excelよりも簡単にグラフ作成可能
Excelファイルを開いてデータ列を選ぶだけ
上のような表形式のExcelデータ(拡張子.csv)を例にグラフ作成テストを行いました。1行目がヘッダ(見出し)で、2行目以降が各データになります。
動画にあるように、ファイルを選択するとデータが読み込まれるので(①)、X軸・Y軸にするデータを選択して(②)、「Scatter Plot」を選択すれば散布図の出来上がりです(③)。
「Scatter Plot」を繰り返し押すと重ね描きされていくので、前のプロットを消したい場合にはリセットボタンを押します(④)。グラフの体裁を調整したい場合は左下のオプションを調整します(⑤)。
(グラフの体裁オプションを変更してプロットした後で、再び体裁を変更しても反映されない場合があります。その場合は体裁オプションを修正した後で一度グラフ初期化(④)を行います。)
Data1,Data2があるのは、フォーマットが違うファイルからプロットできるようにするためです。(Data1でも同じ形式であれば複数ファイルを選択できますが、形式が違うとエラーが生じます。)
実現したかったこと
私が本プログラムを作成したのは、Excelでグラフを作成して体裁を整えるのが面倒くさいと思ったことがきっかけです。
Excelマクロを使ったりPythonなどの言語でプログラムを書くことはできるのですが、
・ちょっとX軸・Y軸データからグラフを書きたい、
・でも発表スライドに載せられるくらいの体裁は整えたい
と思うことが大学・会社で度々ありました。
もちろん世の中にはExcelで扱うcsvファイルからグラフを作成するツールがいくつも存在していますが、
・確認用には使えるものの体裁が整っていないグラフを作成するツール
・体裁の整ったグラフは作成できるものの設定する条件の多いツール
などが多いと感じました。
大学の研究室ではIgorという有料ソフトを用いており、マクロ機能を使って複雑なグラフも作成可能でしたが、多くの方はそこまで多くの機能がなくても、きれいなグラフを簡単にかけるフリーソフトがあれば十分だと思いました。
Python環境がある方は以前のカラープロットの記事のようにコードを書くことでグラフをかけますが、毎回似たようなグラフを描くならexeファイルのほうが断然簡単だと思います。
手法: PythonのTkinter
機械学習などで近年多く使用されているPythonというプログラミング言語でGUIを作成するツール「Tkinter」を用いました。視覚的に操作できるようにすることで、どなたでも使えるようになると良いと思いました。
ソースコード
今回用いたソースコードを以下に載せます。
#Copyright (C) 2022 てるみかん. All rights reserved.
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.filedialog as tkfd
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib.pyplot as plt
import matplotlib.colors as clr
import matplotlib.markers as mkr
import pandas as pd
import numpy as np
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.master.title('2D_plot')
self.pack()
self.color_list = clr.cnames
self.color_list_pickup={ 'black': '#000000', 'blue': '#0000FF', 'brown': '#A52A2A', 'cyan': '#00FFFF', 'gold': '#FFD700', 'gray': '#808080', 'green': '#008000', 'magenta': '#FF00FF', 'navy': '#000080', 'orange': '#FFA500', 'pink': '#FFC0CB', 'purple': '#800080', 'red': '#FF0000', 'white': '#FFFFFF','yellow': '#FFFF00'}
self.marker_list = mkr.MarkerStyle().markers
self.create_widgets()
self.dict_data_frame = {}
self.selected_data = []
self.init_status_bar()
self.master.bind('<Control-v>', self.scatter_plot(self.entry1,self.num1))
self.master.bind('<Control-V>', self.scatter_plot(self.entry1,self.num1))
self.master.bind('<Control-c>', self.scatter_plot(self.entry1,self.num1))
self.master.bind('<Control-C>', self.scatter_plot(self.entry1,self.num1))
def click_x1_set_button(self):
self.x1_data_box.delete(0, tk.END)
if not self.selected_data:
self.status_bar_str.set('Select data from Data List')
return
self.group_data_name_str_x1 = ','.join(self.selected_data[-1])
self.x1_data_box.insert(tk.END, self.group_data_name_str_x1)
def click_y1_set_button(self):
self.y1_data_box.delete(0, tk.END)
if not self.selected_data:
self.status_bar_str.set('Select data from Data List')
return
self.group_data_name_str_y1 = ','.join(self.selected_data[-1])
self.y1_data_box.insert(tk.END, self.group_data_name_str_y1)
def click_x2_set_button(self):
self.x2_data_box.delete(0, tk.END)
if not self.selected_data:
self.status_bar_str.set('Select data from Data List')
return
self.group_data_name_str_x2 = ','.join(self.selected_data[-1])
self.x2_data_box.insert(tk.END, self.group_data_name_str_x2)
def click_y2_set_button(self):
self.y2_data_box.delete(0, tk.END)
if not self.selected_data:
self.status_bar_str.set('Select data from Data List')
return
self.group_data_name_str_y2 = ','.join(self.selected_data[-1])
self.y2_data_box.insert(tk.END, self.group_data_name_str_y2)
def init_status_bar(self):
self.status_bar_str = tk.StringVar()
self.status_bar = tk.Label(self.master,
textvariable=self.status_bar_str,
bd=1, relief=tk.SUNKEN,
anchor=tk.W)
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
self.status_bar_str.set('')
def init_data_list(self):
self.data_list_label = tk.Label(text='Data List')
self.data_list_label.pack()
container = ttk.Frame()
container.pack(fill=tk.BOTH, expand=True)
data_header = ['Data group', 'Data name', 'Max', 'Min', 'Mean', 'Sigma']
self.data_list = ttk.Treeview(columns=data_header, show='headings')
self.data_list.column(2, width=100)
self.data_list.column(3, width=100)
self.data_list.column(4, width=100)
self.data_list.column(5, width=100)
v_scrollbar = ttk.Scrollbar(orient='vertical', command=self.data_list.yview)
h_scrollbar = ttk.Scrollbar(orient='horizontal', command=self.data_list.xview)
self.data_list.configure(xscrollcommand=h_scrollbar.set,
yscrollcommand=v_scrollbar.set)
self.data_list.grid(column=0, row=0, sticky='nsew', in_=container)
v_scrollbar.grid(column=1, row=0, sticky='ns', in_=container)
h_scrollbar.grid(column=0, row=1, sticky='ew', in_=container)
container.grid_columnconfigure(0, weight=3)
container.grid_rowconfigure(0, weight=1)
for column in data_header:
self.data_list.heading(column, text=column.title())
def insert_data_frame(self, df, path):
group_name = path.split('/')[-1]
if not self.dict_data_frame.keys():
self.dict_data_frame[group_name] = df
else:
last_group_name = list(self.dict_data_frame.keys())[-1]
last_df = self.dict_data_frame[last_group_name]
last_df_columns = last_df.columns.values.tolist()
add_df_columns = df.columns.values.tolist()
if last_df_columns == add_df_columns:
self.dict_data_frame[last_group_name] = pd.concat([self.dict_data_frame[last_group_name], df])
else:
self.dict_data_frame[group_name] = df
def insert_data_list(self):
for group_name in list(self.dict_data_frame.keys()):
single_df = self.dict_data_frame[group_name]
single_df_columns = single_df.columns.values.tolist()
for column in single_df_columns:
# calculate max, min, ave and sigma of each value
data = single_df[column]
max_value = round(float(np.max(data)), 2)
min_value = round(float(np.min(data)), 2)
mean_value = round(float(np.mean(data)), 2)
sigma_value = round(float(np.std(data)), 2)
self.data_list.insert('', 'end', values=(group_name, column, max_value,
min_value, mean_value, sigma_value))
# binding event
self.data_list.bind('<<TreeviewSelect>>', self.select_data_from_list)
def select_data_from_list(self, event):
widget = event.widget
self.selected_data = []
for index in widget.selection():
data_group_name = widget.item(index)['values']
self.selected_data.append(data_group_name)
self.status_bar_str.set('')
def create_widgets(self):
#----------------------plot1-------------------------------------------------------------------------
self.Frame1 = tk.Frame(self.master)
self.Frame1.pack(side=tk.TOP)
self.num1=1
self.Button11 = tk.Button(self.Frame1, text="Data1", command=lambda: [self.read_csv_file(self.entry1)])
self.Button11.pack(side=tk.LEFT)
self.entry1 = tk.Entry(self.Frame1, width=100)
self.entry1.pack(side=tk.LEFT)
self.Button12 = tk.Button(self.Frame1, text="Scatter Plot", command=lambda: self.scatter_plot(self.entry1,self.num1))
self.Button12.pack(side=tk.LEFT)
self.Button13 = tk.Button(self.Frame1, text="Line Plot", command=lambda: self.line_plot(self.entry1,self.num1))
self.Button13.pack(side=tk.LEFT)
#----------------------plot2-------------------------------------------------------------------------
self.Frame2 = tk.Frame(self.master)
self.Frame2.pack(side=tk.TOP)
self.Button21 = tk.Button(self.Frame2, text="Data2", command=lambda: [self.read_csv_file(self.entry2)])
self.Button21.pack(side=tk.LEFT)
self.entry2 = tk.Entry(self.Frame2, width=100)
self.entry2.pack(side=tk.LEFT)
self.Button22 = tk.Button(self.Frame2, text="Scatter Plot", command=lambda: self.scatter_plot(self.entry2,self.num2))
self.Button22.pack(side=tk.LEFT)
self.Button23 = tk.Button(self.Frame2, text="Line Plot", command=lambda: self.line_plot(self.entry2,self.num2))
self.Button23.pack(side=tk.LEFT)
#---------------------- Frame3 -------------------------------------------------------------------------
self.Frame3 = tk.Frame(self.master)
self.Frame3.pack(side=tk.TOP)
# x data set
self.x1_data_button = tk.Button(self.Frame3,text='Data1 X', command=self.click_x1_set_button)
self.x1_data_button.grid(row=0, column=0)
self.x1_data_box = tk.Entry(self.Frame3,width=22)
self.x1_data_box.grid(row=0, column=1)
# y data set
self.y1_data_button = tk.Button(self.Frame3,text='Data1 Y', command=self.click_y1_set_button)
self.y1_data_button.grid(row=0, column=2)
self.y1_data_box = tk.Entry(self.Frame3,width=22)
self.y1_data_box.grid(row=0, column=3)
# x2 data set
self.x2_data_button = tk.Button(self.Frame3,text='Data2 X', command=self.click_x2_set_button)
self.x2_data_button.grid(row=0, column=4)
self.x2_data_box = tk.Entry(self.Frame3,width=22)
self.x2_data_box.grid(row=0, column=5)
# y data set
self.y2_data_button = tk.Button(self.Frame3,text='Data2 Y', command=self.click_y2_set_button)
self.y2_data_button.grid(row=0, column=6)
self.y2_data_box = tk.Entry(self.Frame3,width=22)
self.y2_data_box.grid(row=0, column=7)
# ボタンをフレームに配置
self.btn_open_folder = tk.Button(self.Frame3, text="Graph Reset",command = lambda:self.clear_graph())#, image = self.ico_open_file)
self.btn_open_folder.grid(column=8, row=0) # 左側だけ隙間を空ける
#----------------------Data_List-------------------------------------------------------------------------
self.Frame5 = tk.Frame(self.master)
self.Frame5.pack(expand=True,side=tk.TOP,fill=tk.BOTH)
self.data_list_label = tk.Label(self.Frame5,text='Data List')
container = ttk.Frame(self.Frame5)
container.pack(fill=tk.BOTH)
data_header = ['Data group', 'Data name', 'Max', 'Min', 'Mean', 'Sigma']
self.data_list = ttk.Treeview(self.Frame5,columns=data_header, show='headings')
self.data_list.column(2, width=60)
self.data_list.column(3, width=60)
self.data_list.column(4, width=60)
self.data_list.column(5, width=60)
v_scrollbar = ttk.Scrollbar(self.Frame5,orient='vertical', command=self.data_list.yview)
h_scrollbar = ttk.Scrollbar(self.Frame5,orient='horizontal', command=self.data_list.xview)
self.data_list.configure(xscrollcommand=h_scrollbar.set,
yscrollcommand=v_scrollbar.set)
self.data_list.grid(column=0, row=0, sticky='nsew', in_=container)
v_scrollbar.grid(column=1, row=0, sticky='ns', in_=container)
h_scrollbar.grid(column=0, row=1, sticky='ew', in_=container)
container.grid_columnconfigure(0, weight=3)
container.grid_rowconfigure(0, weight=1)
for column in data_header:
self.data_list.heading(column, text=column.title())
#----------------------Data_List-------------------------------------------------------------------------
self.Frame6 = tk.Frame(self.master)
self.Frame6.pack(expand=True,side=tk.TOP)
# graph title
self.graph_title_label = tk.Label(self.Frame6,text='Graph Title')
self.graph_title_label.grid(column=0, row=0)
self.graph_title = tk.Entry(self.Frame6,width=12)
self.graph_title.grid(column=1, row=0)
self.graph_title.insert(tk.END,"Title")
# x_axis title
self.x_axis_title_label = tk.Label(self.Frame6,text='X_axis Title')
self.x_axis_title_label.grid(column=2, row=0)
self.x_axis_title = tk.Entry(self.Frame6,width=12)
self.x_axis_title.grid(column=3, row=0)
self.x_axis_title.insert(tk.END,"X")
# y_axis title
self.y_axis_title_label = tk.Label(self.Frame6,text='Y_axis Title')
self.y_axis_title_label.grid(column=4, row=0)
self.y_axis_title = tk.Entry(self.Frame6,width=12)
self.y_axis_title.grid(column=5, row=0)
self.y_axis_title.insert(tk.END,"Y")
# figure size
self.fig_size_label = tk.Label(self.Frame6,text='Figure Size(width,height)')
self.fig_size_label.grid(column=6, row=0)
self.fig_size = tk.Entry(self.Frame6,width=8)
self.fig_size.grid(column=7, row=0)
self.fig_size.insert(tk.END,"5,5")
# X range
self.X_Range_label = tk.Label(self.Frame6,text='X Range(min,max)')
self.X_Range_label.grid(column=0, row=1)
self.X_Range = tk.Entry(self.Frame6,width=8)
self.X_Range.grid(column=1, row=1)
#self.X_Range.insert(tk.END,"test")
# Y range
self.Y_Range_label = tk.Label(self.Frame6,text='Y Range(min,max)')
self.Y_Range_label.grid(column=2, row=1)
self.Y_Range = tk.Entry(self.Frame6,width=8)
self.Y_Range.grid(column=3, row=1)
# font size
self.font_size_label = tk.Label(self.Frame6,text='Font Size')
self.font_size_label.grid(column=4, row=1)
self.font_size = tk.Entry(self.Frame6,width=8)
self.font_size.grid(column=5, row=1)
self.font_size.insert(tk.END,"16")
# font family
self.font_family_label = tk.Label(self.Frame6,text='Font Family')
self.font_family_label.grid(column=6, row=1)
self.font_family = tk.Entry(self.Frame6,width=8)
self.font_family.grid(column=7, row=1)
self.font_family.insert(tk.END,"Arial")
# plot1 color pattern
self.color1_list_label = tk.Label(self.Frame6,text='Plot1 Color')
self.color1_list_label.grid(column=0, row=2)
self.color1_list_cmbbox = ttk.Combobox(self.Frame6, state='readonly', justify='center', width=12)#,command=lambda: [self.open_command()])
self.color1_list_cmbbox['values'] = list(self.color_list_pickup.keys())
self.color1_list_cmbbox.current(0)
self.color1_list_cmbbox.grid(column=1, row=2)
# plot2 color pattern
self.color2_list_label = tk.Label(self.Frame6,text='Plot2 Color')
self.color2_list_label.grid(column=0, row=3)
self.color2_list_cmbbox = ttk.Combobox(self.Frame6, state='readonly', justify='center', width=12)#,command=lambda: [self.open_command()])
self.color2_list_cmbbox['values'] = list(self.color_list_pickup.keys())
self.color2_list_cmbbox.current(12)
self.color2_list_cmbbox.grid(column=1, row=3)
def open_command(self):
self.color_name=str(self.color_list_cmbbox.get())
self.color_list_cmbbox.config(bg=str(self.color_list_cmbbox.get()))
# plot1 marker pattern
self.marker1_list_label = tk.Label(self.Frame6,text='Marker Pattern1')
self.marker1_list_label.grid(column=2, row=2)
self.marker1_list_cmbbox = ttk.Combobox(self.Frame6, state='readonly', justify='center', width=12)
self.marker1_list_cmbbox['values'] = list(self.marker_list.keys())
self.marker1_list_cmbbox.current(0)
self.marker1_list_cmbbox.grid(column=3, row=2)
# plot2 marker pattern
self.marker2_list_label = tk.Label(self.Frame6,text='Marker Pattern2')
self.marker2_list_label.grid(column=2, row=3)
self.marker2_list_cmbbox = ttk.Combobox(self.Frame6, state='readonly', justify='center', width=12)
self.marker2_list_cmbbox['values'] = list(self.marker_list.keys())
self.marker2_list_cmbbox.current(12)
self.marker2_list_cmbbox.grid(column=3, row=3)
# plot1 marker size
self.marker_size1_label = tk.Label(self.Frame6,text='Marker Size1')
self.marker_size1_label.grid(column=4, row=2)
self.marker_size1 = tk.Entry(self.Frame6,width=8)
self.marker_size1.grid(column=5, row=2)
self.marker_size1.insert(tk.END,"10")
# plot2 marker pattern
self.marker_size2_label = tk.Label(self.Frame6,text='Marker Size2')
self.marker_size2_label.grid(column=4, row=3)
self.marker_size2 = tk.Entry(self.Frame6,width=8)
self.marker_size2.grid(column=5, row=3)
self.marker_size2.insert(tk.END,"10")
# plot1 legend
self.legend1_label = tk.Label(self.Frame6,text='Legend1')
self.legend1_label.grid(column=6, row=2)
self.legend1 = tk.Entry(self.Frame6,width=12)
self.legend1.grid(column=7, row=2)
#self.legend1.insert(tk.END,"data1")
# plot2 legend
self.legend2_label = tk.Label(self.Frame6,text='Legend2')
self.legend2_label.grid(column=6, row=3)
self.legend2 = tk.Entry(self.Frame6,width=12)
self.legend2.grid(column=7, row=3)
#self.legend2.insert(tk.END,"data2")
####### row=4 #################################################################
# set grid
self.var_grid=tk.BooleanVar()#True or False
self.set_grid_check = tk.Checkbutton(self.Frame6,text="set grid",variable=self.var_grid)
self.set_grid_check.grid(column=0, row=4)
self.var_grid.set(False)
# grid color pattern
self.grid_color_label = tk.Label(self.Frame6,text='Grid Color')
self.grid_color_label.grid(column=1, row=4)
self.grid_color = ttk.Combobox(self.Frame6, state='readonly', justify='center', width=12)#,command=lambda: [self.open_command()])
self.grid_color['values'] = list(self.color_list_pickup.keys())
self.grid_color.current(0)
self.grid_color.grid(column=2, row=4)
# grid xy
self.grid_xy_label = tk.Label(self.Frame6,text='Grid XY')
self.grid_xy_label.grid(column=3, row=4)
self.grid_xy= ttk.Combobox(self.Frame6, state='readonly', justify='center', width=12)#,command=lambda: [self.open_command()])
self.grid_xy['values'] = ['both','x','y']
self.grid_xy.current(0)
self.grid_xy.grid(column=4, row=4)
# grid linestyle
self.grid_linestyle_label = tk.Label(self.Frame6,text='Grid Linestyle')
self.grid_linestyle_label.grid(column=5, row=4)
self.grid_linestyle= ttk.Combobox(self.Frame6, state='readonly', justify='center', width=12)#,command=lambda: [self.open_command()])
self.grid_linestyle['values'] = ['dotted','solid','dashed','dashdot']
self.grid_linestyle.current(0)
self.grid_linestyle.grid(column=6, row=4)
plt.rcParams['font.family'] =self.font_family.get()#使用するフォント
plt.rcParams['xtick.direction'] = "in"#x軸の目盛線が内向き('in')か外向き('out')か双方向か('inout')
plt.rcParams['ytick.direction'] = "in"#y軸の目盛線が内向き('in')か外向き('out')か双方向か('inout')
plt.rcParams['xtick.major.width'] = 2.0#x軸主目盛り線の線幅
plt.rcParams['ytick.major.width'] = 2.0#y軸主目盛り線の線幅
plt.rcParams['font.size'] = self.font_size.get() #フォントの大きさ
plt.rcParams['axes.linewidth'] = 2.0# 軸の線幅edge linewidth。囲みの太さ
#----------------------figure-------------------------------------------------------------------------
self.Frame4 = tk.Frame(self.master)
self.Frame4.pack(after=self.Frame3,side=tk.RIGHT)
self.figsize_tuple=tuple(self.fig_size.get())
self.fig = plt.Figure(figsize=(int(self.figsize_tuple[0]),int(self.figsize_tuple[2])))
self.ax = self.fig.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.fig, self.Frame4)
self.canvas.draw()
self.toolbar = NavigationToolbar2Tk(self.canvas, self.Frame4)
self.toolbar.update()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.ax.set_title(self.graph_title.get())#(self.acquisited_graph_title)#Application.graph_title)
self.ax.set_xlabel(self.x_axis_title.get())
self.ax.set_ylabel(self.y_axis_title.get())
self.fig.tight_layout()
self.ax.legend( loc="best")#"best","upper right","upper left","lower left","lower right","right","center right","lower center","upper center","center"
#----------------------end-------------------------------------------------------------------------
def load_data(self, entry):
file_path = tk.filedialog.askopenfilename()
entry.insert(tk.END, file_path)
def scatter_plot(self,entry,num):
filename = entry.get()
try:
df = pd.read_csv(filename, header=0)
if num==1:
x1_split=self.group_data_name_str_x1.split(",")
y1_split=self.group_data_name_str_y1.split(",")
x_org = df.loc[:,x1_split[1]]#2列目がheader
y_org = df.loc[:,y1_split[1]]
self.ax.scatter(x_org,y_org,label=self.legend1.get(), c=self.color1_list_cmbbox.get(),s=int(self.marker_size1.get()))#,marker=str(self.marker1_list_cmbbox))
else:
x2_split=self.group_data_name_str_x2.split(",")
y2_split=self.group_data_name_str_y2.split(",")
x_org = df.loc[:,x2_split[1]]#2列目がheader
y_org = df.loc[:,y2_split[1]]
self.ax.scatter(x_org,y_org, label=self.legend2.get(), c=self.color2_list_cmbbox.get(),s=int(self.marker_size2.get()))#,marker=str(self.marker2_list_cmbbox))
except:
x_org = []
y_org = []
self.ax.set_title(self.graph_title.get())
self.X_Range_split=self.X_Range.get().split(',')
if len(self.X_Range_split)>1:
self.ax.set_xlim(int(self.X_Range_split[0]),int(self.X_Range_split[1]))
self.Y_Range_split=self.Y_Range.get().split(',')
if len(self.Y_Range_split)>1:
self.ax.set_ylim(int(self.Y_Range_split[0]),int(self.Y_Range_split[1]))
if self.var_grid.get()==True:
self.ax.grid(color=self.grid_color.get(),axis=self.grid_xy.get(),linestyle=self.grid_linestyle.get(),linewidth=1)#グリッド線を追加。
else:
plt.grid(b=None)
self.fig.tight_layout()
self.ax.legend( loc="best")#"best","upper right","upper left","lower left","lower right","right","center right","lower center","upper center","center")
self.canvas.draw()
def line_plot(self,entry,num):
filename = entry.get()
try:
df = pd.read_csv(filename, header=0)
if num==1:
x1_split=self.group_data_name_str_x1.split(",")
y1_split=self.group_data_name_str_y1.split(",")
x_org = df.loc[:,x1_split[1]]#2列目がheader
y_org = df.loc[:,y1_split[1]]
self.ax.plot(x_org,y_org,label=self.legend1.get(), c=self.color1_list_cmbbox.get(),s=int(self.marker_size1.get()))#,marker=str(self.marker1_list_cmbbox))
else:
x2_split=self.group_data_name_str_x2.split(",")
y2_split=self.group_data_name_str_y2.split(",")
x_org = df.loc[:,x2_split[1]]#2列目がheader
y_org = df.loc[:,y2_split[1]]
self.ax.plot(x_org,y_org, label=self.legend2.get(), c=self.color2_list_cmbbox.get(),s=int(self.marker_size2.get()))#,marker=str(self.marker2_list_cmbbox))
except:
x_org = []
y_org = []
self.ax.set_title(self.graph_title.get())
self.X_Range_split=self.X_Range.get().split(',')
if len(self.X_Range_split)>1:
self.ax.set_xlim(int(self.X_Range_split[0]),int(self.X_Range_split[1]))
self.Y_Range_split=self.Y_Range.get().split(',')
if len(self.Y_Range_split)>1:
self.ax.set_ylim(int(self.Y_Range_split[0]),int(self.Y_Range_split[1]))
if self.var_grid.get()==True:
self.ax.grid(color=self.grid_color.get(),axis=self.grid_xy.get(),linestyle=self.grid_linestyle.get(),linewidth=1)#グリッド線を追加。
else:
plt.grid(b=None)
self.fig.tight_layout()
self.ax.legend( loc="best")#"best","upper right","upper left","lower left","lower right","right","center right","lower center","upper center","center")
self.canvas.draw()
def read_csv_file(self,entry):
self.data_list.delete(*self.data_list.get_children())
self.status_bar_str.set('')
self.status_bar_str.set('Reading csv files...')
fType = [('CSV', '*.csv')]
csv_file_paths = tkfd.askopenfilenames(title='Select csv files',
filetypes=fType)
entry.delete(0, tk.END)
entry.insert(tk.END, csv_file_paths)
if not csv_file_paths:
self.status_bar_str.set('Select csv files')
return
self.dict_data_frame = {}
for path in csv_file_paths:
df = pd.read_csv(path)
self.insert_data_frame(df, path)
self.insert_data_list()
self.status_bar_str.set('Finished!!')
def clear_graph(self):
self.canvas.get_tk_widget().destroy()
self.fig = plt.Figure(figsize=(int(self.figsize_tuple[0]),int(self.figsize_tuple[2])))
self.ax = self.fig.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.fig, self.Frame4)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# ボタンをフレームに配置
self.toolbar.destroy()
self.toolbar = NavigationToolbar2Tk(self.canvas, self.Frame4)
self.toolbar.update()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.ax.set_title(self.graph_title.get())
self.var_grid.set(False)
if self.var_grid.get()==True:
self.ax.grid(color=self.grid_color.get(),axis=self.grid_xy.get(),linestyle=self.grid_linestyle.get(),linewidth=1)#グリッド線を追加。
else:
plt.grid(b=None)
self.ax.set_xlabel(self.x_axis_title.get())
self.ax.set_ylabel(self.y_axis_title.get())
self.fig.tight_layout()
root = tk.Tk()
app = Application(master=root)
root.minsize(width=1300, height=400)
app.mainloop()
参考にしたgitコードは以下になります。
用いたライブラリはnumpy,matplotlib,pandas(いずれもBSDライセンス)です。
最後に
散布図を簡単に描画できるアプリの作成に挑戦してみましたが、想像以上に難しいと感じました。体裁をもう少し整えたかったのですが、体裁を直すと動作しなくなるバグが生じてしまったこともあって詰めきれませんでした。
機能追加したバージョンや、コードの詳細についても今後記事にできれば良いと思っています。
コメント