DEV Community

Mate Technologies
Mate Technologies

Posted on

Build an Employee Attrition Prediction GUI in Python

Learn how to build AttritionPredictor v1.0, a GUI app that predicts employee attrition from CSV datasets. We'll use Python, Tkinter, ttkbootstrap, and pandas.

๐Ÿ”— GitHub repo: Employee Attrition Prediction GUI

Step 1: Set Up Your Environment

First, install the required packages. Youโ€™ll need:

pip install pandas ttkbootstrap tkinterdnd2

pandas: for handling CSV data

ttkbootstrap: for a modern, styled Tkinter GUI

tkinterdnd2: optional, allows drag & drop support

Step 2: Import Libraries

Start your Python script with these imports:

import os, sys, threading
import pandas as pd
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import ttkbootstrap as tb
from ttkbootstrap.constants import *

try:
    from tkinterdnd2 import TkinterDnD, DND_FILES
    DND_ENABLED = True
except ImportError:
    DND_ENABLED = False
    print("Drag & Drop requires tkinterdnd2: pip install tkinterdnd2")
Enter fullscreen mode Exit fullscreen mode

โœ… Explanation:

We import threading for running predictions without freezing the GUI.

TkinterDnD enables drag-and-drop CSV files.

ttkbootstrap makes the GUI look modern with minimal styling code.

Step 3: Helper Function

We'll need a helper to locate resources like icons:

def resource_path(file_name):
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”น Explanation: This ensures your app can access files correctly, even after packaging with tools like PyInstaller.

Step 4: Create the Prediction Logic

For now, we use a simple placeholder model:

class AttritionWorker:
    def __init__(self, dataframe, callbacks):
        self.df = dataframe
        self.callbacks = callbacks
        self._running = True

    def stop(self):
        self._running = False

    def run(self):
        results = []
        for idx, row in self.df.iterrows():
            if not self._running:
                break
            # Placeholder logic
            attrition_prob = min(1.0, max(0.0, 0.1 + 0.2 * row.get("Age", 30)/50))
            prediction = "Yes" if attrition_prob > 0.5 else "No"
            results.append((row.get("EmployeeID", idx), row.get("Name", "N/A"), prediction))
            if "update" in self.callbacks:
                self.callbacks["update"](idx, results[-1])
        if "finished" in self.callbacks:
            self.callbacks["finished"](results)
Enter fullscreen mode Exit fullscreen mode

โœ… Explanation:

Each row in the CSV is checked for Age.

A simple rule calculates the probability of leaving (attrition_prob).

Predictions are returned as "Yes" or "No".

Step 5: Build the GUI

We use ttkbootstrap to create a sleek window:

class AttritionPredictorApp:
    APP_NAME = "AttritionPredictor"
    APP_VERSION = "1.0"

    def __init__(self):
        if DND_ENABLED:
            self.root = TkinterDnD.Tk()
        else:
            self.root = tb.Window(themename="darkly")
        self.root.title(f"{self.APP_NAME} v{self.APP_VERSION}")
        self.root.minsize(1100, 600)
        self.worker_obj = None
        self.file_path = None
        self._build_ui()
        self._apply_styles()
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”น Explanation:

The main window uses the "darkly" theme from ttkbootstrap.

We set a minimum window size for usability.

worker_obj will handle predictions in a separate thread.

Step 6: Add UI Components

def _build_ui(self):
    main = tb.Frame(self.root, padding=10)
    main.pack(fill="both", expand=True)

    tb.Label(main, text=f"๐Ÿง  {self.APP_NAME} - Enterprise Attrition Predictor",
             font=("Segoe UI", 20, "bold")).pack(pady=(0,4))
    tb.Label(main, text="Upload employee dataset, predict attrition, export results",
             font=("Segoe UI", 10, "italic"), foreground="#9ca3af").pack(pady=(0,20))

    # File input and buttons
    row1 = tb.Frame(main)
    row1.pack(fill="x", pady=(0,6))

    self.path_input = tb.Entry(row1, width=80)
    self.path_input.pack(side="left", fill="x", expand=True, padx=(0,6))
    self.path_input.insert(0, "Drag & drop employee CSV hereโ€ฆ")

    browse_btn = tb.Button(row1, text="๐Ÿ“‚ Browse", bootstyle="info", command=self.browse)
    browse_btn.pack(side="left", padx=3)
    self.start_btn = tb.Button(row1, text="๐Ÿš€ Predict Attrition", bootstyle="success", command=self.start)
    self.start_btn.pack(side="left", padx=3)
Enter fullscreen mode Exit fullscreen mode

โœ… Explanation:

Entry box for file path input.

Browse button opens a file dialog.

Start button runs predictions.

Step 7: Handle File Selection & Drag-and-Drop

def browse(self):
    path = filedialog.askopenfilename(filetypes=[("CSV Files","*.csv")])
    if path:
        self.path_input.delete(0, "end")
        self.path_input.insert(0, path)
        self.file_path = path

def on_drop(self, event):
    path = self.root.tk.splitlist(event.data)[0]
    if os.path.isfile(path) and path.lower().endswith(".csv"):
        self.path_input.delete(0, "end")
        self.path_input.insert(0, path)
        self.file_path = path
Enter fullscreen mode Exit fullscreen mode

Step 8: Run Predictions in a Thread

def start(self):
    if not self.file_path or not os.path.isfile(self.file_path):
        messagebox.showwarning("No File", "Select a valid CSV file first.")
        return
    self.start_btn.config(state="disabled")
    df = pd.read_csv(self.file_path)
    self.worker_obj = AttritionWorker(df, callbacks={
        "update": self.add_row,
        "finished": self.finish
    })
    threading.Thread(target=self.worker_obj.run, daemon=True).start()
Enter fullscreen mode Exit fullscreen mode

โœ… Explanation:

Using a separate thread prevents the GUI from freezing during predictions.

Step 9: Show Results

def add_row(self, idx, data):
    self.tree.insert("", "end", values=("โ˜‘๏ธ", data[0], data[1], data[2]))
Enter fullscreen mode Exit fullscreen mode

Displays employee ID, name, and prediction in a Treeview table.

Step 10: Export Predictions

def export_results(self):
    selected = [self.tree.item(i)['values'] for i in self.tree.get_children()
                if self.tree.item(i)['values'][0]=="โ˜‘๏ธ"]
    if not selected:
        messagebox.showwarning("Export", "No selected rows to export")
        return
    path = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV Files","*.csv")])
    if path:
        pd.DataFrame(selected, columns=["Selected","EmployeeID","Name","Attrition"]).to_csv(path,index=False)
        messagebox.showinfo("Export", "Export completed")
Enter fullscreen mode Exit fullscreen mode

Export only the rows youโ€™ve checked.

Step 11: Run the App

Finally, run your GUI:

if __name__ == "__main__":
    app = AttritionPredictorApp()
    app.run()
Enter fullscreen mode Exit fullscreen mode

Open your terminal and run:

python attrition_gui.py

You now have a fully functional employee attrition prediction GUI! ๐ŸŽ‰

Step 12: Next Steps

Replace the placeholder prediction logic with a real ML model (like Logistic Regression).

Add more features like charts, filters, or department-wise analysis.

Package the app with PyInstaller for distribution.

๐Ÿ’ป Clone the full project:
https://github.com/rogers-cyber/python-tiny-tools/tree/main/Employee-attrition-prediction-GUI

Top comments (0)