Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import numpy as np | |
| import pandas as pd | |
| from AutoVisualizer.processing import check_dataset_cleanliness, task_type,is_probably_categorical, is_discrete, is_continuous, parse_datetime_columns | |
| from AutoVisualizer.categorical_viz import combine_figures_as_subplots, generate_count_plots, generate_bar_plots, generate_grouped_bar_plots, generate_pie_plots, generate_categorical_correlation_heatmap | |
| from AutoVisualizer.numerical_viz import generate_box_plots, generate_numeric_correlation_heatmap, generate_scatter_plots, generate_histograms, generate_line_plots | |
| st.set_page_config(page_title= "Auto-Visualizer",page_icon= "📊",layout="wide") | |
| # col1, col2 = st.columns([0.3, 0.7]) | |
| with st.sidebar: | |
| # Upload the dataset file (can upload only CSV, XLSX, JSON, XML) | |
| uploaded_file = st.file_uploader("Upload your dataset file:", ["csv", "xlsx", "json", "xml"]) | |
| if uploaded_file is not None: | |
| file_type = uploaded_file.name | |
| try: | |
| # Read the dataset through pandas | |
| if file_type.endswith(".csv"): | |
| df = pd.read_csv(uploaded_file) | |
| elif file_type.endswith(".xlsx"): | |
| df = pd.read_excel(uploaded_file) | |
| elif file_type.endswith(".json"): | |
| df = pd.read_json(uploaded_file) | |
| else: | |
| df = pd.read_xml(uploaded_file) | |
| except Exception as e: | |
| st.write("Error:", e) | |
| with st.sidebar: | |
| # Show a a Disclaimer to user to upload as clean data as possible | |
| st.info(""" | |
| ⚠️ **Heads up!** For the best experience, please upload a clean dataset. | |
| This app is designed for *visualizing data*, not cleaning it. | |
| 📌 *Tip:* Use the quick checker below to spot potential issues. | |
| """) | |
| if st.button("Run Cleanliness Check"): | |
| # Use session state to track button click | |
| st.session_state.run_clean_check = True | |
| st.divider() | |
| # Display the cleanliness checker result on the main page (not sidebar) if button was clicked | |
| if st.session_state.get("run_clean_check", False): | |
| with st.expander("➡️ See Cleanliness Checker Result"): | |
| check_dataset_cleanliness(df) | |
| # Display the user DataFrame | |
| st.markdown("Your Dataset:") | |
| st.dataframe(df, height=210) | |
| st.divider() | |
| # Extract column names from the dataset + add "No Target" element if there's no target in the user dataset | |
| feature_list = list(df.columns) | |
| target_selector = ["No Target"] + feature_list | |
| with st.sidebar: | |
| # Ask the user to select target column from their dataset | |
| target_col = st.selectbox("Specify the target column in your dataset:", target_selector) | |
| # Identify the task/type of dataset (i.e. classification/regression/clustering(if no target feature at all)) | |
| task = task_type(df, target_col) | |
| # Display the task to user | |
| st.write(f"🔍 Task identified: **{task}**") | |
| # Identify the date-time columns (if any) and extract new time-based components from it | |
| # date_time_ls --> List that will store date-time feature names | |
| # extracted_datetime --> List that will store extracted date-time feature names | |
| df, date_time_ls, extracted_datetime = parse_datetime_columns(df) | |
| # Remove date-time feature names as we already extracted time based components from it | |
| feature_list = [x for x in feature_list if x not in date_time_ls] | |
| categorical_ls = [] # List that will store categorical feature names | |
| discrete_ls = [] # List that will store discrete feature names | |
| continuous_ls = [] # List that will store continuous feature names | |
| for feature in feature_list: | |
| if is_probably_categorical(df[feature]): | |
| categorical_ls.append(feature) # Calling Categorical Feature Identifier Function | |
| elif is_discrete(df[feature]): | |
| discrete_ls.append(feature) # Calling Discrete Feature Identifier Function | |
| elif is_continuous(df[feature]): | |
| continuous_ls.append(feature) # Calling Continuous Feature Identifier Function | |
| # Add time based components that appear to be categorical | |
| for feature in extracted_datetime: | |
| if is_probably_categorical(df[feature]): | |
| categorical_ls.append(feature) | |
| # Creating Dialog Box to show identified features | |
| def open_dialog(): | |
| if categorical_ls: | |
| with st.popover("Categorical Features", use_container_width= True): | |
| st.code("\n".join([f"• {item}" for item in categorical_ls])) | |
| if discrete_ls: | |
| with st.popover("Discrete Features", use_container_width= True): | |
| st.code("\n".join([f"• {item}" for item in discrete_ls])) | |
| if continuous_ls: | |
| with st.popover("Continuous Features", use_container_width= True): | |
| st.code("\n".join([f"• {item}" for item in continuous_ls])) | |
| if date_time_ls: | |
| with st.popover("Date-Time Features", use_container_width= True): | |
| st.code("\n".join([f"• {item}" for item in date_time_ls])) | |
| with st.popover("Extracted features from your Date-Time like features", use_container_width= True): | |
| st.code("\n".join([f"• {item}" for item in extracted_datetime])) | |
| with st.sidebar: | |
| # Calling the dialog box through a button | |
| if st.button("See Your Feature Details"): | |
| open_dialog() | |
| # Generate the Plots | |
| with st.spinner("Generating Plots.....", show_time= True): | |
| if categorical_ls: | |
| st.header("📊 Categorical Plots") | |
| # 1. Count Plots | |
| count_plots = [] | |
| for x_col in categorical_ls: | |
| if df[x_col].nunique() <= 20: | |
| count_plots.extend(generate_count_plots(df, x_col)) | |
| if count_plots: | |
| st.subheader("Count Plots :-") | |
| st.plotly_chart(combine_figures_as_subplots(count_plots), use_container_width=True) | |
| # 2. Bar Plots | |
| bar_plots = [] | |
| # (Categorical vs Discrete + Continuous) | |
| for x_col in categorical_ls: | |
| if df[x_col].nunique() <= 20: | |
| bar_plots.extend(generate_bar_plots(df, x_col, discrete_ls + continuous_ls)) | |
| if bar_plots: | |
| st.subheader("Bar Plots :-") | |
| st.plotly_chart(combine_figures_as_subplots(bar_plots), use_container_width=True) | |
| # 3. Grouped Bar Plots | |
| grp_bar_plots = [] | |
| # (Categorical vs Discrete + Continuous) | |
| grp_bar_plots.extend(generate_grouped_bar_plots(df, categorical_ls, discrete_ls + continuous_ls)) | |
| if grp_bar_plots: | |
| st.subheader("Grouped Bar Plots :-") | |
| st.plotly_chart(combine_figures_as_subplots(grp_bar_plots), use_container_width=True) | |
| # 4. Pie Charts | |
| pie_plots = [] | |
| for x_col in categorical_ls: | |
| if df[x_col].nunique() <= 20: | |
| pie_plots.extend(generate_pie_plots(df, x_col)) | |
| if pie_plots: | |
| st.subheader("Pie Charts :-") | |
| st.plotly_chart(combine_figures_as_subplots(pie_plots), use_container_width=True) | |
| if continuous_ls: | |
| st.header("📊 Numerical Plots") | |
| # 5. Box Plots | |
| box_plots = [] | |
| for x_col in categorical_ls: | |
| if df[x_col].nunique() <= 10: | |
| box_plots.extend(generate_box_plots(df, x_col, continuous_ls)) | |
| if box_plots: | |
| st.subheader("Box Plots :-") | |
| st.plotly_chart(combine_figures_as_subplots(box_plots), use_container_width=True) | |
| # 6. Heat Maps | |
| heat_maps = [] | |
| if task == 'Regression': | |
| if categorical_ls: | |
| heat_maps.extend(generate_categorical_correlation_heatmap(df, target_col, categorical_ls)) | |
| heat_maps.extend(generate_numeric_correlation_heatmap(df[continuous_ls])) | |
| if heat_maps: | |
| st.subheader("Heat Maps :-") | |
| st.plotly_chart(combine_figures_as_subplots(heat_maps), use_container_width=True) | |
| # 7. Scatter Plots | |
| if len(continuous_ls) >= 2: | |
| st.subheader("Scatter Plots") | |
| scatter_plots = [] | |
| # Creation of unique feature pairs (no repetition like (B, A) if (A, B) is already used) | |
| feature_pairs = [] | |
| for i in range(len(continuous_ls)): | |
| for j in range(i + 1, len(continuous_ls)): | |
| feature_pairs.append((continuous_ls[i], continuous_ls[j])) | |
| selection = st.pills("Highlight using a categorical feature :- ", categorical_ls) | |
| scatter_plots.extend(generate_scatter_plots(df, feature_pairs, selection)) | |
| if scatter_plots: | |
| st.plotly_chart(combine_figures_as_subplots(scatter_plots), use_container_width=True) | |
| # 8. Histograms | |
| histograms = [] | |
| histograms.extend(generate_histograms(df, continuous_ls)) | |
| if histograms: | |
| st.subheader("Histograms") | |
| st.plotly_chart(combine_figures_as_subplots(histograms), use_container_width=True) | |
| # 9. Line Plots | |
| line_plots = [] | |
| if date_time_ls: | |
| # Extract only date-related components | |
| date_related_keywords = ['_year', '_month', '_day', '_weekday'] | |
| date_component_cols = [col for col in extracted_datetime if any(key in col for key in date_related_keywords)] | |
| if date_component_cols: | |
| st.subheader("Line Plots :-") | |
| # Mapping of labels to values | |
| time_grouping_options = { | |
| "Daily": "D", | |
| "Weekly": "W", | |
| "Monthly": "ME", | |
| "Yearly": "YE" | |
| } | |
| time_choice = st.pills("Choose time interval for grouping :- ", list(time_grouping_options.keys())) | |
| # Extract the actual value for resampling | |
| selected_freq = time_grouping_options[time_choice] if time_choice else "ME" # Use default "ME" if no selection | |
| line_plots.extend(generate_line_plots(df, date_component_cols, continuous_ls, selected_freq)) | |
| if line_plots: | |
| st.plotly_chart(combine_figures_as_subplots(line_plots), use_container_width= True) | |