数据分析工具:利用 Python 和 Tkinter 构建强大的数据可视化和模型训练平台

本项目使用 Python 和 Tkinter 构建了一个功能强大的数据分析工具,涵盖了数据导入、预处理、模型训练、可视化等功能。用户可以方便地导入 CSV 数据集,进行缺失值处理、特征编码等预处理操作,并选择不同的机器学习模型进行训练和评估。同时,该工具还提供直方图、饼图、箱线图等可视化图表,帮助用户更直观地理解数据和模型结果。

主要功能

  • 数据导入: 支持从本地文件系统导入 CSV 数据集。
  • 数据预处理:
    • 缺失值检测
    • 缺失值填充
    • 数据标准化
    • 特征编码
  • 模型训练:
    • 逻辑回归模型
    • K近邻模型
    • 高斯模型
  • 数据可视化:
    • 直方图
    • 饼图
    • 箱线图

代码示例

import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
import pandas as pd 
import numpy as np
from tkinter import *
from tkinter import filedialog
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
import matplotlib.pyplot as plt
from pyecharts.charts import Pie
from pyecharts.charts import Bar
from sklearn.ensemble import RandomForestClassifier
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg as FigureCanvas
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk


#导入数据集并划分训练集测试集,进行图形的绘制
class DataPreprocessor:
    def __init__(self, root):
        self.root = root
        self.data = None
        self.X_train = None
        self.X_test = None
        self.y_train = None
        self.y_test = None
        self.clf = None

        # 窗口布局
        self.load_data_button = tk.Button(root, text='导入数据', command=self.load_data)
        self.load_data_button.place(relx=0.6, rely=0.1, relwidth=0.3, relheight=0.1)

        self.train_button = tk.Button(root, text='训练模型', command=self.train_model)
        self.train_button.place(relx=0.6, rely=0.2, relwidth=0.3, relheight=0.1)


        self.plot_type = tk.StringVar()  # 创建一个变量,用于存储当前选中的图像类型
        self.plot_type.set('请选择图像类型')  # 设置默认值
        self.plot_menu = tk.OptionMenu(root, self.plot_type, '直方图', '饼图', '箱线图')
        self.plot_menu.configure(width=20)
        self.plot_menu.place(relx=0.6, rely=0.3, relwidth=0.3, relheight=0.1)

        self.plot_button = tk.Button(root, text='绘制图像', command=self.plot)
        self.plot_button.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1)

    def plot(self):
        plot_type = self.plot_type.get()
        if plot_type == '请选择图像类型':
            tk.messagebox.showwarning(title='Warning', message='请选择图像类型!')
            return
        elif plot_type == '直方图':
            self.histogram()
        elif plot_type == '饼图':
            self.pie_chart()
        elif plot_type == '箱线图':
            self.box_plot()
    
    def load_data(self):
        # 加载数据集,这里使用 Pandas 库中的 read_csv() 方法
        filename = filedialog.askopenfilename(initialdir='./data', title='Select file', filetypes=(('CSV files', '*.csv'),))
        if not filename:
            return
        self.data = pd.read_csv(filename)
        tk.messagebox.showinfo(title='Info', message=f'成功导入 {self.data.shape[0]} 条数据!')

        # 划分训练集和测试集
        self.X_train, self.X_test, self.y_train, self.y_test = train_test_split(self.data.iloc[:, :-1], self.data.iloc[:, -1], test_size=0.3)
        tk.messagebox.showinfo(title='Info', message=f'成功划分训练集和测试集!')


    def histogram(self):
        # 检查是否已经完成数据导入、划分训练集和测试集、训练模型等操作
        if not hasattr(self, 'X_train') or not hasattr(self, 'X_test') or not hasattr(self, 'y_train') or not hasattr(self, 'y_test') or not self.clf:
            tk.messagebox.showwarning(title='Warning', message='请先导入数据集并划分训练集和测试集,再训练模型!')
            return

        # 绘制直方图
        fig, ax = plt.subplots()
        ax.hist(self.X_train.iloc[:, 0], bins=20)
        ax.set_xlabel('Feature 1')
        ax.set_ylabel('Count')
        ax.set_title('Histogram')
        histogram_window = tk.Toplevel(self.root)
        canvas = FigureCanvasTkAgg(fig, master=histogram_window)
        canvas.draw()
        canvas.get_tk_widget().pack()
        toolbar = NavigationToolbar2Tk(canvas, histogram_window)
        toolbar.update()
        canvas.get_tk_widget().pack()
    def pie_chart(self):
        if not hasattr(self, 'X_train') or not hasattr(self, 'X_test') or not hasattr(self, 'y_train') or not hasattr(self, 'y_test') or not self.clf:
            tk.messagebox.showwarning(title='Warning', message='请先导入数据集并划分训练集和测试集,再训练模型!')
            return
        counts = self.data['species'].value_counts()

            # 创建饼状图
        self.fig = Figure(figsize=(5, 4), dpi=100)
        self.fig.add_subplot(111).pie(counts, labels=counts.index, autopct='%1.1f%%')

            # 在窗口中显示饼状图
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)


    def box_plot(self):
        # 检查是否已经完成数据导入、划分训练集和测试集、训练模型等操作
        if not hasattr(self, 'X_train') or not hasattr(self, 'X_test') or not hasattr(self, 'y_train') or not hasattr(self, 'y_test') or not self.clf:
            tk.messagebox.showwarning(title='Warning', message='请先导入数据集并划分训练集和测试集,再训练模型!')
            return

        # 绘制箱线图,用于展示特征的分布情况
        fig, ax = plt.subplots()
        box_data = pd.concat([self.X_train, self.X_test], axis=1)
        box_data.columns = [f'Feature {i}' for i in range(1, box_data.shape[1]+1)]
        box_data.plot(kind='box', ax=ax)
        ax.set_title('Box plot')
        box_window = tk.Toplevel(self.root)
        canvas = FigureCanvasTkAgg(fig, master=box_window)
        canvas.draw()
        canvas.get_tk_widget().pack()
        toolbar = NavigationToolbar2Tk(canvas, box_window)
        toolbar.update()
        canvas.get_tk_widget().pack()

    def train_model(self):
        # 检查是否已经完成数据导入、划分训练集和测试集等操作
        if not hasattr(self, 'X_train') or not hasattr(self, 'X_test') or not hasattr(self, 'y_train') or not hasattr(self, 'y_test'):
            tk.messagebox.showwarning(title='Warning', message='请先导入数据集并划分训练集和测试集!')
            return

        # 训练模型,这里使用 scikit-learn 库中的 RandomForestClassifier() 方法
        self.clf = RandomForestClassifier(n_estimators=10, max_depth=5)
        self.clf.fit(self.X_train, self.y_train)
        tk.messagebox.showinfo(title='Info', message='成功训练模型!')
