Gleaming Data Alchemist Python GUI

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

class DataAlchemistApp:
    def __init__(self, master):
        self.master = master
        master.title("Gleaming Data Alchemist")

        self.notebook = ttk.Notebook(master)
        self.notebook.pack(fill='both', expand=True)

        self.create_import_tab()
        self.create_visualization_tab()
        self.create_transformation_tab()
        self.create_export_tab()
        self.create_about_tab()



    def create_import_tab(self):
        self.import_tab = ttk.Frame(self.notebook)
        self.notebook.add(self.import_tab, text='Import Data')

        self.import_label = tk.Label(self.import_tab, text="Select a CSV or Excel file:")
        self.import_label.pack(pady=10)

        self.import_button = tk.Button(self.import_tab, text="Browse", command=self.load_data)
        self.import_button.pack(pady=5)

        self.data_preview_label = tk.Label(self.import_tab, text="Data Preview:")
        self.data_preview_label.pack(pady=5)

        self.data_preview = tk.Text(self.import_tab, height=10, width=80)
        self.data_preview.pack(pady=5)

        self.df = None # Store the loaded DataFrame here

    def create_visualization_tab(self):
        self.visualization_tab = ttk.Frame(self.notebook)
        self.notebook.add(self.visualization_tab, text='Visualization')

        self.visualization_label = tk.Label(self.visualization_tab, text="Select columns for visualization:")
        self.visualization_label.pack(pady=10)

        # Column selection
        self.x_var = tk.StringVar()
        self.y_var = tk.StringVar()

        self.x_label = tk.Label(self.visualization_tab, text="X-axis:")
        self.x_label.pack()
        self.x_dropdown = ttk.Combobox(self.visualization_tab, textvariable=self.x_var, state='readonly')
        self.x_dropdown.pack()

        self.y_label = tk.Label(self.visualization_tab, text="Y-axis:")
        self.y_label.pack()
        self.y_dropdown = ttk.Combobox(self.visualization_tab, textvariable=self.y_var, state='readonly')
        self.y_dropdown.pack()

        # Plot type selection
        self.plot_type_var = tk.StringVar(value='scatter')
        self.plot_type_label = tk.Label(self.visualization_tab, text="Plot Type:")
        self.plot_type_label.pack()
        self.plot_type_dropdown = ttk.Combobox(self.visualization_tab, textvariable=self.plot_type_var, values=['scatter', 'line', 'bar', 'hist'], state='readonly')
        self.plot_type_dropdown.pack()

        self.visualize_button = tk.Button(self.visualization_tab, text="Visualize", command=self.visualize_data)
        self.visualize_button.pack(pady=10)

        self.visualization_frame = tk.Frame(self.visualization_tab)
        self.visualization_frame.pack(fill='both', expand=True)

        self.canvas = None

    def create_transformation_tab(self):
        self.transformation_tab = ttk.Frame(self.notebook)
        self.notebook.add(self.transformation_tab, text='Transformation')

        self.transformation_label = tk.Label(self.transformation_tab, text="Perform data transformations:")
        self.transformation_label.pack(pady=10)

        # Example transformations - you can add more
        self.fillna_button = tk.Button(self.transformation_tab, text="Fill Missing Values (Mean)", command=self.fill_missing_values)
        self.fillna_button.pack(pady=5)

        self.normalize_button = tk.Button(self.transformation_tab, text="Normalize Data", command=self.normalize_data)
        self.normalize_button.pack(pady=5)

        self.result_preview_label = tk.Label(self.transformation_tab, text="Transformed Data Preview:")
        self.result_preview_label.pack(pady=5)

        self.result_preview = tk.Text(self.transformation_tab, height=10, width=80)
        self.result_preview.pack(pady=5)

    def create_export_tab(self):
        self.export_tab = ttk.Frame(self.notebook)
        self.notebook.add(self.export_tab, text='Export Data')

        self.export_label = tk.Label(self.export_tab, text="Export the transformed data:")
        self.export_label.pack(pady=10)

        self.export_button = tk.Button(self.export_tab, text="Export to CSV", command=self.export_data)
        self.export_button.pack(pady=5)

    def create_about_tab(self):
         self.about_tab = ttk.Frame(self.notebook)
         self.notebook.add(self.about_tab, text='About')

         self.about_label = tk.Label(self.about_tab, text="Gleaming Data Alchemist - A versatile tool for data import, visualization, transformation, and export.", wraplength=500)
         self.about_label.pack(pady=20)

         # Add a logo or image
         try:
             # Load the image
             image = Image.open("data_alchemist_logo.png")  # Replace with your logo file
             image = image.resize((200, 200))  # Resize if needed
             self.logo_image = ImageTk.PhotoImage(image)
             self.logo_label = tk.Label(self.about_tab, image=self.logo_image)
             self.logo_label.pack()
         except FileNotFoundError:
             print("Logo image not found.")  # Handle the error gracefully
             pass # Just continue without the logo


    def load_data(self):
        filename = filedialog.askopenfilename(initialdir=".", title="Select a file", filetypes=(("CSV files", "*.csv"), ("Excel files", "*.xlsx;*.xls"), ("all files", "*.*")))
        if filename:
            try:
                if filename.endswith(('.csv')):
                    self.df = pd.read_csv(filename)
                elif filename.endswith(('.xlsx', '.xls')):
                    self.df = pd.read_excel(filename)
                else:
                    messagebox.showerror("Error", "Unsupported file format.")
                    return

                self.data_preview.delete('1.0', tk.END)
                self.data_preview.insert(tk.END, self.df.head().to_string())

                # Update column options in visualization tab
                columns = list(self.df.columns)
                self.x_dropdown['values'] = columns
                self.y_dropdown['values'] = columns

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

    def visualize_data(self):
        if self.df is None:
            messagebox.showerror("Error", "No data loaded. Please import a file first.")
            return

        x_col = self.x_var.get()
        y_col = self.y_var.get()
        plot_type = self.plot_type_var.get()

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

        try:
            plt.clf()
            if plot_type == 'scatter':
                plt.scatter(self.df[x_col], self.df[y_col])
            elif plot_type == 'line':
                plt.plot(self.df[x_col], self.df[y_col])
            elif plot_type == 'bar':
                plt.bar(self.df[x_col], self.df[y_col])
            elif plot_type == 'hist':
                plt.hist(self.df[x_col])
            else:
                messagebox.showerror("Error", "Invalid plot type.")
                return

            plt.xlabel(x_col)
            plt.ylabel(y_col)
            plt.title(f"{plot_type.capitalize()} Plot of {x_col} vs {y_col}")
            plt.grid(True)

            # Embed plot in Tkinter window
            figure = plt.gcf()
            if self.canvas:
                self.canvas.get_tk_widget().destroy()

            self.canvas = FigureCanvasTkAgg(figure, master=self.visualization_frame)
            self.canvas.draw()
            self.canvas.get_tk_widget().pack(fill='both', expand=True)

        except KeyError:
            messagebox.showerror("Error", "Invalid column selection.")
        except Exception as e:
            messagebox.showerror("Error", f"Error creating visualization: {e}")


    def fill_missing_values(self):
        if self.df is None:
            messagebox.showerror("Error", "No data loaded. Please import a file first.")
            return

        try:
            self.df = self.df.fillna(self.df.mean(numeric_only=True))
            self.result_preview.delete('1.0', tk.END)
            self.result_preview.insert(tk.END, self.df.head().to_string())
        except Exception as e:
            messagebox.showerror("Error", f"Error filling missing values: {e}")

    def normalize_data(self):
        if self.df is None:
            messagebox.showerror("Error", "No data loaded. Please import a file first.")
            return

        try:
            from sklearn.preprocessing import MinMaxScaler  # Import here to avoid requiring it if not used
            scaler = MinMaxScaler()
            numerical_cols = self.df.select_dtypes(include=['number']).columns  # Only normalize numerical columns
            self.df[numerical_cols] = scaler.fit_transform(self.df[numerical_cols])
            self.result_preview.delete('1.0', tk.END)
            self.result_preview.insert(tk.END, self.df.head().to_string())
        except Exception as e:
            messagebox.showerror("Error", f"Error normalizing data: {e}")


    def export_data(self):
        if self.df is None:
            messagebox.showerror("Error", "No data loaded. Please import a file first.")
            return

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



root = tk.Tk()
app = DataAlchemistApp(root)

# Create a toplevel window for detailed information
def show_details():
    details_window = tk.Toplevel(root)
    details_window.title("Program Details")
    details_text = tk.Text(details_window, height=20, width=80)
    details_text.pack(padx=10, pady=10)
    details_text.insert(tk.END, """
    Gleaming Data Alchemist is a versatile data analysis tool built with Python and Tkinter.
    
    Key Features:
    - Import data from CSV and Excel files.
    - Preview the imported data.
    - Visualize data using various plot types (scatter, line, bar, histogram).
    - Perform data transformations like filling missing values and normalizing data.
    - Export transformed data to CSV files.
    - Simple and intuitive graphical user interface.

    This program leverages pandas for data manipulation, matplotlib for visualization, and scikit-learn for normalization.
    """)
    details_text.config(state=tk.DISABLED) # Make it read-only

# Add a button to the main window to trigger the details window
details_button = tk.Button(root, text="Details", command=show_details)
details_button.pack(pady=5)

root.mainloop()
👁️ Viewed: 8

Comments