{"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":35332,"databundleVersionId":3723648,"sourceType":"competition"}],"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\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport warnings\nimport gc\nfrom tqdm import tqdm\nimport dask.dataframe as dd\nfrom sklearn.preprocessing import LabelEncoder\nfrom scipy import stats\n\nwarnings.filterwarnings('ignore')\nplt.style.use('seaborn-v0_8-darkgrid')\nsns.set_palette(\"husl\")\n\n# Настройка для работы с большими данными\npd.set_option('display.max_columns', None)\npd.set_option('display.max_rows', 100)\npd.set_option('display.float_format', '{:.3f}'.format)\n\n# Функция для очистки памяти\ndef clear_memory():\n    gc.collect()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-07T16:56:34.962293Z","iopub.execute_input":"2025-12-07T16:56:34.962616Z","iopub.status.idle":"2025-12-07T16:56:40.481500Z","shell.execute_reply.started":"2025-12-07T16:56:34.962589Z","shell.execute_reply":"2025-12-07T16:56:40.480536Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels = pd.read_csv('/kaggle/input/amex-default-prediction/train_labels.csv')\nprint(f\"Размер train_labels: {train_labels.shape}\")\nprint(f\"Количество уникальных клиентов: {train_labels['customer_ID'].nunique()}\")\nprint(\"\\nПервые 5 строк:\")\nprint(train_labels.head())\nprint(f\"\\nДубликатов customer_ID: {train_labels['customer_ID'].duplicated().sum()}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T16:56:40.483264Z","iopub.execute_input":"2025-12-07T16:56:40.483872Z","iopub.status.idle":"2025-12-07T16:56:42.130370Z","shell.execute_reply.started":"2025-12-07T16:56:40.483838Z","shell.execute_reply":"2025-12-07T16:56:42.129470Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Распределение классов:\")\nclass_dist = train_labels['target'].value_counts()\nprint(class_dist)\nprint(f\"\\nДоля класса 1 (дефолт): {class_dist[1]/len(train_labels)*100:.2f}%\")\n\nfig, ax = plt.subplots(1, 1, figsize=(5, 5))\nax.pie(class_dist.values, labels=['Не дефолт (0)', 'Дефолт (1)'], \n            autopct='%1.1f%%', colors=['green', 'red'], startangle=90)\nax.set_title('Процентное распределение')\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T16:56:42.131354Z","iopub.execute_input":"2025-12-07T16:56:42.132402Z","iopub.status.idle":"2025-12-07T16:56:42.349300Z","shell.execute_reply.started":"2025-12-07T16:56:42.132370Z","shell.execute_reply":"2025-12-07T16:56:42.347872Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_sample = pd.read_csv('/kaggle/input/amex-default-prediction/train_data.csv', nrows=100000)\nprint(f\"Размер сэмпла: {train_sample.shape}\")\nprint(\"\\nТипы данных:\")\nprint(train_sample.dtypes.value_counts())\n\nprint(\"\\nПервые 5 строк:\")\nprint(train_sample.head())\nprint(\"\\nИнформация о датасете:\")\nprint(train_sample.info(memory_usage='deep'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T16:56:42.350246Z","iopub.execute_input":"2025-12-07T16:56:42.350534Z","iopub.status.idle":"2025-12-07T16:56:49.811909Z","shell.execute_reply.started":"2025-12-07T16:56:42.350494Z","shell.execute_reply":"2025-12-07T16:56:49.810993Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Анализ временных меток:\")\ntrain_sample['S_2'] = pd.to_datetime(train_sample['S_2'])\nprint(f\"Уникальные значения S_2 (дата): {train_sample['S_2'].nunique()}\")\nprint(f\"Диапазон дат: от {train_sample['S_2'].min()} до {train_sample['S_2'].max()}\")\n\n# Анализ количества записей на клиента\nrecords_per_customer = train_sample.groupby('customer_ID').size()\nprint(f\"\\nСтатистика записей на клиента:\")\nprint(f\"Среднее: {records_per_customer.mean():.2f}\")\nprint(f\"Медиана: {records_per_customer.median():.2f}\")\nprint(f\"Мин: {records_per_customer.min()}\")\nprint(f\"Макс: {records_per_customer.max()}\")\nprint(f\"Стандартное отклонение: {records_per_customer.std():.2f}\")\n\n# Визуализация\nfig, axes = plt.subplots(1, 2, figsize=(14, 5))\n\n# Распределение количества записей на клиента\naxes[0].hist(records_per_customer, bins=50, edgecolor='black')\naxes[0].set_title('Распределение количества записей на клиента')\naxes[0].set_xlabel('Количество записей')\naxes[0].set_ylabel('Частота')\n\n# Временной анализ (количество записей по месяцам)\nmonthly_counts = train_sample['S_2'].dt.to_period('M').value_counts().sort_index()\naxes[1].bar(range(len(monthly_counts)), monthly_counts.values)\naxes[1].set_title('Количество записей по месяцам')\naxes[1].set_xlabel('Месяц')\naxes[1].set_ylabel('Количество записей')\naxes[1].set_xticks(range(len(monthly_counts)))\naxes[1].set_xticklabels([str(p) for p in monthly_counts.index], rotation=45)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T16:56:49.813715Z","iopub.execute_input":"2025-12-07T16:56:49.813986Z","iopub.status.idle":"2025-12-07T16:56:50.358390Z","shell.execute_reply.started":"2025-12-07T16:56:49.813966Z","shell.execute_reply":"2025-12-07T16:56:50.357449Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"chunk_size = 100000\nmissing_stats = []\ntotal_rows = 0\n\nprint(\"Анализ пропущенных значений по частям...\")\nfor chunk in tqdm(pd.read_csv('/kaggle/input/amex-default-prediction/train_data.csv', chunksize=chunk_size)):\n    missing_percent = chunk.isnull().sum() / len(chunk) * 100\n    missing_stats.append(missing_percent)\n    total_rows += len(chunk)\n\n# Объединяем статистику\nmissing_df = pd.DataFrame(missing_stats).mean().sort_values(ascending=False)\nmissing_df = pd.DataFrame({'feature': missing_df.index, 'missing_percent': missing_df.values})\n\nprint(\"\\nТоп признаков с наибольшим количеством пропусков:\")\nprint(missing_df.head(35))\n\n# Визуализация\nplt.figure(figsize=(12, 12))\ntop_35 = missing_df.head(35)\nplt.barh(top_35['feature'], top_35['missing_percent'])\nplt.xlabel('Процент пропусков (%)')\nplt.ylabel('Признаки')\nplt.title('Топ признаков с наибольшим количеством пропусков')\nplt.gca().invert_yaxis()\nplt.tight_layout()\nplt.show()\n\nclear_memory()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T16:56:50.359311Z","iopub.execute_input":"2025-12-07T16:56:50.359610Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"categorical_features = ['B_30', 'B_38', 'D_114', 'D_116', 'D_117', 'D_120', \n                        'D_126', 'D_63', 'D_64', 'D_66', 'D_68']\ntrain_sample = pd.read_csv('/kaggle/input/amex-default-prediction/train_data.csv', nrows=500000)\n\nprint(\"Анализ типов признаков:\")\nprint(f\"Всего признаков: {train_sample.shape[1]}\")\n\n# Разделяем признаки по категориям\nnumeric_features = []\ncat_features_found = []\nfor col in train_sample.columns:\n    if col in categorical_features:\n        cat_features_found.append(col)\n    elif col not in ['customer_ID', 'S_2', 'target']:\n        numeric_features.append(col)\n\nprint(f\"\\nКатегориальные признаки (из описания): {len(cat_features_found)}\")\nprint(f\"Числовые признаки: {len(numeric_features)}\")\nprint(f\"Служебные колонки: customer_ID, S_2\")\n\nprint(\"\\nАнализ категориальных признаков:\")\nfor col in cat_features_found:\n    if col in train_sample.columns:\n        unique_vals = train_sample[col].nunique()\n        print(f\"{col}: {unique_vals} уникальных значений\")\n        \n        plt.figure(figsize=(10, 4))\n        train_sample[col].value_counts().head(20).plot(kind='bar')\n        plt.title(f'Распределение признака {col}')\n        plt.xlabel('Значение')\n        plt.ylabel('Частота')\n        plt.xticks(rotation=45)\n        plt.tight_layout()\n        plt.show()\n\nclear_memory()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Анализ распределения числовых признаков...\")\nsample_features = numeric_features[:20]  # Первые 20 числовых признаков\n\nfig, axes = plt.subplots(5, 4, figsize=(20, 15))\naxes = axes.flatten()\n\nfor i, col in enumerate(sample_features):\n    axes[i].hist(train_sample[col].dropna(), bins=50, alpha=0.7, edgecolor='black')\n    axes[i].set_title(f'{col}')\n    axes[i].set_xlabel('Значение')\n    axes[i].set_ylabel('Частота')\n    \n    mean_val = train_sample[col].mean()\n    median_val = train_sample[col].median()\n    axes[i].axvline(mean_val, color='red', linestyle='--', alpha=0.7, label=f'Mean: {mean_val:.2f}')\n    axes[i].axvline(median_val, color='green', linestyle='--', alpha=0.7, label=f'Median: {median_val:.2f}')\n    axes[i].legend(fontsize=8)\n\nplt.tight_layout()\nplt.show()\n\nprint(\"\\nБазовые статистики для числовых признаков:\")\nstats_df = pd.DataFrame({\n    'mean': train_sample[sample_features].mean(),\n    'std': train_sample[sample_features].std(),\n    'min': train_sample[sample_features].min(),\n    '25%': train_sample[sample_features].quantile(0.25),\n    '50%': train_sample[sample_features].quantile(0.50),\n    '75%': train_sample[sample_features].quantile(0.75),\n    'max': train_sample[sample_features].max(),\n    'missing': train_sample[sample_features].isnull().sum() / len(train_sample) * 100\n})\nprint(stats_df)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Анализ выбросов...\")\nselected_features = numeric_features[:20]\n\nfig, axes = plt.subplots(2, 10, figsize=(20, 15))\naxes = axes.flatten()\n\nfor i, col in enumerate(selected_features):\n    train_sample[[col]].boxplot(ax=axes[i])\n    axes[i].set_title(f'{col}')\n    axes[i].set_ylabel('Значение')\n    \n    # Правило 1.5*IQR\n    Q1 = train_sample[col].quantile(0.25)\n    Q3 = train_sample[col].quantile(0.75)\n    IQR = Q3 - Q1\n    lower_bound = Q1 - 1.5 * IQR\n    upper_bound = Q3 + 1.5 * IQR\n    \n    outliers = train_sample[(train_sample[col] < lower_bound) | (train_sample[col] > upper_bound)]\n    outlier_percent = len(outliers) / len(train_sample) * 100\n    \n    axes[i].text(0.05, 0.95, f'Выбросов: {outlier_percent:.1f}%', \n                transform=axes[i].transAxes, fontsize=10,\n                verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Анализ корреляций...\")\ncustomer_target_map = train_labels.set_index('customer_ID')['target'].to_dict()\ntrain_sample['target'] = train_sample['customer_ID'].map(customer_target_map)\ncorr_features = numeric_features[:20] + ['target']\n\ncorr_matrix = train_sample[corr_features].corr(method='spearman')\ntarget_correlations = corr_matrix['target'].drop('target').sort_values(ascending=False)\n\nprint(\"\\nТоп признаков с наибольшей корреляцией с target:\")\nprint(target_correlations.head(20))\n\n# Визуализация корреляций с целевой переменной\nplt.figure(figsize=(12, 6))\ntop_corr = target_correlations.head(20)\ncolors = ['red' if x < 0 else 'blue' for x in top_corr.values]\nplt.barh(top_corr.index, top_corr.values, color=colors)\nplt.xlabel('Корреляция с target (Spearman)')\nplt.title('Топ признаков по корреляции с целевой переменной')\nplt.axvline(x=0, color='black', linestyle='-', linewidth=0.5)\nplt.tight_layout()\nplt.show()\n\ntop_features = list(target_correlations.head(15).index) + ['target']\nplt.figure(figsize=(12, 10))\nsns.heatmap(train_sample[top_features].corr(method='spearman'), \n            cmap='coolwarm', center=0, annot=True, fmt='.2f')\nplt.title('Корреляционная матрица (топ-15 признаков + target)')\nplt.tight_layout()\nplt.show()\n\nclear_memory()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Анализ возможных преобразований и генерации новых признаков","metadata":{}},{"cell_type":"markdown","source":"1) Генерация временных признаков: Месяц, квартал, год, День месяца, день недели\n2) Агрегированные признаки для каждого клиента: Среднее, Медиана, std по всем временным точкам. Минимум, Максимум. Количество записей на клиента. Тренд\n3) Отбрасывание признаков с большим кол-ом пропусков. Заполнение пропусков аггрегациями.\n4) Можно попробовать брать отношения между связанными признаками или их отношения.\n5) Логарифмирование для скошенных распределений. Категоризация непрерывных признаков (биннинг)","metadata":{}},{"cell_type":"markdown","source":"### P.S. Анализ тестового сета предоставлять не буду, в нем я бы повторил тоже самое, что не затрагивает target.","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}