if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('3000x2000')
    app = DataPreprocessor(root)
    
    
lb1 =Label(root, text='数据分析界面')#root是主体,text是内容
lb1.place(relx=0.1, rely=0.0, relwidth=0.8, relheight=0.1)#设置位置
#数据集的导入
def openfile():#打开文件并显示
    filepath = filedialog.askopenfilename() #获得选择好的文件,单个文件
    imgtype=['.csv']#规定读取的文件类型
    return filepath
def duru(txt):
    txt=pd.read_csv(txt)
    txt=txt.describe()
    text = Text(root)
    text.place(rely=0.6, relheight=0.4)
    text.insert(END, txt)
btn1 =Button(root,text='导入csv数据集',command=lambda:duru(openfile()))
btn1.place(relx=0.1, rely=0.1, relwidth=0.3, relheight=0.1)
btn2 = Button(root, text='关闭窗口', command=root.destroy)
btn2.place(relx=0.1, rely=0.2, relwidth=0.3, relheight=0.1)

data= pd.read_csv('新冠1.csv')


c=True
def jiance():
    t=data.isnull().any()
    global c
    global yu1
    if c==True:
        c=False
        yu1=Label(root,text=t)
        yu1.pack(side='bottom',expand=True)
    else:
        yu1.pack_forget()
        c=True

def tianchong():
    global a
    global yu2
    a1=data.fillna(data.mean())
    a=a1.fillna(method='bfill')  
    global c
    if c==True:
        c=False
        yu2=Label(root,text=a)
        yu2.pack(side='bottom',expand=True)
    else:
        yu2.pack_forget()
        c=True
def biaozhun():
    my_zscore=preprocessing.StandardScaler()
    a[['LoanAmount']]=my_zscore.fit_transform(a[['LoanAmount']])
    global c
    global yu3
    if c==True:
        c=False
        yu3=Label(root,text=a)
        yu3.pack(side='bottom',expand=True)
    else:
        yu3.pack_forget()
        c=True
        
def bianma():
    #特征编码
    onehot=pd.get_dummies((a[['Gender']]),prefix='Gender')
    global c
    global yu4
    if c==True:
        c=False
        yu4=Label(root,text=onehot)
        yu4.pack(side='bottom',expand=True)
    else:
        yu4.pack_forget()
        c=True
        
data=pd.read_csv('新冠1.csv')

def func1():
    my_model=LogisticRegression()
    my_model.fit(X_train,y_train)
    y_pred=my_model.predict(X_test)
    score=metrics.accuracy_score(y_test,y_pred)
    a1=Label(root,text=('逻辑回归模型的准确率为:',score),font=('微软雅黑 -20'))    #font指定字体和字体大小的参数
    a1.place(x=280,y=250)    #place确定窗体布局的方法
def func2():
    my_model=KNeighborsClassifier()
    my_model.fit(X_train,y_train)
    y_pred=my_model.predict(X_test)
    score=metrics.accuracy_score(y_test,y_pred)
    a2=Label(root,text=('K近邻模型的准确率为:',score),font=('微软雅黑 -20'))
    a2.place(x=280,y=300)
def func3():
    my_model=GaussianNB()
    my_model.fit(X_train,y_train)
    y_pred=my_model.predict(X_test)
    score=metrics.accuracy_score(y_test,y_pred)
    a3=Label(root,text=('高斯模型的准确率为:',score),font=('微软雅黑 -20'))
    a3.place(x=280,y=350)
    
