{"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":36363,"databundleVersionId":4050810,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"1. Ознайомитись з набором даних https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection. Для читання зображень (https://www.kaggle.com/code/micheldc55/how-to-read-dcm-dicom-data)\n\n2. Виконати пояснювальний аналіз даних.\n\n3. Визначити збалансованість класів.","metadata":{}},{"cell_type":"code","source":"import os\nimport glob\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\n\ndef find_competition_path():\n    candidates = [\n        '/kaggle/input/rsna-2022-cervical-spine-fracture-detection',\n        '/kaggle/input/rsna-2022-cervical-spine-fracture-detection/data'\n    ]\n    for c in candidates:\n        if os.path.exists(c):\n            return c\n    for p in glob.glob('/kaggle/input/*'):\n        if 'rsna' in os.path.basename(p).lower():\n            return p\n\n\nCOMP_PATH = find_competition_path()\nprint('Використовується шлях:', COMP_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T10:56:22.126497Z","iopub.execute_input":"2025-10-30T10:56:22.12678Z","iopub.status.idle":"2025-10-30T10:56:22.133048Z","shell.execute_reply.started":"2025-10-30T10:56:22.126757Z","shell.execute_reply":"2025-10-30T10:56:22.13226Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\n\ncsv_files = [f for f in os.listdir(COMP_PATH) if f.endswith('.csv')]\ndfs = {}\n\nprint(f\"Знайдено CSV: {len(csv_files)}\")\nfor f in csv_files:\n    fpath = os.path.join(COMP_PATH, f)\n    try:\n        df = pd.read_csv(fpath)\n        dfs[f.replace('.csv', '')] = df\n        print(f\" {f} — зчитано ({df.shape[0]} рядків, {df.shape[1]} колонок)\")\n    except Exception as e:\n        print(f\"Помилка при зчитуванні {f}: {e}\")\n\nfor name, df in dfs.items():\n    print(f'\\n--- {name} ---')\n    display(df.head())\n    print('Колонки:', df.columns.tolist())\n    print('Відсутні значення:')\n    print(df.isnull().sum().sort_values(ascending=False).head(10))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T10:57:28.610101Z","iopub.execute_input":"2025-10-30T10:57:28.610444Z","iopub.status.idle":"2025-10-30T10:57:28.722983Z","shell.execute_reply.started":"2025-10-30T10:57:28.610416Z","shell.execute_reply":"2025-10-30T10:57:28.722266Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\nimport pandas as pd\n\ndef find_label_columns(df):\n    candidates = []\n    for c in df.columns:\n        lc = c.lower()\n        if any(k in lc for k in ['label', 'fracture', 'target', 'class']):\n            candidates.append(c)\n        elif df[c].nunique(dropna=True) <= 3 and pd.api.types.is_numeric_dtype(df[c]):\n            candidates.append(c)\n    return list(set(candidates))\n\n\nlabel_summary = {}\n\nfor name, df in dfs.items():\n    labels = find_label_columns(df)\n    for lab in labels:\n        counts = df[lab].value_counts(dropna=False)\n        pct = (counts / len(df) * 100).round(2)\n        res = pd.DataFrame({'Кількість': counts, 'Відсоток': pct})\n        label_summary[(name, lab)] = res\n\n        display(res)\n\n        plt.figure(figsize=(6,4))\n        sns.barplot(\n            x=res.index.astype(str),\n            y='Кількість',\n            data=res.reset_index().rename(columns={'index': lab})\n        )\n        plt.title(f'Розподіл класів для {name}.{lab}')\n        plt.xlabel('Клас')\n        plt.ylabel('Кількість')\n        plt.tight_layout()\n        plt.savefig(f'/kaggle/working/balance_{name}_{lab}.png')\n        plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T11:04:29.55053Z","iopub.execute_input":"2025-10-30T11:04:29.550816Z","iopub.status.idle":"2025-10-30T11:04:31.737736Z","shell.execute_reply.started":"2025-10-30T11:04:29.550792Z","shell.execute_reply":"2025-10-30T11:04:31.736902Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport glob\nimport pydicom\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\ntrain_path = os.path.join(COMP_PATH, \"train_images\")\ntest_path = os.path.join(COMP_PATH, \"test_images\")\n\nsubdirs = sorted([os.path.join(train_path, d) for d in os.listdir(train_path)])[:3]\ntrain_dicom_files = []\nfor d in subdirs:\n    train_dicom_files.extend(glob.glob(os.path.join(d, '*.dcm')))\ntrain_dicom_files = train_dicom_files[:5] \n\nfor f in train_dicom_files:\n    print(\" -\", os.path.relpath(f, COMP_PATH))\n\ndef read_dicom_image(path, voi_lut=True):\n    ds = pydicom.dcmread(path)\n    img = ds.pixel_array\n    if voi_lut:\n        try:\n            img = apply_voi_lut(img, ds)\n        except Exception:\n            pass\n    img = img.astype(np.float32)\n    img = (img - img.min()) / (img.max() - img.min() + 1e-8)\n    return (img * 255).astype(np.uint8), ds\n\nif train_dicom_files:\n    sample_path = train_dicom_files[0]\n    img, ds = read_dicom_image(sample_path)\n    print(f\"\\nПриклад DICOM-зображення:\\n{sample_path}\")\n    plt.figure(figsize=(6,6))\n    plt.imshow(img, cmap='gray')\n    plt.axis('off')\n    plt.title('Приклад DICOM')\n    plt.show()\nelse:\n    print('Не знайдено DICOM-файлів')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T10:59:38.880131Z","iopub.execute_input":"2025-10-30T10:59:38.880485Z","iopub.status.idle":"2025-10-30T10:59:39.069196Z","shell.execute_reply.started":"2025-10-30T10:59:38.880449Z","shell.execute_reply":"2025-10-30T10:59:39.068357Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for (dfname, lab), tab in label_summary.items():\n    out = f'/kaggle/working/class_balance_{dfname}_{lab}.csv'\n    tab.to_csv(out)\n    print('Збережено:', out)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T11:00:04.514921Z","iopub.execute_input":"2025-10-30T11:00:04.515885Z","iopub.status.idle":"2025-10-30T11:00:04.533489Z","shell.execute_reply.started":"2025-10-30T11:00:04.515849Z","shell.execute_reply":"2025-10-30T11:00:04.532562Z"}},"outputs":[],"execution_count":null}]}