Vibrant Data Navigator Python GUI

👤 Sharing: AI
import tkinter as tk
from tkinter import ttk
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import seaborn as sns
import io
from tkinter import filedialog, messagebox

class DataNavigator:
    def __init__(self, master):
        self.master = master
        master.title("Vibrant Data Navigator")
        master.geometry("1200x800")

        self.data = None
        self.filename = None

        # --- Menu Bar ---
        self.menubar = tk.Menu(master)
        filemenu = tk.Menu(self.menubar, tearoff=0)
        filemenu.add_command(label="Open", command=self.load_data)
        filemenu.add_command(label="Save as CSV", command=self.save_as_csv)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=master.quit)
        self.menubar.add_cascade(label="File", menu=filemenu)

        helpmenu = tk.Menu(self.menubar, tearoff=0)
        helpmenu.add_command(label="About", command=self.show_about)
        self.menubar.add_cascade(label="Help", menu=helpmenu)

        master.config(menu=self.menubar)

        # --- Panedwindow layout ---
        self.paned_window = tk.PanedWindow(master, orient=tk.HORIZONTAL)
        self.paned_window.pack(fill=tk.BOTH, expand=True)

        # --- Left Frame (Data View) ---
        self.left_frame = tk.Frame(self.paned_window, bd=2, relief=tk.SUNKEN)
        self.paned_window.add(self.left_frame)

        self.data_label = tk.Label(self.left_frame, text="Data Preview")
        self.data_label.pack(pady=5)

        self.data_tree = ttk.Treeview(self.left_frame, show="headings", height=20)
        self.data_tree.pack(fill=tk.BOTH, expand=True)

        self.scrollbar_x = tk.Scrollbar(self.left_frame, orient=tk.HORIZONTAL, command=self.data_tree.xview)
        self.scrollbar_x.pack(fill=tk.X)
        self.scrollbar_y = tk.Scrollbar(self.left_frame, orient=tk.VERTICAL, command=self.data_tree.yview)
        self.scrollbar_y.pack(fill=tk.Y, side=tk.RIGHT)

        self.data_tree.configure(xscrollcommand=self.scrollbar_x.set, yscrollcommand=self.scrollbar_y.set)


        # --- Right Frame (Controls & Plots) ---
        self.right_frame = tk.Frame(self.paned_window, bd=2, relief=tk.SUNKEN)
        self.paned_window.add(self.right_frame)

        self.control_label = tk.Label(self.right_frame, text="Data Analysis Controls")
        self.control_label.pack(pady=5)

        # --- Plot Type Selection ---
        self.plot_type_label = tk.Label(self.right_frame, text="Plot Type:")
        self.plot_type_label.pack()
        self.plot_type = tk.StringVar(value="scatter") #default value
        self.plot_options = ttk.Combobox(self.right_frame, textvariable=self.plot_type, values=["scatter", "histogram", "bar", "boxplot", "heatmap"], state="readonly")
        self.plot_options.pack()

        # --- Column Selection ---
        self.x_column_label = tk.Label(self.right_frame, text="X Column:")
        self.x_column_label.pack()
        self.x_column = tk.StringVar()
        self.x_column_dropdown = ttk.Combobox(self.right_frame, textvariable=self.x_column, state="readonly")
        self.x_column_dropdown.pack()

        self.y_column_label = tk.Label(self.right_frame, text="Y Column:")
        self.y_column_label.pack()
        self.y_column = tk.StringVar()
        self.y_column_dropdown = ttk.Combobox(self.right_frame, textvariable=self.y_column, state="readonly")
        self.y_column_dropdown.pack()

        # --- Plot Button ---
        self.plot_button = tk.Button(self.right_frame, text="Generate Plot", command=self.generate_plot)
        self.plot_button.pack(pady=10)

        # --- Plot Canvas ---
        self.plot_canvas = tk.Canvas(self.right_frame, bg="white", height=400, width=500)
        self.plot_canvas.pack(fill=tk.BOTH, expand=True)

        # --- Info Button ---
        self.info_button = tk.Button(self.right_frame, text="What does this program do?", command=self.show_details)
        self.info_button.pack(pady=10)

    def load_data(self):
        self.filename = filedialog.askopenfilename(initialdir=".", title="Select a CSV file", filetypes=(("CSV files", "*.csv"), ("all files", "*")))
        if self.filename:
            try:
                self.data = pd.read_csv(self.filename)
                self.populate_treeview()
                self.update_column_options()
            except Exception as e:
                messagebox.showerror("Error", f"Error loading data: {e}")

    def save_as_csv(self):
        if self.data is None:
            messagebox.showerror("Error", "No data loaded to save.")
            return

        filename = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=(("CSV files", "*.csv"), ("all files", "*")))
        if filename:
            try:
                self.data.to_csv(filename, index=False)
                messagebox.showinfo("Success", f"Data saved successfully to {filename}")
            except Exception as e:
                messagebox.showerror("Error", f"Error saving data: {e}")


    def populate_treeview(self):
        # Clear existing data
        for item in self.data_tree.get_children():
            self.data_tree.delete(item)

        # Set up column headers
        self.data_tree["column"] = list(self.data.columns)
        self.data_tree["show"] = "headings"

        for column in self.data_tree["column"]:
            self.data_tree.heading(column, text=column)
            self.data_tree.column(column, width=100)

        # Insert data
        for index, row in self.data.iterrows():
            self.data_tree.insert("", "end", values=list(row))

    def update_column_options(self):
        if self.data is not None:
            columns = list(self.data.columns)
            self.x_column_dropdown['values'] = columns
            self.y_column_dropdown['values'] = columns

    def generate_plot(self):
        if self.data is None:
            messagebox.showerror("Error", "Please load data first.")
            return

        plot_type = self.plot_type.get()
        x_col = self.x_column.get()
        y_col = self.y_column.get()

        if not x_col or not y_col:
            messagebox.showerror("Error", "Please select X and Y columns.")
            return

        try:
            # Clear previous plot
            for item in self.plot_canvas.winfo_children():
                item.destroy()

            fig, ax = plt.subplots(figsize=(6, 4))

            if plot_type == "scatter":
                ax.scatter(self.data[x_col], self.data[y_col])
                ax.set_xlabel(x_col)
                ax.set_ylabel(y_col)
                ax.set_title(f"Scatter Plot: {x_col} vs {y_col}")
            elif plot_type == "histogram":
                ax.hist(self.data[x_col], bins=20)
                ax.set_xlabel(x_col)
                ax.set_ylabel("Frequency")
                ax.set_title(f"Histogram of {x_col}")
            elif plot_type == "bar":
                # Ensure y_col contains counts or values for bars
                ax.bar(self.data[x_col], self.data[y_col])
                ax.set_xlabel(x_col)
                ax.set_ylabel(y_col)
                ax.set_title(f"Bar Chart: {x_col} vs {y_col}")
                plt.xticks(rotation=45, ha='right') #rotate x axis labels
            elif plot_type == "boxplot":
                ax.boxplot(self.data[x_col])
                ax.set_ylabel(x_col)
                ax.set_title(f"Boxplot of {x_col}")
            elif plot_type == "heatmap":
                # Example: Correlation heatmap (requires numeric data)
                correlation_matrix = self.data[[x_col, y_col]].corr()
                sns.heatmap(correlation_matrix, annot=True, cmap="coolwarm", ax=ax)
                ax.set_title(f"Heatmap: Correlation between {x_col} and {y_col}")

            fig.tight_layout()
            canvas = FigureCanvasTkAgg(fig, master=self.plot_canvas)
            canvas.draw()
            canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        except Exception as e:
            messagebox.showerror("Error", f"Error generating plot: {e}")

    def show_details(self):
        messagebox.showinfo("Program Details", "This program, the Vibrant Data Navigator, allows you to load CSV data, view it in a table, and generate various types of plots based on selected columns. You can create scatter plots, histograms, bar charts, boxplots, and heatmaps to explore your data visually.  The program includes a menu for opening files, saving the data as CSV, and an 'About' section with information about the application. It is designed to be a versatile tool for basic data exploration and visualization.")

    def show_about(self):
        messagebox.showinfo("About", "Vibrant Data Navigator\nVersion 1.0\nCreated for versatile data exploration and visualization.\nPowered by Tkinter, Pandas, Matplotlib, and Seaborn.")

root = tk.Tk()
navigator = DataNavigator(root)
root.mainloop()
👁️ Viewed: 79

Comments