Vigilant Data Analyzer Python GUI
👤 Sharing: AI
import tkinter as tk
from tkinter import ttk
from tkinter import 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 DataAnalyzerApp:
def __init__(self, master):
self.master = master
master.title("Vigilant Data Analyzer")
master.geometry("800x600")
self.data = None
self.filename = None
# --- Menu Bar ---
self.menubar = tk.Menu(master)
self.filemenu = tk.Menu(self.menubar, tearoff=0)
self.filemenu.add_command(label="Open", command=self.load_data)
self.filemenu.add_separator()
self.filemenu.add_command(label="Exit", command=master.quit)
self.menubar.add_cascade(label="File", menu=self.filemenu)
master.config(menu=self.menubar)
# --- Left Frame (Data Display) ---
self.left_frame = ttk.Frame(master, padding=10)
self.left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.tree = ttk.Treeview(self.left_frame, show="headings")
self.tree.pack(fill=tk.BOTH, expand=True)
self.tree_scroll_y = ttk.Scrollbar(self.left_frame, orient=tk.VERTICAL, command=self.tree.yview)
self.tree_scroll_y.pack(side=tk.RIGHT, fill=tk.Y)
self.tree.configure(yscrollcommand=self.tree_scroll_y.set)
self.tree_scroll_x = ttk.Scrollbar(self.left_frame, orient=tk.HORIZONTAL, command=self.tree.xview)
self.tree_scroll_x.pack(side=tk.BOTTOM, fill=tk.X)
self.tree.configure(xscrollcommand=self.tree_scroll_x.set)
# --- Right Frame (Controls and Visualizations) ---
self.right_frame = ttk.Frame(master, padding=10)
self.right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
# --- Visualization Selection ---
self.visualization_label = ttk.Label(self.right_frame, text="Select Visualization:")
self.visualization_label.pack()
self.visualization_choices = ["Scatter Plot", "Histogram", "Box Plot", "Bar Chart"]
self.visualization_var = tk.StringVar(value=self.visualization_choices[0])
self.visualization_dropdown = ttk.Combobox(self.right_frame, textvariable=self.visualization_var, values=self.visualization_choices, state="readonly")
self.visualization_dropdown.pack()
# --- Column Selection ---
self.x_column_label = ttk.Label(self.right_frame, text="X Column:")
self.x_column_label.pack()
self.x_column_var = tk.StringVar()
self.x_column_dropdown = ttk.Combobox(self.right_frame, textvariable=self.x_column_var, state="readonly")
self.x_column_dropdown.pack()
self.y_column_label = ttk.Label(self.right_frame, text="Y Column (for Scatter Plot/Box Plot):")
self.y_column_label.pack()
self.y_column_var = tk.StringVar()
self.y_column_dropdown = ttk.Combobox(self.right_frame, textvariable=self.y_column_var, state="readonly")
self.y_column_dropdown.pack()
# --- Generate Button ---
self.generate_button = ttk.Button(self.right_frame, text="Generate Visualization", command=self.generate_visualization)
self.generate_button.pack()
# --- Visualization Area ---
self.visualization_frame = ttk.Frame(self.right_frame)
self.visualization_frame.pack(fill=tk.BOTH, expand=True)
self.visualization_canvas = None
self.visualization_widget = None # Store the widget (e.g., canvas, image label)
# --- Summary Statistics ---
self.summary_label = ttk.Label(self.right_frame, text="Summary Statistics:")
self.summary_label.pack()
self.summary_text = tk.Text(self.right_frame, height=10, width=40, wrap=tk.WORD, state=tk.DISABLED)
self.summary_text.pack()
self.summary_scrollbar = ttk.Scrollbar(self.right_frame, command=self.summary_text.yview)
self.summary_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.summary_text.configure(yscrollcommand=self.summary_scrollbar.set)
def load_data(self):
self.filename = filedialog.askopenfilename(initialdir=".", title="Select a File", filetypes=(("CSV files", "*.csv"), ("Excel files", "*.xlsx;*.xls"), ("All files", "*.*")))
if self.filename:
try:
if self.filename.endswith(('.xls', '.xlsx')):
self.data = pd.read_excel(self.filename)
else:
self.data = pd.read_csv(self.filename)
self.populate_treeview()
self.update_column_options()
self.calculate_summary_statistics()
except Exception as e:
messagebox.showerror("Error", f"Error loading data: {e}")
self.data = None
self.filename = None
def populate_treeview(self):
if self.data is None:
return
self.tree.delete(*self.tree.get_children())
self.tree["columns"] = list(self.data.columns)
for col in self.data.columns:
self.tree.heading(col, text=col)
self.tree.column(col, width=100, stretch=False) # Prevent columns from stretching by default
for index, row in self.data.iterrows():
self.tree.insert("", tk.END, values=list(row))
def update_column_options(self):
if self.data is None:
return
columns = list(self.data.columns)
self.x_column_dropdown['values'] = columns
self.y_column_dropdown['values'] = columns
if columns:
self.x_column_var.set(columns[0]) # Set a default value
if len(columns) > 1:
self.y_column_var.set(columns[1]) # Set a default value
else:
self.y_column_var.set(columns[0]) # Set the same if only one column
def calculate_summary_statistics(self):
if self.data is None:
return
try:
description = self.data.describe(include='all').to_string()
self.summary_text.config(state=tk.NORMAL)
self.summary_text.delete("1.0", tk.END)
self.summary_text.insert(tk.END, description)
self.summary_text.config(state=tk.DISABLED)
except Exception as e:
messagebox.showerror("Error", f"Error calculating summary statistics: {e}")
def generate_visualization(self):
if self.data is None:
messagebox.showerror("Error", "Please load data first.")
return
visualization_type = self.visualization_var.get()
x_column = self.x_column_var.get()
y_column = self.y_column_var.get()
try:
# Clear previous visualization
self.clear_visualization()
# Generate new visualization
fig, ax = plt.subplots(figsize=(6, 4))
if visualization_type == "Scatter Plot":
sns.scatterplot(x=x_column, y=y_column, data=self.data, ax=ax)
ax.set_title(f"Scatter Plot of {y_column} vs {x_column}")
ax.set_xlabel(x_column)
ax.set_ylabel(y_column)
elif visualization_type == "Histogram":
self.data[x_column].hist(ax=ax)
ax.set_title(f"Histogram of {x_column}")
ax.set_xlabel(x_column)
ax.set_ylabel("Frequency")
elif visualization_type == "Box Plot":
sns.boxplot(x=x_column, y=y_column, data=self.data, ax=ax)
ax.set_title(f"Box Plot of {y_column} by {x_column}")
ax.set_xlabel(x_column)
ax.set_ylabel(y_column)
elif visualization_type == "Bar Chart":
# Assuming x_column is categorical
counts = self.data[x_column].value_counts()
counts.plot(kind='bar', ax=ax)
ax.set_title(f"Bar Chart of {x_column}")
ax.set_xlabel(x_column)
ax.set_ylabel("Count")
plt.xticks(rotation=45, ha='right') # Rotate x-axis labels for readability
else:
messagebox.showerror("Error", f"Invalid visualization type: {visualization_type}")
return
plt.tight_layout()
# Embed plot in Tkinter window
canvas = FigureCanvasTkAgg(fig, master=self.visualization_frame)
self.visualization_canvas = canvas
self.visualization_widget = canvas.get_tk_widget()
self.visualization_widget.pack(fill=tk.BOTH, expand=True)
canvas.draw()
except Exception as e:
messagebox.showerror("Error", f"Error generating visualization: {e}")
def clear_visualization(self):
if self.visualization_widget:
self.visualization_widget.destroy()
self.visualization_widget = None
if self.visualization_canvas:
self.visualization_canvas.get_tk_widget().destroy()
self.visualization_canvas = None
plt.close('all') # Close all matplotlib figures
root = tk.Tk()
app = DataAnalyzerApp(root)
root.mainloop()
👁️ Viewed: 5
Comments