diff --git a/README.md b/README.md
index 2289cc4..96e4260 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,7 @@
diff --git a/app.py b/app.py index 7c88018..ba309e2 100644 --- a/app.py +++ b/app.py @@ -135,18 +135,33 @@ def load_kaggle_data(kaggle_input): else: dataset_id = kaggle_input - # Download using existing handler - file_path = KaggleHandler.download_dataset(dataset_id) + # Fetch all supported files + files = KaggleHandler.download_files(dataset_id) + + # Store found files in session state so we can let the user pick one if needed + st.session_state.kaggle_files = files + st.session_state.kaggle_dataset_id = dataset_id - # Load data - df = read_data(file_path) - st.session_state.df = df - st.session_state.input_source = dataset_id - st.success(f"Successfully loaded data from '{dataset_id}'") + # If there's only one file, load it immediately + if len(files) == 1: + _load_specific_kaggle_file(files[0], dataset_id) except Exception as e: st.error(f"Error processing Kaggle dataset: {e}") +def _load_specific_kaggle_file(file_path, dataset_id): + """Helper to load a specific file from a Kaggle dataset.""" + try: + with st.spinner(f"Loading {file_path.name}..."): + df = read_data(file_path) + st.session_state.df = df + st.session_state.input_source = f"{dataset_id}/{file_path.name}" + st.success(f"Successfully loaded '{file_path.name}' from '{dataset_id}'") + # Clear the file list selection state once loaded, if you prefer + # st.session_state.kaggle_files = None + except Exception as e: + st.error(f"Error loading file: {e}") + def render_ingestion(): """Render the data ingestion section (Local File & Kaggle Tabs).""" @@ -173,6 +188,33 @@ def render_ingestion(): load_kaggle_data(kaggle_input) else: st.warning("Please enter a valid Dataset ID or URL.") + + # Check if we have multiple files to choose from + if "kaggle_files" in st.session_state and st.session_state.kaggle_files: + files = st.session_state.kaggle_files + if len(files) > 1: + st.info(f"Found {len(files)} files. Please select one:") + + # Create a mapping of full path -> file object to ensure uniqueness + file_mapping = {str(f): f for f in files} + + def extract_display_name(path_str): + """Format the display name to be shorter if possible""" + f = file_mapping[path_str] + return f"{f.parent.name}/{f.name}" + + selected_file_key = st.selectbox( + "Select file", + options=list(file_mapping.keys()), + format_func=extract_display_name, + key="kaggle_file_select" + ) + + if st.button("Load Selected File", key="btn_kaggle_multiload"): + # Find the path for the selected file using the mapping + selected_path = file_mapping.get(selected_file_key) + if selected_path: + _load_specific_kaggle_file(selected_path, st.session_state.kaggle_dataset_id) def render_preview(): diff --git a/src/dora/kaggle.py b/src/dora/kaggle.py index 80f4857..42c51e3 100644 --- a/src/dora/kaggle.py +++ b/src/dora/kaggle.py @@ -50,12 +50,12 @@ def extract_dataset_id(input_str: str) -> str: return input_str @staticmethod - def download_dataset(dataset_id: str) -> Path: + def download_files(dataset_id: str) -> list[Path]: """ - Download a Kaggle dataset from kagglehub and return the path to the downloaded file. - - :param dataset_id: The 'owner/dataset-name' identifier of the dataset to download. - :return: The path to the downloaded file. + Download a Kaggle dataset and return a list of all supported files. + + :param dataset_id: The 'owner/dataset-name' identifier. + :return: List of Path objects for supported files. """ logging.info("Downloading dataset %s", dataset_id) try: @@ -74,6 +74,19 @@ def download_dataset(dataset_id: str) -> Path: if not files: raise ValueError("No supported files found in the downloaded dataset.") + + return files + + @staticmethod + def download_dataset(dataset_id: str) -> Path: + """ + Download a Kaggle dataset from kagglehub and return the path to the downloaded file. + If multiple files are present, it prompts the user to select one (CLI mode). + + :param dataset_id: The 'owner/dataset-name' identifier of the dataset to download. + :return: The path to the downloaded file. + """ + files = KaggleHandler.download_files(dataset_id) if len(files) == 1: return files[0] diff --git a/src/dora/plots/multivariate.py b/src/dora/plots/multivariate.py index 74a6be1..6e8c44d 100644 --- a/src/dora/plots/multivariate.py +++ b/src/dora/plots/multivariate.py @@ -11,6 +11,7 @@ matplotlib.use("Agg") import matplotlib.pyplot as plt +import numpy as np import pandas as pd import seaborn as sns @@ -48,8 +49,9 @@ def generate_plots( plt.figure(figsize=(12, 10)) corr = df_numeric.corr() + mask = np.triu(np.ones_like(corr, dtype=bool)) cmap = sns.diverging_palette(230, 20, as_cmap=True) - sns.heatmap(corr, annot=True, fmt=".2f", cmap=cmap, linewidths=0.5) + sns.heatmap(corr, mask=mask, annot=True, fmt=".2f", cmap=cmap, linewidths=0.5) plt.title( "Correlation Matrix of Numerical Features", loc="left",