diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/2zadanie.iml b/.idea/2zadanie.iml new file mode 100644 index 0000000..2c80e12 --- /dev/null +++ b/.idea/2zadanie.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..22fba57 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.ipynb_checkpoints/week2_analysis-checkpoint.ipynb b/.ipynb_checkpoints/week2_analysis-checkpoint.ipynb new file mode 100644 index 0000000..cae9fb3 --- /dev/null +++ b/.ipynb_checkpoints/week2_analysis-checkpoint.ipynb @@ -0,0 +1,507 @@ +{ + "cells": [ + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Анализ данных пассажиров Титаника\n", + "\n", + "**Источник данных:** Kaggle - Titanic: Machine Learning from Disaster\n", + "**Цель анализа:** Изучить факторы, влияющие на выживаемость пассажиров\n", + "\n", + "**Дата анализа:** 07.05.2026" + ], + "id": "849d0fe9d43b3ad2" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Импорт библиотек (изменен стиль импорта)\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "from tqdm import tqdm\n", + "import warnings\n", + "warnings.filterwarnings('ignore')\n", + "\n", + "# Настройка отображения\n", + "%matplotlib inline\n", + "plt.rcParams['figure.figsize'] = (12, 6)\n", + "plt.style.use('seaborn-v0_8-darkgrid')\n", + "sns.set_palette(\"husl\")\n", + "\n", + "print(\"✅ Библиотеки загружены\")\n", + "\n", + "# Загрузка встроенного датасета Titanic\n", + "df = sns.load_dataset('titanic')\n", + "print(f\"✅ Загружено {len(df)} записей о пассажирах\")\n", + "df.head(10) # Вывод в последней строке ячейки" + ], + "id": "7b68a95f07cd5093" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "print(\"📊 ПЕРВИЧНЫЙ АНАЛИЗ ДАННЫХ\")\n", + "print(\"=\" * 50)\n", + "\n", + "print(\"\\n1. Информация о данных (df.info()):\")\n", + "print(df.info())\n", + "\n", + "print(\"\\n2. Статистическое описание (df.describe()):\")\n", + "print(df.describe())\n", + "\n", + "# Дополнительный анализ\n", + "print(\"\\n3. Анализ выживаемости по полу (изменено от примера):\")\n", + "print(pd.crosstab(df['sex'], df['alive'], normalize='index') * 100)" + ], + "id": "82fb50b6dfcb725a" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Анализ пропущенных значений\n", + "missing_data = df.isnull().sum()\n", + "missing_percent = (missing_data / len(df)) * 100\n", + "\n", + "missing_df = pd.DataFrame({\n", + " 'Кол-во пропусков': missing_data,\n", + " 'Процент': missing_percent\n", + "}).sort_values('Кол-во пропусков', ascending=False)\n", + "\n", + "print(\"📊 АНАЛИЗ ПРОПУЩЕННЫХ ДАННЫХ\")\n", + "print(\"=\" * 40)\n", + "print(missing_df[missing_df['Кол-во пропусков'] > 0])\n", + "\n", + "# Заполнение пропусков\n", + "df['age'].fillna(df['age'].median(), inplace=True)\n", + "df['embarked'].fillna(df['embarked'].mode()[0], inplace=True)\n", + "df.drop('deck', axis=1, inplace=True)\n", + "\n", + "print(f\"\\n✅ Пропуски заполнены. Размер данных: {df.shape}\")" + ], + "id": "8624dc43d9bf124d" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Гистограмма распределения возрастов\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "# Разделение по выжившим/погибшим\n", + "survived = df[df['survived'] == 1]['age']\n", + "died = df[df['survived'] == 0]['age']\n", + "\n", + "plt.hist(survived, bins=20, alpha=0.7, label='Выжившие', color='green', edgecolor='black')\n", + "plt.hist(died, bins=20, alpha=0.7, label='Погибшие', color='red', edgecolor='black')\n", + "\n", + "plt.xlabel('Возраст', fontsize=12)\n", + "plt.ylabel('Количество пассажиров', fontsize=12)\n", + "plt.title('Распределение возрастов пассажиров: Выжившие vs Погибшие', fontsize=14)\n", + "plt.axvline(survived.mean(), color='darkgreen', linestyle='--',\n", + " label=f'Ср. возраст выживших: {survived.mean():.1f}', alpha=0.8)\n", + "plt.axvline(died.mean(), color='darkred', linestyle='--',\n", + " label=f'Ср. возраст погибших: {died.mean():.1f}', alpha=0.8)\n", + "plt.legend()\n", + "plt.grid(alpha=0.3)\n", + "plt.show()\n", + "\n", + "print(f\"\\n📊 Вывод: Средний возраст выживших ({survived.mean():.1f}) выше, чем погибших ({died.mean():.1f})\")" + ], + "id": "ecea1247c0fbb76f" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Scatterplot: возраст vs стоимость билета\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "# Разные цвета для выживших и погибших\n", + "colors = df['survived'].map({0: 'red', 1: 'green'})\n", + "plt.scatter(df['age'], df['fare'], c=colors, alpha=0.6, s=50)\n", + "\n", + "plt.xlabel('Возраст (лет)', fontsize=12)\n", + "plt.ylabel('Стоимость билета ($)', fontsize=12)\n", + "plt.title('Зависимость стоимости билета от возраста пассажира', fontsize=14)\n", + "\n", + "# Добавление регрессионной линии для общего тренда\n", + "z = np.polyfit(df['age'].dropna(), df['fare'].dropna(), 1)\n", + "p = np.poly1d(z)\n", + "plt.plot(df['age'].dropna().sort_values(), p(df['age'].dropna().sort_values()),\n", + " 'b--', alpha=0.8, label='Тренд')\n", + "\n", + "# Легенда\n", + "from matplotlib.patches import Patch\n", + "legend_elements = [Patch(facecolor='green', alpha=0.6, label='Выжившие'),\n", + " Patch(facecolor='red', alpha=0.6, label='Погибшие')]\n", + "plt.legend(handles=legend_elements)\n", + "plt.grid(alpha=0.3)\n", + "plt.show()\n", + "\n", + "print(f\"\\n📊 Корреляция между возрастом и стоимостью билета: {df['age'].corr(df['fare']):.3f}\")" + ], + "id": "a2e54f37810622bd" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Boxplot: класс билета vs возраст\n", + "plt.figure(figsize=(10, 6))\n", + "\n", + "# Изменен порядок классов и добавлены цвета\n", + "order = [1, 2, 3]\n", + "sns.boxplot(x='class', y='age', data=df, order=order, palette='Set2')\n", + "\n", + "plt.xlabel('Класс билета (1 - лучший, 3 - худший)', fontsize=12)\n", + "plt.ylabel('Возраст пассажира', fontsize=12)\n", + "plt.title('Распределение возрастов по классам билетов', fontsize=14)\n", + "\n", + "# Добавление средних значений\n", + "for i, class_val in enumerate([1, 2, 3]):\n", + " mean_age = df[df['pclass'] == class_val]['age'].mean()\n", + " plt.text(i, mean_age + 1, f'Ср.: {mean_age:.1f}', ha='center', fontsize=10)\n", + "\n", + "plt.grid(axis='y', alpha=0.3)\n", + "plt.show()\n", + "\n", + "print(\"\\n📊 Статистика по классам:\")\n", + "print(df.groupby('pclass')['age'].agg(['mean', 'median', 'std']).round(1))" + ], + "id": "85009f4a16158b88" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "from tqdm import tqdm\n", + "import time\n", + "\n", + "# Симуляция обработки данных с прогресс-баром\n", + "print(\"🔄 Анализ данных пассажиров с прогресс-баром...\")\n", + "\n", + "# Группировка пассажиров и анализ\n", + "results = []\n", + "for ticket_class in tqdm(df['pclass'].unique(), desc=\"Анализ классов\", unit=\"класс\", colour='green'):\n", + " class_data = df[df['pclass'] == ticket_class]\n", + " time.sleep(0.1) # Симуляция вычислений\n", + "\n", + " results.append({\n", + " 'класс': ticket_class,\n", + " 'кол-во_пассажиров': len(class_data),\n", + " 'выживаемость_%': (class_data['survived'].sum() / len(class_data)) * 100,\n", + " 'средний_возраст': class_data['age'].mean(),\n", + " 'средняя_цена_билета': class_data['fare'].mean()\n", + " })\n", + "\n", + "result_df = pd.DataFrame(results)\n", + "print(\"\\n✅ Анализ завершен!\")\n", + "result_df" + ], + "id": "ea8315adea678f3d" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Тепловая карта корреляций\n", + "plt.figure(figsize=(10, 8))\n", + "\n", + "# Выбираем числовые колонки\n", + "numeric_cols = ['survived', 'pclass', 'age', 'sibsp', 'parch', 'fare']\n", + "corr_matrix = df[numeric_cols].corr()\n", + "\n", + "sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0,\n", + " square=True, linewidths=2, fmt='.3f',\n", + " cbar_kws={'label': 'Коэффициент корреляции'})\n", + "plt.title('Матрица корреляции параметров выживаемости', fontsize=14)\n", + "plt.show()\n", + "\n", + "print(\"\\n📈 Ключевые корреляции с выживаемостью:\")\n", + "print(f\" Класс билета: {corr_matrix.loc['survived', 'pclass']:.3f} (отрицательная = лучше класс = выше шанс)\")\n", + "print(f\" Цена билета: {corr_matrix.loc['survived', 'fare']:.3f} (положительная = дороже билет = выше шанс)\")\n", + "print(f\" Возраст: {corr_matrix.loc['survived', 'age']:.3f} (слабая корреляция)\")" + ], + "id": "12ede302d3d767ef" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# ============================================\n", + "# ПОЛНЫЙ КОД СО ВСЕМИ ГРАФИКАМИ\n", + "# ============================================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "# Загрузка данных\n", + "df = sns.load_dataset('titanic')\n", + "\n", + "# Очистка данных\n", + "df['age'].fillna(df['age'].median(), inplace=True)\n", + "df['fare'].fillna(df['fare'].median(), inplace=True)\n", + "\n", + "# Настройка стиля\n", + "plt.rcParams['figure.figsize'] = (12, 6)\n", + "sns.set_style(\"whitegrid\")\n", + "\n", + "print(\"=\" * 60)\n", + "print(\"📊 ПОСТРОЕНИЕ ГРАФИКОВ ДЛЯ АНАЛИЗА ДАННЫХ\")\n", + "print(\"=\" * 60)\n", + "\n", + "# ============================================\n", + "# ГРАФИК 1: ГИСТОГРАММА (Histogram)\n", + "# ============================================\n", + "print(\"\\n1️⃣ ГИСТОГРАММА - Распределение возрастов пассажиров\")\n", + "\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "# Разделяем выживших и погибших\n", + "survived = df[df['survived'] == 1]['age']\n", + "died = df[df['survived'] == 0]['age']\n", + "\n", + "plt.hist(survived, bins=20, alpha=0.7, label='Выжившие',\n", + " color='green', edgecolor='black', linewidth=1.5)\n", + "plt.hist(died, bins=20, alpha=0.7, label='Погибшие',\n", + " color='red', edgecolor='black', linewidth=1.5)\n", + "\n", + "plt.xlabel('Возраст (лет)', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Количество пассажиров', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 1: Распределение возрастов (Выжившие vs Погибшие)',\n", + " fontsize=14, fontweight='bold')\n", + "plt.axvline(survived.mean(), color='darkgreen', linestyle='--', linewidth=2,\n", + " label=f'Средний возраст выживших: {survived.mean():.1f}')\n", + "plt.axvline(died.mean(), color='darkred', linestyle='--', linewidth=2,\n", + " label=f'Средний возраст погибших: {died.mean():.1f}')\n", + "plt.legend(loc='upper right', fontsize=10)\n", + "plt.grid(alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"✅ ГРАФИК 1 построен! Средний возраст выживших: {survived.mean():.1f}, погибших: {died.mean():.1f}\")\n", + "\n", + "# ============================================\n", + "# ГРАФИК 2: ТОЧЕЧНЫЙ ГРАФИК (Scatterplot)\n", + "# ============================================\n", + "print(\"\\n2️⃣ ТОЧЕЧНЫЙ ГРАФИК - Возраст vs Стоимость билета\")\n", + "\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "# Цветовая схема: зеленые - выжившие, красные - погибшие\n", + "colors = df['survived'].map({0: 'red', 1: 'green'})\n", + "sizes = df['age'].fillna(30) * 2 # Размер точек зависит от возраста\n", + "\n", + "scatter = plt.scatter(df['age'], df['fare'], c=colors, alpha=0.6, s=sizes, edgecolors='black', linewidth=0.5)\n", + "\n", + "plt.xlabel('Возраст (лет)', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Стоимость билета ($)', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 2: Зависимость стоимости билета от возраста пассажира',\n", + " fontsize=14, fontweight='bold')\n", + "\n", + "# Добавляем линию тренда\n", + "z = np.polyfit(df['age'].dropna(), df['fare'].dropna(), 1)\n", + "p = np.poly1d(z)\n", + "x_trend = np.linspace(df['age'].min(), df['age'].max(), 100)\n", + "plt.plot(x_trend, p(x_trend), 'b--', linewidth=2, label='Линия тренда')\n", + "\n", + "# Легенда\n", + "from matplotlib.patches import Patch\n", + "legend_elements = [\n", + " Patch(facecolor='green', alpha=0.6, label='Выжившие'),\n", + " Patch(facecolor='red', alpha=0.6, label='Погибшие'),\n", + " Patch(facecolor='blue', alpha=0.6, label='Линия тренда')\n", + "]\n", + "plt.legend(handles=legend_elements, loc='upper right', fontsize=10)\n", + "plt.grid(alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "correlation = df['age'].corr(df['fare'])\n", + "print(f\"✅ ГРАФИК 2 построен! Корреляция между возрастом и ценой билета: {correlation:.3f}\")\n", + "\n", + "# ============================================\n", + "# ГРАФИК 3: BOXPLOT (Ящик с усами)\n", + "# ============================================\n", + "print(\"\\n3️⃣ ЯЩИК С УСАМИ - Распределение цен на билеты по классам\")\n", + "\n", + "plt.figure(figsize=(10, 6))\n", + "\n", + "# Создаем boxplot с кастомными цветами\n", + "boxplot = sns.boxplot(x='pclass', y='fare', data=df,\n", + " palette='Set2', linewidth=2,\n", + " fliersize=5, flierprops=dict(marker='o', markerfacecolor='red', markersize=6))\n", + "\n", + "plt.xlabel('Класс билета (1 - первый/роскошный, 3 - третий/эконом)', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Стоимость билета ($)', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 3: Распределение стоимости билетов по классам обслуживания',\n", + " fontsize=14, fontweight='bold')\n", + "\n", + "# Добавляем аннотации со средними значениями\n", + "for i, pclass in enumerate([1, 2, 3], 1):\n", + " mean_fare = df[df['pclass'] == pclass]['fare'].mean()\n", + " plt.text(i - 0.8, mean_fare + 10, f'Средняя: ${mean_fare:.0f}',\n", + " fontsize=10, ha='center', bbox=dict(boxstyle=\"round,pad=0.3\", facecolor=\"yellow\", alpha=0.7))\n", + "\n", + "plt.xticks([0, 1, 2], ['1 класс (люкс)', '2 класс (стандарт)', '3 класс (эконом)'], rotation=15)\n", + "plt.grid(axis='y', alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"✅ ГРАФИК 3 построен!\")\n", + "print(f\" Средние цены: 1 класс: ${df[df['pclass']==1]['fare'].mean():.0f}, \"\n", + " f\"2 класс: ${df[df['pclass']==2]['fare'].mean():.0f}, \"\n", + " f\"3 класс: ${df[df['pclass']==3]['fare'].mean():.0f}\")\n", + "\n", + "# ============================================\n", + "# ДОПОЛНИТЕЛЬНЫЙ ГРАФИК 4: Тепловая карта (Heatmap)\n", + "# ============================================\n", + "print(\"\\n4️⃣ ТЕПЛОВАЯ КАРТА - Корреляция параметров\")\n", + "\n", + "plt.figure(figsize=(10, 8))\n", + "\n", + "# Выбираем числовые параметры\n", + "numeric_cols = ['survived', 'pclass', 'age', 'sibsp', 'parch', 'fare']\n", + "corr_matrix = df[numeric_cols].corr()\n", + "\n", + "# Создаем тепловую карту\n", + "sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0,\n", + " square=True, linewidths=2, fmt='.3f',\n", + " cbar_kws={'label': 'Коэффициент корреляции', 'shrink': 0.8},\n", + " annot_kws={'size': 12, 'weight': 'bold'})\n", + "\n", + "plt.title('ГРАФИК 4: Матрица корреляции параметров выживаемости',\n", + " fontsize=14, fontweight='bold')\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(\"✅ ГРАФИК 4 построен!\")\n", + "print(\" Ключевые корреляции с выживаемостью (survived):\")\n", + "print(f\" • Класс билета (pclass): {corr_matrix.loc['survived', 'pclass']:.3f} (отрицательная)\")\n", + "print(f\" • Цена билета (fare): {corr_matrix.loc['survived', 'fare']:.3f} (положительная)\")\n", + "\n", + "# ============================================\n", + "# ДОПОЛНИТЕЛЬНЫЙ ГРАФИК 5: Столбчатая диаграмма\n", + "# ============================================\n", + "print(\"\\n5️⃣ СТОЛБЧАТАЯ ДИАГРАММА - Выживаемость по классам\")\n", + "\n", + "plt.figure(figsize=(10, 6))\n", + "\n", + "# Считаем выживаемость по классам\n", + "survival_by_class = df.groupby('pclass')['survived'].mean() * 100\n", + "\n", + "bars = plt.bar([1, 2, 3], survival_by_class.values,\n", + " color=['gold', 'silver', '#CD7F32'],\n", + " edgecolor='black', linewidth=2, alpha=0.8)\n", + "\n", + "# Добавляем значения на столбцы\n", + "for bar, value in zip(bars, survival_by_class.values):\n", + " plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2,\n", + " f'{value:.1f}%', ha='center', va='bottom', fontsize=12, fontweight='bold')\n", + "\n", + "plt.xlabel('Класс билета', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Выживаемость (%)', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 5: Процент выживших пассажиров по классам',\n", + " fontsize=14, fontweight='bold')\n", + "plt.xticks([1, 2, 3], ['1 класс\\n(люкс)', '2 класс\\n(стандарт)', '3 класс\\n(эконом)'])\n", + "plt.ylim(0, 100)\n", + "plt.grid(axis='y', alpha=0.3)\n", + "\n", + "# Добавляем среднюю линию\n", + "plt.axhline(df['survived'].mean() * 100, color='red', linestyle='--', linewidth=2,\n", + " label=f'Общая выживаемость: {df[\"survived\"].mean()*100:.1f}%')\n", + "plt.legend()\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(\"✅ ГРАФИК 5 построен!\")\n", + "print(f\" Выживаемость: 1 класс: {survival_by_class[1]:.1f}%, \"\n", + " f\"2 класс: {survival_by_class[2]:.1f}%, \"\n", + " f\"3 класс: {survival_by_class[3]:.1f}%\")\n", + "\n", + "# ============================================\n", + "# ИТОГИ\n", + "# ============================================\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"📊 ИТОГИ ПОСТРОЕНИЯ ГРАФИКОВ\")\n", + "print(\"=\" * 60)\n", + "print(\"✅ Построено 5 графиков:\")\n", + "print(\" 1. Гистограмма (Histogram) - распределение возрастов\")\n", + "print(\" 2. Точечный график (Scatterplot) - возраст vs цена билета\")\n", + "print(\" 3. Ящик с усами (Boxplot) - распределение цен по классам\")\n", + "print(\" 4. Тепловая карта (Heatmap) - корреляция параметров\")\n", + "print(\" 5. Столбчатая диаграмма (Bar chart) - выживаемость по классам\")\n", + "print(\"=\" * 60)" + ], + "id": "870930145d19645" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 📝 ВЫВОДЫ ПО РЕЗУЛЬТАТАМ АНАЛИЗА\n", + "\n", + "### Ключевые результаты:\n", + "1. **Объем данных**: Проанализировано {len(df)} пассажиров\n", + "2. **Общая выживаемость**: {df['survived'].mean()*100:.1f}%\n", + "\n", + "### Факторы, влияющие на выживаемость:\n", + "- **Класс билета**: Пассажиры 1-го класса выживали значительно чаще\n", + "- **Пол**: Женщины выживали чаще мужчин\n", + "- **Возраст**: Дети выживали чаще взрослых\n", + "- **Цена билета**: Более дорогие билеты коррелируют с более высокими шансами\n", + "\n", + "### Рекомендации для системы управления:\n", + "1. Учитывать категории пользователей при приоритизации\n", + "2. Внедрить систему лояльности для постоянных клиентов\n", + "3. Анализировать поведение разных сегментов аудитории\n", + "\n" + ], + "id": "bb76a6b35ff61162" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "", + "id": "ad6c90dab130cf29" + }, + { + "metadata": {}, + "cell_type": "code", + "source": "", + "id": "4c1457863ccaa86", + "outputs": [], + "execution_count": null + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/week2_analysis.ipynb b/week2_analysis.ipynb new file mode 100644 index 0000000..2234338 --- /dev/null +++ b/week2_analysis.ipynb @@ -0,0 +1,541 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "849d0fe9d43b3ad2", + "metadata": {}, + "source": [ + "# Анализ данных пассажиров Титаника\n", + "\n", + "**Источник данных:** Kaggle - Titanic: Machine Learning from Disaster\n", + "**Цель анализа:** Изучить факторы, влияющие на выживаемость пассажиров\n", + "\n", + "**Дата анализа:** 07.05.2026" + ] + }, + { + "cell_type": "markdown", + "id": "7b68a95f07cd5093", + "metadata": {}, + "source": [ + "# Импорт библиотек (изменен стиль импорта)\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "from tqdm import tqdm\n", + "import warnings\n", + "warnings.filterwarnings('ignore')\n", + "\n", + "# Настройка отображения\n", + "%matplotlib inline\n", + "plt.rcParams['figure.figsize'] = (12, 6)\n", + "plt.style.use('seaborn-v0_8-darkgrid')\n", + "sns.set_palette(\"husl\")\n", + "\n", + "print(\"✅ Библиотеки загружены\")\n", + "\n", + "# Загрузка встроенного датасета Titanic\n", + "df = sns.load_dataset('titanic')\n", + "print(f\"✅ Загружено {len(df)} записей о пассажирах\")\n", + "df.head(10) # Вывод в последней строке ячейки" + ] + }, + { + "cell_type": "markdown", + "id": "82fb50b6dfcb725a", + "metadata": {}, + "source": [ + "print(\"📊 ПЕРВИЧНЫЙ АНАЛИЗ ДАННЫХ\")\n", + "print(\"=\" * 50)\n", + "\n", + "print(\"\\n1. Информация о данных (df.info()):\")\n", + "print(df.info())\n", + "\n", + "print(\"\\n2. Статистическое описание (df.describe()):\")\n", + "print(df.describe())\n", + "\n", + "# Дополнительный анализ\n", + "print(\"\\n3. Анализ выживаемости по полу (изменено от примера):\")\n", + "print(pd.crosstab(df['sex'], df['alive'], normalize='index') * 100)" + ] + }, + { + "cell_type": "markdown", + "id": "8624dc43d9bf124d", + "metadata": {}, + "source": [ + "# Анализ пропущенных значений\n", + "missing_data = df.isnull().sum()\n", + "missing_percent = (missing_data / len(df)) * 100\n", + "\n", + "missing_df = pd.DataFrame({\n", + " 'Кол-во пропусков': missing_data,\n", + " 'Процент': missing_percent\n", + "}).sort_values('Кол-во пропусков', ascending=False)\n", + "\n", + "print(\"📊 АНАЛИЗ ПРОПУЩЕННЫХ ДАННЫХ\")\n", + "print(\"=\" * 40)\n", + "print(missing_df[missing_df['Кол-во пропусков'] > 0])\n", + "\n", + "# Заполнение пропусков\n", + "df['age'].fillna(df['age'].median(), inplace=True)\n", + "df['embarked'].fillna(df['embarked'].mode()[0], inplace=True)\n", + "df.drop('deck', axis=1, inplace=True)\n", + "\n", + "print(f\"\\n✅ Пропуски заполнены. Размер данных: {df.shape}\")" + ] + }, + { + "cell_type": "markdown", + "id": "ecea1247c0fbb76f", + "metadata": {}, + "source": [ + "# Гистограмма распределения возрастов\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "# Разделение по выжившим/погибшим\n", + "survived = df[df['survived'] == 1]['age']\n", + "died = df[df['survived'] == 0]['age']\n", + "\n", + "plt.hist(survived, bins=20, alpha=0.7, label='Выжившие', color='green', edgecolor='black')\n", + "plt.hist(died, bins=20, alpha=0.7, label='Погибшие', color='red', edgecolor='black')\n", + "\n", + "plt.xlabel('Возраст', fontsize=12)\n", + "plt.ylabel('Количество пассажиров', fontsize=12)\n", + "plt.title('Распределение возрастов пассажиров: Выжившие vs Погибшие', fontsize=14)\n", + "plt.axvline(survived.mean(), color='darkgreen', linestyle='--',\n", + " label=f'Ср. возраст выживших: {survived.mean():.1f}', alpha=0.8)\n", + "plt.axvline(died.mean(), color='darkred', linestyle='--',\n", + " label=f'Ср. возраст погибших: {died.mean():.1f}', alpha=0.8)\n", + "plt.legend()\n", + "plt.grid(alpha=0.3)\n", + "plt.show()\n", + "\n", + "print(f\"\\n📊 Вывод: Средний возраст выживших ({survived.mean():.1f}) выше, чем погибших ({died.mean():.1f})\")" + ] + }, + { + "cell_type": "markdown", + "id": "a2e54f37810622bd", + "metadata": {}, + "source": [ + "# Scatterplot: возраст vs стоимость билета\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "# Разные цвета для выживших и погибших\n", + "colors = df['survived'].map({0: 'red', 1: 'green'})\n", + "plt.scatter(df['age'], df['fare'], c=colors, alpha=0.6, s=50)\n", + "\n", + "plt.xlabel('Возраст (лет)', fontsize=12)\n", + "plt.ylabel('Стоимость билета ($)', fontsize=12)\n", + "plt.title('Зависимость стоимости билета от возраста пассажира', fontsize=14)\n", + "\n", + "# Добавление регрессионной линии для общего тренда\n", + "z = np.polyfit(df['age'].dropna(), df['fare'].dropna(), 1)\n", + "p = np.poly1d(z)\n", + "plt.plot(df['age'].dropna().sort_values(), p(df['age'].dropna().sort_values()),\n", + " 'b--', alpha=0.8, label='Тренд')\n", + "\n", + "# Легенда\n", + "from matplotlib.patches import Patch\n", + "legend_elements = [Patch(facecolor='green', alpha=0.6, label='Выжившие'),\n", + " Patch(facecolor='red', alpha=0.6, label='Погибшие')]\n", + "plt.legend(handles=legend_elements)\n", + "plt.grid(alpha=0.3)\n", + "plt.show()\n", + "\n", + "print(f\"\\n📊 Корреляция между возрастом и стоимостью билета: {df['age'].corr(df['fare']):.3f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "85009f4a16158b88", + "metadata": {}, + "source": [ + "# Boxplot: класс билета vs возраст\n", + "plt.figure(figsize=(10, 6))\n", + "\n", + "# Изменен порядок классов и добавлены цвета\n", + "order = [1, 2, 3]\n", + "sns.boxplot(x='class', y='age', data=df, order=order, palette='Set2')\n", + "\n", + "plt.xlabel('Класс билета (1 - лучший, 3 - худший)', fontsize=12)\n", + "plt.ylabel('Возраст пассажира', fontsize=12)\n", + "plt.title('Распределение возрастов по классам билетов', fontsize=14)\n", + "\n", + "# Добавление средних значений\n", + "for i, class_val in enumerate([1, 2, 3]):\n", + " mean_age = df[df['pclass'] == class_val]['age'].mean()\n", + " plt.text(i, mean_age + 1, f'Ср.: {mean_age:.1f}', ha='center', fontsize=10)\n", + "\n", + "plt.grid(axis='y', alpha=0.3)\n", + "plt.show()\n", + "\n", + "print(\"\\n📊 Статистика по классам:\")\n", + "print(df.groupby('pclass')['age'].agg(['mean', 'median', 'std']).round(1))" + ] + }, + { + "cell_type": "markdown", + "id": "ea8315adea678f3d", + "metadata": {}, + "source": [ + "from tqdm import tqdm\n", + "import time\n", + "\n", + "# Симуляция обработки данных с прогресс-баром\n", + "print(\"🔄 Анализ данных пассажиров с прогресс-баром...\")\n", + "\n", + "# Группировка пассажиров и анализ\n", + "results = []\n", + "for ticket_class in tqdm(df['pclass'].unique(), desc=\"Анализ классов\", unit=\"класс\", colour='green'):\n", + " class_data = df[df['pclass'] == ticket_class]\n", + " time.sleep(0.1) # Симуляция вычислений\n", + "\n", + " results.append({\n", + " 'класс': ticket_class,\n", + " 'кол-во_пассажиров': len(class_data),\n", + " 'выживаемость_%': (class_data['survived'].sum() / len(class_data)) * 100,\n", + " 'средний_возраст': class_data['age'].mean(),\n", + " 'средняя_цена_билета': class_data['fare'].mean()\n", + " })\n", + "\n", + "result_df = pd.DataFrame(results)\n", + "print(\"\\n✅ Анализ завершен!\")\n", + "result_df" + ] + }, + { + "cell_type": "markdown", + "id": "12ede302d3d767ef", + "metadata": {}, + "source": [ + "# Тепловая карта корреляций\n", + "plt.figure(figsize=(10, 8))\n", + "\n", + "# Выбираем числовые колонки\n", + "numeric_cols = ['survived', 'pclass', 'age', 'sibsp', 'parch', 'fare']\n", + "corr_matrix = df[numeric_cols].corr()\n", + "\n", + "sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0,\n", + " square=True, linewidths=2, fmt='.3f',\n", + " cbar_kws={'label': 'Коэффициент корреляции'})\n", + "plt.title('Матрица корреляции параметров выживаемости', fontsize=14)\n", + "plt.show()\n", + "\n", + "print(\"\\n📈 Ключевые корреляции с выживаемостью:\")\n", + "print(f\" Класс билета: {corr_matrix.loc['survived', 'pclass']:.3f} (отрицательная = лучше класс = выше шанс)\")\n", + "print(f\" Цена билета: {corr_matrix.loc['survived', 'fare']:.3f} (положительная = дороже билет = выше шанс)\")\n", + "print(f\" Возраст: {corr_matrix.loc['survived', 'age']:.3f} (слабая корреляция)\")" + ] + }, + { + "cell_type": "markdown", + "id": "870930145d19645", + "metadata": {}, + "source": [ + "# =========================\n", + "# КОД СО ВСЕМИ ГРАФИКАМИ\n", + "# =========================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "# Загрузка данных\n", + "df = sns.load_dataset('titanic')\n", + "\n", + "df['age'] = df['age'].fillna(df['age'].median())\n", + "df['fare'] = df['fare'].fillna(df['fare'].median())\n", + "df['embarked'] = df['embarked'].fillna(df['embarked'].mode()[0])\n", + "\n", + "df = df.drop('deck', axis=1)\n", + "\n", + "print(\"=\" * 60)\n", + "print(\"📊 ПОСТРОЕНИЕ ГРАФИКОВ ДЛЯ АНАЛИЗА ДАННЫХ ТИТАНИКА\")\n", + "print(\"=\" * 60)\n", + "print(f\"✅ Загружено {len(df)} пассажиров\")\n", + "print(f\"✅ Пропуски заполнены\")\n", + "print(f\"✅ Данные готовы к анализу\")\n", + "\n", + "# =================================\n", + "# ГРАФИК 1: ГИСТОГРАММА (Histogram)\n", + "# =================================\n", + "print(\"\\n1️⃣ ГИСТОГРАММА - Распределение возрастов пассажиров\")\n", + "\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "# Разделяем выживших и погибших\n", + "survived = df[df['survived'] == 1]['age'].dropna()\n", + "died = df[df['survived'] == 0]['age'].dropna()\n", + "\n", + "plt.hist(survived, bins=20, alpha=0.7, label='Выжившие', \n", + " color='green', edgecolor='black', linewidth=1.5)\n", + "plt.hist(died, bins=20, alpha=0.7, label='Погибшие', \n", + " color='red', edgecolor='black', linewidth=1.5)\n", + "\n", + "plt.xlabel('Возраст (лет)', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Количество пассажиров', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 1: Распределение возрастов (Выжившие vs Погибшие)', \n", + " fontsize=14, fontweight='bold')\n", + "plt.axvline(survived.mean(), color='darkgreen', linestyle='--', linewidth=2,\n", + " label=f'Ср. возраст выживших: {survived.mean():.1f}')\n", + "plt.axvline(died.mean(), color='darkred', linestyle='--', linewidth=2,\n", + " label=f'Ср. возраст погибших: {died.mean():.1f}')\n", + "plt.legend(loc='upper right', fontsize=10)\n", + "plt.grid(alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"✅ ГРАФИК 1 построен!\")\n", + "\n", + "# =======================================\n", + "# ГРАФИК 2: ТОЧЕЧНЫЙ ГРАФИК (Scatterplot)\n", + "# =======================================\n", + "print(\"\\n2️⃣ ТОЧЕЧНЫЙ ГРАФИК - Возраст vs Стоимость билета\")\n", + "\n", + "plt.figure(figsize=(12, 6))\n", + "\n", + "clean_age = df['age'].dropna()\n", + "clean_fare = df['fare'].dropna()\n", + "\n", + "# Цветовая схема: зеленые - выжившие, красные - погибшие\n", + "colors = df.loc[clean_age.index, 'survived'].map({0: 'red', 1: 'green'})\n", + "\n", + "plt.scatter(clean_age, clean_fare, c=colors, alpha=0.6, s=50, edgecolors='black', linewidth=0.5)\n", + "\n", + "plt.xlabel('Возраст (лет)', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Стоимость билета ($)', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 2: Зависимость стоимости билета от возраста пассажира', \n", + " fontsize=14, fontweight='bold')\n", + "\n", + "z = np.polyfit(clean_age, clean_fare, 1)\n", + "p = np.poly1d(z)\n", + "x_trend = np.linspace(clean_age.min(), clean_age.max(), 100)\n", + "plt.plot(x_trend, p(x_trend), 'b--', linewidth=2, label='Линия тренда')\n", + "\n", + "# Легенда\n", + "from matplotlib.patches import Patch\n", + "legend_elements = [\n", + " Patch(facecolor='green', alpha=0.6, label='Выжившие'),\n", + " Patch(facecolor='red', alpha=0.6, label='Погибшие'),\n", + " Patch(facecolor='blue', alpha=0.6, label='Линия тренда')\n", + "]\n", + "plt.legend(handles=legend_elements, loc='upper right', fontsize=10)\n", + "plt.grid(alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "correlation = clean_age.corr(clean_fare)\n", + "print(f\"✅ ГРАФИК 2 построен!\")\n", + "print(f\" Корреляция между возрастом и ценой билета: {correlation:.3f}\")\n", + "\n", + "# ============================================\n", + "# ГРАФИК 3: BOXPLOT (Ящик с усами)\n", + "# ============================================\n", + "print(\"\\n3️⃣ ЯЩИК С УСАМИ - Распределение цен на билеты по классам\")\n", + "\n", + "plt.figure(figsize=(10, 6))\n", + "\n", + "# Создаем boxplot с кастомными цветами\n", + "boxplot = sns.boxplot(x='pclass', y='fare', data=df, \n", + " palette='Set2', linewidth=2, \n", + " fliersize=5, flierprops=dict(marker='o', markerfacecolor='red', markersize=6))\n", + "\n", + "plt.xlabel('Класс билета (1 - первый/роскошный, 3 - третий/эконом)', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Стоимость билета ($)', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 3: Распределение стоимости билетов по классам обслуживания', \n", + " fontsize=14, fontweight='bold')\n", + "\n", + "# Добавляем аннотации со средними значениями\n", + "for i, pclass in enumerate([1, 2, 3], 1):\n", + " mean_fare = df[df['pclass'] == pclass]['fare'].mean()\n", + " plt.text(i - 0.8, mean_fare + 10, f'Средняя: ${mean_fare:.0f}', \n", + " fontsize=10, ha='center', bbox=dict(boxstyle=\"round,pad=0.3\", facecolor=\"yellow\", alpha=0.7))\n", + "\n", + "plt.xticks([0, 1, 2], ['1 класс (люкс)', '2 класс (стандарт)', '3 класс (эконом)'], rotation=15)\n", + "plt.grid(axis='y', alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"✅ ГРАФИК 3 построен!\")\n", + "\n", + "# ============================================\n", + "# ГРАФИК 4: ДОПОЛНИТЕЛЬНЫЙ - Тепловая карта (Heatmap)\n", + "# ============================================\n", + "print(\"\\n4️⃣ ТЕПЛОВАЯ КАРТА - Корреляция параметров\")\n", + "\n", + "plt.figure(figsize=(10, 8))\n", + "\n", + "# Выбираем числовые параметры\n", + "numeric_cols = ['survived', 'pclass', 'age', 'sibsp', 'parch', 'fare']\n", + "corr_matrix = df[numeric_cols].corr()\n", + "\n", + "# Создаем тепловую карту\n", + "sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0, \n", + " square=True, linewidths=2, fmt='.3f',\n", + " cbar_kws={'label': 'Коэффициент корреляции', 'shrink': 0.8},\n", + " annot_kws={'size': 12, 'weight': 'bold'})\n", + "\n", + "plt.title('ГРАФИК 4: Матрица корреляции параметров выживаемости', \n", + " fontsize=14, fontweight='bold')\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(\"✅ ГРАФИК 4 построен!\")\n", + "\n", + "# ============================================\n", + "# ГРАФИК 5: ДОПОЛНИТЕЛЬНЫЙ - Столбчатая диаграмма\n", + "# ============================================\n", + "print(\"\\n5️⃣ СТОЛБЧАТАЯ ДИАГРАММА - Выживаемость по классам\")\n", + "\n", + "plt.figure(figsize=(10, 6))\n", + "\n", + "# Считаем выживаемость по классам\n", + "survival_by_class = df.groupby('pclass')['survived'].mean() * 100\n", + "\n", + "bars = plt.bar([1, 2, 3], survival_by_class.values, \n", + " color=['gold', 'silver', '#CD7F32'], \n", + " edgecolor='black', linewidth=2, alpha=0.8)\n", + "\n", + "# Добавляем значения на столбцы\n", + "for bar, value in zip(bars, survival_by_class.values):\n", + " plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2, \n", + " f'{value:.1f}%', ha='center', va='bottom', fontsize=12, fontweight='bold')\n", + "\n", + "plt.xlabel('Класс билета', fontsize=12, fontweight='bold')\n", + "plt.ylabel('Выживаемость (%)', fontsize=12, fontweight='bold')\n", + "plt.title('ГРАФИК 5: Процент выживших пассажиров по классам', \n", + " fontsize=14, fontweight='bold')\n", + "plt.xticks([1, 2, 3], ['1 класс\\n(люкс)', '2 класс\\n(стандарт)', '3 класс\\n(эконом)'])\n", + "plt.ylim(0, 100)\n", + "plt.grid(axis='y', alpha=0.3)\n", + "\n", + "# Добавляем среднюю линию\n", + "plt.axhline(df['survived'].mean() * 100, color='red', linestyle='--', linewidth=2,\n", + " label=f'Общая выживаемость: {df[\"survived\"].mean()*100:.1f}%')\n", + "plt.legend()\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(\"✅ ГРАФИК 5 построен!\")\n", + "\n", + "# ============================================\n", + "# tqdm демонстрация\n", + "# ============================================\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"🔄 АНАЛИЗ С ПРОГРЕСС-БАРОМ (tqdm)\")\n", + "print(\"=\" * 60)\n", + "\n", + "from tqdm import tqdm\n", + "import time\n", + "\n", + "results = []\n", + "for pclass in tqdm([1, 2, 3], desc=\"Анализ классов\", unit=\"класс\", colour='green'):\n", + " class_data = df[df['pclass'] == pclass]\n", + " time.sleep(0.1) # Симуляция\n", + " \n", + " results.append({\n", + " 'Класс': pclass,\n", + " 'Пассажиров': len(class_data),\n", + " 'Выживаемость %': round((class_data['survived'].sum() / len(class_data)) * 100, 1),\n", + " 'Средняя цена': round(class_data['fare'].mean(), 2)\n", + " })\n", + "\n", + "print(\"\\n✅ Результаты анализа:\")\n", + "result_df = pd.DataFrame(results)\n", + "print(result_df.to_string(index=False))\n", + "\n", + "# ============================================\n", + "# ИТОГИ\n", + "# ============================================\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"📊 ВЫВОДЫ ПО РЕЗУЛЬТАТАМ АНАЛИЗА\")\n", + "print(\"=\" * 60)\n", + "\n", + "print(f\"\"\"\n", + "✅ Основные результаты:\n", + "1. Всего проанализировано: {len(df)} пассажиров\n", + "2. Общая выживаемость: {df['survived'].mean() * 100:.1f}%\n", + "\n", + "✅ Факторы, влияющие на выживаемость:\n", + "3. Класс билета:\n", + " - 1 класс: {(df[df['pclass']==1]['survived'].mean()*100):.1f}%\n", + " - 2 класс: {(df[df['pclass']==2]['survived'].mean()*100):.1f}%\n", + " - 3 класс: {(df[df['pclass']==3]['survived'].mean()*100):.1f}%\n", + "\n", + "4. Возраст: средний возраст выживших ({survived.mean():.1f}) vs погибших ({died.mean():.1f})\n", + "\n", + "5. Цена билета: корреляция с выживаемостью {corr_matrix.loc['survived', 'fare']:.3f}\n", + "\"\"\")\n", + "\n", + "print(\"=\" * 60)\n", + "print(\"✅ АНАЛИЗ УСПЕШНО ЗАВЕРШЕН!\")\n", + "print(\" Построено 5 графиков: Гистограмма, Scatterplot, Boxplot, Heatmap, Bar chart\")\n", + "print(\"=\" * 60)" + ] + }, + { + "cell_type": "markdown", + "id": "bb76a6b35ff61162", + "metadata": {}, + "source": [ + "## 📝 ВЫВОДЫ ПО РЕЗУЛЬТАТАМ АНАЛИЗА\n", + "\n", + "### Ключевые результаты:\n", + "1. **Объем данных**: Проанализировано {len(df)} пассажиров\n", + "2. **Общая выживаемость**: {df['survived'].mean()*100:.1f}%\n", + "\n", + "### Факторы, влияющие на выживаемость:\n", + "- **Класс билета**: Пассажиры 1-го класса выживали значительно чаще\n", + "- **Пол**: Женщины выживали чаще мужчин\n", + "- **Возраст**: Дети выживали чаще взрослых\n", + "- **Цена билета**: Более дорогие билеты коррелируют с более высокими шансами\n", + "\n", + "### Рекомендации для системы управления:\n", + "1. Учитывать категории пользователей при приоритизации\n", + "2. Внедрить систему лояльности для постоянных клиентов\n", + "3. Анализировать поведение разных сегментов аудитории\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "ad6c90dab130cf29", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c1457863ccaa86", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}