{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":106680,"databundleVersionId":13374319,"sourceType":"competition"},{"sourceId":13929627,"sourceType":"datasetVersion","datasetId":8876672},{"sourceId":13931683,"sourceType":"datasetVersion","datasetId":8878189},{"sourceId":13945577,"sourceType":"datasetVersion","datasetId":8888247}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\n\n# Le chemin d'accès au fichier est ajusté au contexte de l'interpréteur\nINPUT_FILE_PATH = '/kaggle/input/airr-submission/submission (1).csv'\n\ntry:\n    df_submission = pd.read_csv(INPUT_FILE_PATH)\n    \n    print(\"--- 📋 INSPECTION DE LA COLONNE ID ---\")\n    \n    # 1. Identifier les valeurs NaN (celles qui causent la duplication des IDs d'attribution)\n    nan_count = df_submission['ID'].isna().sum()\n    \n    # 2. Compter le nombre total de lignes dupliquées (inclut les 400 000 NaN)\n    # L'argument keep=False marque toutes les occurrences d'une valeur dupliquée (y compris la première)\n    total_duplicate_rows = df_submission['ID'].duplicated(keep=False).sum()\n\n    print(f\"Total des lignes : {len(df_submission)}\")\n    print(f\"Nombre de valeurs manquantes (NaN) dans 'ID' : {nan_count}\")\n    print(f\"Nombre de lignes avec un ID non-unique (inclut les NaN et les IDs valides si dupliqués) : {total_duplicate_rows}\")\n\n    # 3. Afficher les IDs les plus fréquents (pour voir le 'NaN')\n    print(\"\\n--- 📊 5 IDs les plus fréquents ---\")\n    \n    # Utilisation de dropna=False pour inclure les NaN dans le décompte (s'ils existent)\n    id_counts = df_submission['ID'].value_counts(dropna=False)\n    \n    # Remplacer temporairement 'NaN' par une chaîne lisible pour l'affichage\n    top_ids = id_counts.head(5).rename(index={np.nan: 'NaN (Placeholder d\\'Attribution)'})\n    print(top_ids.to_markdown())\n\nexcept FileNotFoundError:\n    print(f\"❌ Erreur: Le fichier {INPUT_FILE_PATH} n'a pas été trouvé.\")\nexcept Exception as e:\n    print(f\"❌ Une erreur inattendue est survenue: {e}\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-01T13:48:47.186805Z","iopub.execute_input":"2025-12-01T13:48:47.187034Z","iopub.status.idle":"2025-12-01T13:48:47.566467Z","shell.execute_reply.started":"2025-12-01T13:48:47.187020Z","shell.execute_reply":"2025-12-01T13:48:47.565741Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport os\n\n# Chemin d'accès au fichier à corriger\nINPUT_FILE_PATH = '/kaggle/input/airr-submission/submission (1).csv'\n# Chemin où sauvegarder le fichier corrigé (dans /kaggle/working/ pour la soumission)\nOUTPUT_FILE_PATH = '/kaggle/working/submission_corrected.csv'\n\n# Colonne à supprimer\nCOLUMN_TO_DROP = 'ID.1'\n\ntry:\n    # Lire le fichier (avec le DtypeWarning ignoré)\n    df_submission = pd.read_csv(INPUT_FILE_PATH, low_memory=False)\n    \n    if COLUMN_TO_DROP in df_submission.columns:\n        \n        # 1. Supprimer la colonne ID.1\n        df_submission_cleaned = df_submission.drop(columns=[COLUMN_TO_DROP])\n        \n        # --- 🔎 INSPECTION DES VALEURS NULLES AJOUTÉE ---\n        print(\"\\n--- 🔎 DÉCOMPTE DES VALEURS NULLES (NaN) APRÈS SUPPRESSION DE 'ID.1' ---\")\n        print(\"Ceci confirme les colonnes à nettoyer pour l'étape suivante.\")\n        print(df_submission_cleaned.isnull().sum())\n        # -----------------------------------------------------------------------\n        \n        # 2. Sauvegarder le fichier corrigé\n        df_submission_cleaned.to_csv(OUTPUT_FILE_PATH, index=False)\n        \n        print(f\"\\n✅ Colonne '{COLUMN_TO_DROP}' supprimée avec succès.\")\n        print(f\"Nouvelle forme: {df_submission_cleaned.shape}\")\n        print(f\"Fichier corrigé sauvegardé sous: {OUTPUT_FILE_PATH}\")\n        print(\"\\n[HEAD du fichier corrigé - CONFIRMATION UNE SEULE COLONNE ID]:\")\n        print(df_submission_cleaned.head(2).to_markdown(index=False))\n\n    else:\n        print(f\"✅ La colonne '{COLUMN_TO_DROP}' n'a pas été trouvée. Le fichier est déjà prêt.\")\n\nexcept FileNotFoundError:\n    print(f\"❌ Erreur: Le fichier {INPUT_FILE_PATH} n'a pas été trouvé. Vérifiez le chemin d'accès.\")\nexcept Exception as e:\n    print(f\"❌ Une erreur inattendue est survenue: {e}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --------------------------------------------------------------------------------------\n# 🚀 CELLULE UNIQUE V7.2 : CORRECTION DU CHEMIN ET INJECTION FINALE (FIXED CSV DELIMITER)\n# --------------------------------------------------------------------------------------\nimport pandas as pd\nimport numpy as np\nimport os\n\n# --- CHEMINS D'ACCÈS ---\nSAMPLE_FILE_PATH = '/kaggle/input/adaptive-immune-profiling-challenge-2025/sample_submissions.csv' \nPREDICTIONS_FILE_PATH = '/kaggle/working/submission_corrected.csv'\nATTRIBUTION_FILENAME = '/kaggle/input/airr-df-attributions/df_attributions.csv'\nOUTPUT_FILE_PATH = '/kaggle/working/submission_final_ready_v7.csv'\n\nMISSING_SUBMISSION_VALUE = -999.0\nSTART_INJECTION_INDEX = 4213 \nCOLUMN_TO_DROP = 'ID.1' \n\ntry:\n    # 1. Charger le fichier SAMPLE comme structure de base\n    df_final = pd.read_csv(SAMPLE_FILE_PATH, low_memory=False)\n    \n    # 2. Charger les PRÉDICTIONS du participant\n    df_predictions = pd.read_csv(PREDICTIONS_FILE_PATH, low_memory=False)\n\n    if 'label_positive_probability' not in df_predictions.columns:\n         raise ValueError(\"Le fichier de prédictions du participant n'a pas la colonne 'label_positive_probability'.\")\n\n    # 3. INJECTION des PRÉDICTIONS (lignes 0 à 4212)\n    df_final.loc[:START_INJECTION_INDEX-1, 'label_positive_probability'] = df_predictions.loc[:START_INJECTION_INDEX-1, 'label_positive_probability'].values\n    print(\"✅ Prédictions du participant injectées (lignes 1 à 4213).\")\n    \n    # 4. Nettoyage de la colonne ID.1\n    if COLUMN_TO_DROP in df_final.columns:\n        df_final = df_final.drop(columns=[COLUMN_TO_DROP])\n        print(f\"✅ Colonne '{COLUMN_TO_DROP}' supprimée avec succès.\")\n\n    # 5. Charger le contenu d'Attribution\n    # 💥 CORRECTION DE L'ERREUR ICI : Retrait de delim_whitespace=True 💥\n    df_attributions = pd.read_csv(ATTRIBUTION_FILENAME).fillna(\"\")\n    \n    required_len = len(df_final) - START_INJECTION_INDEX\n    \n    if required_len > 0:\n        # Sélectionner les colonnes de contenu à injecter\n        # Cette ligne fonctionnera maintenant\n        df_content_to_inject = df_attributions[['junction_aa', 'v_call', 'j_call']].head(required_len)\n        \n        # S'assurer que les longueurs correspondent (omissions pour la concision)\n\n        # 6. REMPLACEMENT DES SÉQUENCES UNIQUEMENT\n        df_final.loc[START_INJECTION_INDEX:, 'junction_aa'] = df_content_to_inject['junction_aa'].values\n        df_final.loc[START_INJECTION_INDEX:, 'v_call'] = df_content_to_inject['v_call'].values\n        df_final.loc[START_INJECTION_INDEX:, 'j_call'] = df_content_to_inject['j_call'].values\n        \n        # S'assurer que la probabilité reste -999.0 dans la section Attribution\n        df_final.loc[START_INJECTION_INDEX:, 'label_positive_probability'] = float(MISSING_SUBMISSION_VALUE)\n\n    # 7. Finalisation et Sauvegarde\n    expected_cols = ['ID', 'dataset', 'label_positive_probability', 'junction_aa', 'v_call', 'j_call']\n    df_final = df_final[[c for c in expected_cols if c in df_final.columns]].copy()\n    \n    for col in ['ID', 'dataset', 'junction_aa', 'v_call', 'j_call']:\n        df_final[col] = df_final[col].fillna(\"\").astype(str)\n            \n    df_final['label_positive_probability'] = pd.to_numeric(df_final['label_positive_probability'], errors='coerce').fillna(MISSING_SUBMISSION_VALUE).astype(float)\n    \n    df_final.to_csv(OUTPUT_FILE_PATH, index=False)\n\n    # 8. Inspection et vérification des IDs\n    print(\"\\n--- 🔎 INSPECTION FINALE DU DATAFRAME CORRIGÉ V7.2 ---\")\n    \n    if df_final['ID'].nunique() == len(df_final):\n        print(\"✅ VÉRIFICATION ID : La colonne 'ID' est entièrement unique. C'est parfait pour la soumission.\")\n    else:\n        num_duplicates = len(df_final) - df_final['ID'].nunique()\n        print(f\"❌ VÉRIFICATION ID : ATTENTION ! {num_duplicates} doublons trouvés dans la colonne 'ID'. La soumission risque d'échouer.\")\n\n    print(\"\\n[HEAD - 5 premières lignes (Classification - Vos Prédictions)]\")\n    print(df_final[['ID', 'dataset', 'label_positive_probability', 'junction_aa']].head().to_markdown(index=False))\n\n    print(\"\\n[TAIL - 5 dernières lignes (Attribution - NOUVELLES Séquences)]\")\n    print(df_final[['ID', 'dataset', 'label_positive_probability', 'junction_aa']].tail().to_markdown(index=False))\n\n    print(f\"\\n🎉 Fichier INTERMÉDIAIRE V7.2 PRÊT À ÊTRE TRAITÉ PAR V8 : {OUTPUT_FILE_PATH}\")\n\nexcept FileNotFoundError as e:\n    print(f\"❌ Erreur: L'un des fichiers n'a pas été trouvé. Vérifiez le chemin : {e}\")\nexcept Exception as e:\n    print(f\"❌ Une erreur inattendue est survenue: {e}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\n\n# Fichier intermédiaire (généré par le script V7)\nINPUT_FILE_PATH = '/kaggle/working/submission_final_ready_v7.csv'\n# Fichier FINAL prêt à soumettre\nOUTPUT_FILE_PATH = '/kaggle/working/submission_final_ready_v8.csv'\n\n# Colonnes qui doivent être des chaînes\nSTRING_COLS_FOR_RECAST = ['ID', 'dataset', 'junction_aa', 'v_call', 'j_call']\nFLOAT_COLS = ['label_positive_probability']\n\ntry:\n    df_final = pd.read_csv(INPUT_FILE_PATH, low_memory=False)\n\n    print(f\"Fichier intermédiaire chargé. Forme: {df_final.shape}\")\n    print(\"\\n--- DÉCOMPTE DES NaN AVANT CORRECTION ---\")\n    print(df_final.isnull().sum())\n    \n    # 1. Remplir les NaN de toutes les colonnes STRING par une chaîne vide \"\"\n    for col in STRING_COLS_FOR_RECAST:\n        if col in df_final.columns:\n            # S'assurer que tous les NaN sont des chaînes vides avant le type casting final\n            df_final[col] = df_final[col].fillna(\"\").astype(str)\n            \n    # 2. Remplir les NaN des colonnes FLOAT par -999.0 float\n    for col in FLOAT_COLS:\n        if col in df_final.columns:\n            df_final[col] = pd.to_numeric(df_final[col], errors='coerce').fillna(float(MISSING_SUBMISSION_VALUE)).astype(float)\n\n\n    # 3. Sauvegarde du fichier corrigé\n    df_final.to_csv(OUTPUT_FILE_PATH, index=False)\n    \n    # 4. INSPECTION FINALE DU FICHIER EXPORTÉ (vérification ultime du format)\n    df_check_exported = pd.read_csv(OUTPUT_FILE_PATH, low_memory=False)\n    \n    print(\"\\n--- 🔎 INSPECTION FINALE DU FICHIER EXPORTÉ V8 (Post-Export) ---\")\n    \n    # Décompte des NaN sur le fichier relu\n    nan_count_exported = df_check_exported.isnull().sum().sum()\n    if nan_count_exported == 0:\n        print(f\"✅ Aucune valeur nulle (NaN) trouvée dans le fichier exporté.\")\n    else:\n        print(f\"❌ Erreur critique : {nan_count_exported} NaN sont encore présents après export.\")\n        print(df_check_exported.isnull().sum())\n        \n    # Vérification des types\n    print(\"\\n[Vérification des 5 premières lignes et des types de colonnes (doit être clean)]:\")\n    print(df_check_exported.head(5).to_markdown(index=False))\n    \n    # Vérification des types des colonnes textuelles (pour s'assurer que \"\" n'est pas devenu NaN à l'export)\n    print(\"\\n[Vérification des Types des colonnes Clés (doit être float pour la probabilité et object/string pour le reste)]:\")\n    print(df_check_exported.dtypes.to_markdown())\n\n    print(f\"\\n🎉 Fichier FINAL V8 PRÊT À ÊTRE SOUMIS : {OUTPUT_FILE_PATH}\")\n\nexcept FileNotFoundError:\n    print(f\"❌ Erreur: Le fichier {INPUT_FILE_PATH} n'a pas été trouvé.\")\nexcept Exception as e:\n    print(f\"❌ Une erreur inattendue est survenue: {e}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport os\n\n# Chemin d'accès au fichier sample_submissions.csv\nINPUT_FILE_PATH = '/kaggle/input/adaptive-immune-profiling-challenge-2025/sample_submissions.csv'\n# Index de départ pour l'inspection (ligne 4214 = index 4213)\nSTART_INSPECTION_INDEX = 4213 \n# Nombre de lignes à afficher\nROWS_TO_DISPLAY = 15 \n\ntry:\n    # Charger le fichier (low_memory=False pour gérer les types mixtes)\n    # L'en-tête est souvent dupliqué ou incorrectement lu dans ce type de fichier, \n    # d'où la nécessité de 'low_memory=False'.\n    df_sample = pd.read_csv(INPUT_FILE_PATH, low_memory=False)\n    \n    # Isoler les colonnes d'intérêt\n    cols_of_interest = ['ID', 'dataset', 'label_positive_probability', 'junction_aa', 'v_call', 'j_call']\n    \n    # Isoler les lignes de la section Attribution (à partir de l'index 4213)\n    df_attribution_section = df_sample[cols_of_interest].iloc[START_INSPECTION_INDEX:]\n    \n    print(f\"\\n--- 🔎 INSPECTION DE LA SECTION ATTRIBUTION ({ROWS_TO_DISPLAY} LIGNES à partir de la ligne 4214) ---\")\n    \n    # Afficher le résultat\n    print(df_attribution_section.head(ROWS_TO_DISPLAY).to_markdown(index=True))\n    \n    print(\"\\n--- RAPPEL DES VALEURS UNIQUES DANS LA SECTION JONCTION ---\")\n    # Confirmer ce qui est dans les colonnes des séquences\n    print(f\"Valeurs uniques dans 'junction_aa' (section Attribution) : {df_attribution_section['junction_aa'].unique()}\")\n    print(f\"Valeurs uniques dans 'v_call' (section Attribution) : {df_attribution_section['v_call'].unique()}\")\n    \nexcept FileNotFoundError:\n    print(f\"❌ Erreur: Le fichier {INPUT_FILE_PATH} n'a pas été trouvé. Vérifiez le chemin d'accès.\")\nexcept Exception as e:\n    print(f\"❌ Une erreur inattendue est survenue: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-01T14:30:47.049014Z","iopub.execute_input":"2025-12-01T14:30:47.049323Z","iopub.status.idle":"2025-12-01T14:30:48.352233Z","shell.execute_reply.started":"2025-12-01T14:30:47.049305Z","shell.execute_reply":"2025-12-01T14:30:48.350826Z"}},"outputs":[],"execution_count":null}]}