# 创建菜单栏(顶层菜单)
menu = tk.Menu(root)

# 创建下拉菜单
submenu = tk.Menu(menu, tearoff=1)  #tearoff默认值为1
submenu.add_command(label='LogisticRegression', command=func1,font=('微软雅黑 -30'))
#add_command添加命令菜单项
submenu.add_command(label='KNeighborsClassifier', command=func2,font=('微软雅黑 -30'))
submenu.add_command(label='GaussianNB', command=func3,font=('微软雅黑 -30'))

#在下拉菜单中创建子菜单
fenmenu=tk.Menu(submenu)   #指定下级菜单
fenmenu.add_command(label='线性回归模型',font=('微软雅黑 -30'))
#add_cascade添加下级菜单
submenu.add_cascade(label='分类',menu=fenmenu,font=('微软雅黑 -30'))
juecemenu=tk.Menu(submenu,tearoff=0)
juecemenu.add_command(label='决策树模型',font=('微软雅黑 -30'))
submenu.add_cascade(label='决策树',menu=juecemenu,font=('微软雅黑 -30'))

# 添加下拉菜单到菜单栏
menu.add_cascade(label='模型菜单', menu=submenu)   

# 显示菜单栏
root.config(menu=menu) #将菜单与窗口关联起来


      
        
        
        
        
        
#按钮布局
btn3 = Button(root, text='缺失值检测', command=lambda:jiance()) 
btn3.place(relx=0.1, rely=0.3, relwidth=0.3, relheight=0.1)
btn4 = Button(root, text='缺失值填充', command=lambda:tianchong()) 
btn4.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1)
btn5 = Button(root, text='标准化', command=lambda:biaozhun()) 
btn5.place(relx=0.1, rely=0.5, relwidth=0.3, relheight=0.1)
btn6 = Button(root, text='特征编码', command=lambda:bianma()) 
btn6.place(relx=0.6, rely=0.5, relwidth=0.3, relheight=0.1)

root.mainloop()

# 在界面上添加背景图片
bg_img = Image.open('bg.jpg')
bg_img = bg_img.resize((3000, 2000), Image.ANTIALIAS)
bg_img = ImageTk.PhotoImage(bg_img)
bg_label = tk.Label(root, image=bg_img)
bg_label.place(x=0, y=0)

# 修改按钮样式
style = tk.Style()
style.configure('TButton', font=('微软雅黑', 20), borderwidth='4', relief='raised', foreground='white', background='#4B0082')
style.map('TButton', foreground=[('active', 'white')], background=[('active', '#483D8B')])

# 修改标签样式
style.configure('TLabel', font=('微软雅黑', 20), background='#F0F8FF')

# 修改下拉菜单样式
style.configure('TMenubutton', font=('微软雅黑', 20), background='#F0F8FF')

# 修改文本框样式
style.configure('TText', font=('微软雅黑', 20), background='#F0F8FF')

# 修改选项菜单样式
style.configure('TMenubutton', font=('微软雅黑', 20), background='#F0F8FF', borderwidth='1', relief='solid')

# 修改窗口标题
root.title('数据分析')

# 修改窗口图标
root.iconbitmap('icon.ico')

# 修改窗口大小和位置
root.geometry('3000x2000+0+0')

# 修改窗口最小尺寸
root.minsize(800, 600)

界面美化

  • 添加背景图片: 使用 ImageImageTk 模块加载并显示背景图片。
  • 修改按钮样式: 使用 tk.Style 对象修改按钮的字体、边框、颜色等属性。
  • 修改标签样式: 修改标签的字体、背景颜色等属性。
  • 修改下拉菜单样式: 修改下拉菜单的字体、背景颜色等属性。
  • 修改文本框样式: 修改文本框的字体、背景颜色等属性。
  • 修改选项菜单样式: 修改选项菜单的字体、背景颜色、边框等属性。
  • 修改窗口标题: 使用 root.title() 方法设置窗口标题。
  • 修改窗口图标: 使用 root.iconbitmap() 方法设置窗口图标。
  • 修改窗口大小和位置: 使用 root.geometry() 方法设置窗口大小和位置。
  • 修改窗口最小尺寸: 使用 root.minsize() 方法设置窗口最小尺寸。

使用方法

  1. 安装必要的 Python 包:
pip install tkinter pandas numpy scikit-learn matplotlib pyecharts
  1. bg.jpgicon.ico 文件放置在与代码相同的目录下。

  2. 运行 Python 代码:

python your_script.py

注意事项

  • 本项目代码仅供参考,实际使用中可能需要根据需求进行修改。
  • 数据集路径需要根据实际情况进行调整。
  • 为了保证代码正常运行,请确保已经安装了必要的 Python 包。

未来展望

  • 增加更多数据预处理功能,例如数据清洗、数据转换等。
  • 支持更多机器学习模型,例如支持向量机、神经网络等。
  • 提供更丰富的可视化图表,例如散点图、热力图等。
  • 开发更加人性化的界面,例如使用更直观的图标、更简洁的布局等。

原文地址: https://www.cveoy.top/t/topic/opSB 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录