1364 lines
258 KiB
Plaintext
1364 lines
258 KiB
Plaintext
|
{
|
|||
|
"cells": [
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"## Датасет №1 (рейтинги плиток шоколада) \n",
|
|||
|
"\n",
|
|||
|
"Ссылка: https://www.kaggle.com/datasets/rtatman/chocolate-bar-ratings\n",
|
|||
|
"\n",
|
|||
|
"Проблемная область: качество шоколада и факторы, влияющие на его оценку потребителями.\n",
|
|||
|
"\n",
|
|||
|
"Объекты наблюдения: плитки шоколада, каждая из которых имеет свои уникальные характеристики."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 532,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Index(['Company (Maker-if known)', 'Specific Bean Originor Bar Name', 'REF',\n",
|
|||
|
" 'ReviewDate', 'CocoaPercent', 'CompanyLocation', 'Rating', 'BeanType',\n",
|
|||
|
" 'Broad BeanOrigin'],\n",
|
|||
|
" dtype='object')\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"import pandas as pd\n",
|
|||
|
"import matplotlib.pyplot as plt\n",
|
|||
|
"import seaborn as sns\n",
|
|||
|
"from sklearn.model_selection import train_test_split\n",
|
|||
|
"\n",
|
|||
|
"# вывод всех столбцов\n",
|
|||
|
"df = pd.read_csv(\"..//..//static//csv//flavors_of_cacao.csv\")\n",
|
|||
|
"df.columns = df.columns.str.replace('\\n', '')\n",
|
|||
|
"print(df.columns)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Атрибуты: \n",
|
|||
|
"* Company (Maker-if known) – название компании-производителя плитки;\n",
|
|||
|
"* Specific Bean Originor Bar Name – географический регион происхождения плитки;\n",
|
|||
|
"* REF – значение, связанное с тем, когда рецензия была внесена в базу данных. Чем значение больше, тем позже;\n",
|
|||
|
"* ReviewDate – дата публикации рецензии;\n",
|
|||
|
"* CocoaPercent – процент какао в плитке;\n",
|
|||
|
"* CompanyLocation – страна, где базируется производитель;\n",
|
|||
|
"* Rating – оценка эксперта;\n",
|
|||
|
"* BeanType – разновидность какао-бобов;\n",
|
|||
|
"* Broad BeanOrigin – географический регион происхождения бобов.\n",
|
|||
|
"\n",
|
|||
|
"Примеры бизнес целей и целей технического проекта:\n",
|
|||
|
"1. Оптимизация рецептур и производство высококачественного шоколада.\n",
|
|||
|
" * Бизнес-цель: повышение качества шоколадных плиток на основе анализа рейтингов и факторов, влияющих на вкус и текстуру (процент какао, происхождение бобов, сорт бобов).\n",
|
|||
|
" * Цель технического проекта: разработка системы анализа и предсказания успешности шоколада на основе его рейтинга, используя характеристики какао-бобов, содержания какао и других параметров.\n",
|
|||
|
"2. Разработка маркетинговых стратегий для производителей шоколада.\n",
|
|||
|
" * Бизнес-цель: определение лучших производителей и регионов происхождения какао-бобов для создания продуктов премиум-класса и продвижения их на рынке.\n",
|
|||
|
" * Цель технического проекта: создание системы ранжирования производителей и регионов на основе данных о рейтингах шоколадных плиток и происхождении какао-бобов.\n",
|
|||
|
"3. Стратегии закупок сырья для промышленности.\n",
|
|||
|
" * Бизнес-цель: оптимизация цепочек поставок какао-бобов с высоким качеством для производства шоколада с лучшими характеристиками.\n",
|
|||
|
" * Цель технического проекта: разработка системы анализа происхождения какао-бобов и их связи с качеством шоколада для улучшения стратегий закупок и логистики.\n",
|
|||
|
"\n",
|
|||
|
"Входные данные и целевой признак могут быть следующими:\n",
|
|||
|
"1. Входные данные:\n",
|
|||
|
" * Регион происхождения плитки;\n",
|
|||
|
" * Название кампании-производителя плитки;\n",
|
|||
|
" * Процент какао в плитке;\n",
|
|||
|
" * Страна, где базируется производитель;\n",
|
|||
|
" * Разновидность какао-бобов;\n",
|
|||
|
" * Регион происхождения бобов.\n",
|
|||
|
"2. Целевой признак:\n",
|
|||
|
" * Рейтинг, как оценка качества шоколада.\n",
|
|||
|
"\n",
|
|||
|
"Актуальность: анализ качества шоколада и факторов, влияющих на вкусовые характеристики, не только помогает производителям улучшать свои продукты и удовлетворять требования потребителей, но и способствует развитию новых технологий в пищевой промышленности, улучшению цепочек поставок и изучению свойств какао. Поэтому эта тема имеет важное значение для развития кондитерской индустрии, повышения стандартов качества и поддержки устойчивого производства.\n",
|
|||
|
"\n",
|
|||
|
"### Проверяем на выбросы"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 533,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Количество выбросов в столбце 'CocoaPercent': 186\n",
|
|||
|
"Количество выбросов в столбце 'Rating': 19\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABdIAAAISCAYAAADIuT2dAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABTwElEQVR4nO3deXhU5f03/k8IJEFWEdkUQVRAcV8fpApUqiL4gAsWRQERV6zSqnWtQK2l1ta1fsEVbFWsWHdFjbg9KnWniiKi4i5YZVfW5Pz+8Jf5EhIOmRBIoq/XdeXSOeeemc9Z5sx93py5T06SJEkAAAAAAADlqlPdBQAAAAAAQE0mSAcAAAAAgBSCdAAAAAAASCFIBwAAAACAFIJ0AAAAAABIIUgHAAAAAIAUgnQAAAAAAEghSAcAAAAAgBSCdAAAAAAASCFIB36SPv7448jJyYmJEydWdymlPP7447H77rtHQUFB5OTkxMKFC6u7JAAA+FFyTpCd0aNHR05OTnWXAVBtBOnABpk4cWLk5OSU+mvRokX07NkzpkyZssnrefbZZ0vVUq9evejQoUMMHjw4Pvrooyp5j5deeilGjx5d5R3ab7/9No455pioX79+3HDDDfGPf/wjGjRokPqcDz/8ME499dTo0KFDFBQUROPGjaNbt25x7bXXxrJly6q0vo1l7X2ooKAgOnbsGGeeeWbMmzevusvbYO+++26MHj06Pv744+ouBQBgo3BOUHWyOSdYe73XrVs3ttpqqxg6dGh88cUXlXr/77//PkaPHh3PPvvsBiwFwI9T3eouAPhx+P3vfx/bbrttJEkS8+bNi4kTJ8Zhhx0WDz/8cPTt23eT13PWWWfFPvvsE6tWrYo33ngjbrrppnj00Ufj7bffjjZt2mzQa7/00ksxZsyYGDp0aDRt2rRqCo6IV199NZYsWRKXXXZZ9OrVa73tH3300RgwYEDk5+fH4MGDY+edd46VK1fGCy+8EOedd1688847cdNNN1VZfRtbyT60fPnyeOGFF2LcuHHx2GOPxYwZM2KzzTar7vIq7d13340xY8ZEjx49on379tVdDgDARuOcYMNle04QUbof/e9//zsmTpwYL7zwQsyYMSMKCgqyev/vv/8+xowZExERPXr0KDXvkksuiQsuuCCr1wP4MRGkA1Wid+/esffee2cen3TSSdGyZcuYNGlStXSaDzjggDj66KMjIuLEE0+Mjh07xllnnRW33357XHjhhZu8nor4+uuvIyIq1BGfM2dODBw4MNq1axdPP/10tG7dOjNvxIgR8cEHH8Sjjz66sUrdKNbch4YPHx5bbLFFXHXVVfHggw/Gscceu0Gv/f3339fqMB4AoDZwTrDhsjknKLF2P7p58+ZxxRVXxEMPPRTHHHNMldVWt27dqFtXjAT8dBnaBdgomjZtGvXr1y/T0fruu+/inHPOibZt20Z+fn506tQp/vKXv0SSJBERsWzZsujcuXN07ty51NAk8+fPj9atW8f+++8fRUVFWdfz85//PCJ+CKDTPP3003HAAQdEgwYNomnTptGvX7+YOXNmZv7o0aPjvPPOi4iIbbfdNvMzyvUN2zF58uTYa6+9on79+tG8efM4/vjjS/3cskePHjFkyJCIiNhnn30iJycnhg4dus7X+/Of/xxLly6NW2+9tVSIXmL77bePs88+O/N49erVcdlll8V2220X+fn50b59+7joootixYoVZZ47ZcqU6N69ezRq1CgaN24c++yzT9x1111ZLU9ExFtvvRVDhw7NDDvTqlWrGDZsWHz77bep66pEedvsjjvuyLxvs2bNYuDAgfHZZ5+Vel6PHj1i5513jtdffz0OPPDA2GyzzeKiiy6KiIjly5fH6NGjo2PHjlFQUBCtW7eOI488Mj788MPM84uLi+Oaa66JLl26REFBQbRs2TJOPfXUWLBgQan3ad++ffTt2zdeeOGF2HfffaOgoCA6dOgQf//73zNtJk6cGAMGDIiIiJ49e2b2Fz+VBQB+CpwTlFbV5wTrcsABB0RElOrjrly5Mi699NLYa6+9okmTJtGgQYM44IAD4plnnsm0+fjjj2PLLbeMiIgxY8Zklmv06NGZ5V57jPScnJw488wz44EHHoidd9458vPzo0uXLvH444+XqevZZ5+NvffeOwoKCmK77baLG2+80bjrQK3inxKBKrFo0aL45ptvIkmS+Prrr+P666+PpUuXxvHHH59pkyRJ/N//+3/jmWeeiZNOOil23333eOKJJ+K8886LL774Iq6++uqoX79+3H777dGtW7e4+OKL46qrroqIH66yXrRoUUycODFyc3Ozrq+kE7nFFluss81TTz0VvXv3jg4dOsTo0aNj2bJlcf3110e3bt3ijTfeiPbt28eRRx4Z77//fkyaNCmuvvrqaN68eUREpsNZnokTJ8aJJ54Y++yzT4wdOzbmzZsX1157bbz44ovx5ptvRtOmTePiiy+OTp06xU033ZT5aeZ22223ztd8+OGHo0OHDrH//vtXaPmHDx8et99+exx99NFxzjnnxMsvvxxjx46NmTNnxv3331+q1mHDhkWXLl3iwgsvjKZNm8abb74Zjz/+eBx33HEVXp6IiMLCwvjoo4/ixBNPjFatWmWGmnnnnXfi3//+93o7zGtvs8svvzx+97vfxTHHHBPDhw+P//73v3H99dfHgQceWOp9I34YW7J3794xcODAOP7446Nly5ZRVFQUffv2jalTp8bAgQPj7LPPjiVLlkRhYWHMmDEjs75PPfXUzDKeddZZMWfOnPjb3/4Wb775Zrz44otRr169zPt88MEHcfTRR8dJJ50UQ4YMidtuuy2GDh0ae+21V3Tp0iUOPPDAOOuss+K6666Liy66KHbccceIiMx/AQB+TJwTbNpzgnUpCfQ333zzzLTFixfHLbfcEscee2ycfPLJsWTJkrj11lvjkEMOiVdeeSV233332HLLLWPcuHFx+umnxxFHHBFHHnlkRETsuuuuqe/3wgsvxH333RdnnHFGNGrUKK677ro46qij4tNPP82s6zfffDMOPfTQaN26dYwZMyaKiori97//feo6A6hxEoANMGHChCQiyvzl5+cnEydOLNX2gQceSCIi+cMf/lBq+tFHH53k5OQkH3zwQWbahRdemNSpUyd5/vnnk8mTJycRkVxzzTXrreeZZ55JIiK57bbbkv/+97/Jl19+mTz66KNJ+/btk5ycnOTVV19NkiRJ5syZk0REMmHChMxzd99996RFixbJt99+m5n2n//8J6lTp04yePDgzLQrr7wyiYhkzpw5661n5cqVSYsWLZKdd945WbZsWWb6I488kkREcumll2amlazLkhrXZdGiRUlEJP369Vvv+ydJkkyfPj2JiGT48OGlpp977rlJRCRPP/10kiRJsnDhwqRRo0bJfvvtV6rWJEmS4uLirJfn+++/L1PLpEmTkohInn/++TLL/dRTTyX//e9/k88++yy5++67ky222CKpX79+8vnnnycff/xxkpubm1x++eWlXu/tt99O6tatW2p69+7dk4hIxo8fX6rtbbfdlkREctVVV5Wpq2T5/t//+39JRCR33nlnqfmPP/54ment2rUrsyxff/11kp+fn5xzzjmZaSX77zPPPFPmfQEAfgycE6TbGOcEa7Zdsx997733JltuuWWSn5+ffPbZZ5m2q1evTlasWFHq+QsWLEhatmyZDBs2LDPtv//9bxIRyahRo8q836hRo5K1Y6SISPLy8kptt//85z9JRCTXX399Ztrhhx+ebLbZZskXX3yRmTZ79uykbt26ZV4ToKYytAtQJW644YYoLCyMwsLCuOOOO6Jnz54xfPjwuO+++zJtHnvsscjNzY2zzjqr1HPPOeecSJIkpkyZkpk2evTo6NKlSwwZMiTOOOOM6N69e5nnpRk2bFhsueWW0aZNm+jTp0989913cfvtt5cas3FNX331VUyfPj2GDh0azZo1y0zfdddd4xe/+EU89thjFX7vNb322mvx9ddfxxlnnFHqRj99+vSJzp07V2oc88WLF0dERKNGjSrUvqT23/z
|
|||
|
"text/plain": [
|
|||
|
"<Figure size 1500x1000 with 2 Axes>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Удаляем символ '%' и преобразуем столбец CocoaPercent в числовой формат\n",
|
|||
|
"df['CocoaPercent'] = df['CocoaPercent'].str.replace('%', '').astype(float)\n",
|
|||
|
"\n",
|
|||
|
"# Выбираем столбцы для анализа\n",
|
|||
|
"columns_to_check = ['CocoaPercent', 'Rating']\n",
|
|||
|
"\n",
|
|||
|
"# Функция для подсчета выбросов\n",
|
|||
|
"def count_outliers(df, columns):\n",
|
|||
|
" outliers_count = {}\n",
|
|||
|
" for col in columns:\n",
|
|||
|
" Q1 = df[col].quantile(0.25)\n",
|
|||
|
" Q3 = df[col].quantile(0.75)\n",
|
|||
|
" IQR = Q3 - Q1\n",
|
|||
|
" lower_bound = Q1 - 1.5 * IQR\n",
|
|||
|
" upper_bound = Q3 + 1.5 * IQR\n",
|
|||
|
" \n",
|
|||
|
" # Считаем количество выбросов\n",
|
|||
|
" outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)]\n",
|
|||
|
" outliers_count[col] = len(outliers)\n",
|
|||
|
" \n",
|
|||
|
" return outliers_count\n",
|
|||
|
"\n",
|
|||
|
"# Подсчитываем выбросы\n",
|
|||
|
"outliers_count = count_outliers(df, columns_to_check)\n",
|
|||
|
"\n",
|
|||
|
"# Выводим количество выбросов для каждого столбца\n",
|
|||
|
"for col, count in outliers_count.items():\n",
|
|||
|
" print(f\"Количество выбросов в столбце '{col}': {count}\")\n",
|
|||
|
"\n",
|
|||
|
"# Создаем диаграммы размахов\n",
|
|||
|
"plt.figure(figsize=(15, 10))\n",
|
|||
|
"for i, col in enumerate(columns_to_check, 1):\n",
|
|||
|
" plt.subplot(2, 2, i)\n",
|
|||
|
" sns.boxplot(x=df[col])\n",
|
|||
|
" plt.title(f'Box Plot of {col}')\n",
|
|||
|
"plt.tight_layout()\n",
|
|||
|
"plt.show()"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Можно заметить, что оба столбца содержат выбросы, однако их значительно больше в столбце CocoaPercent. Кроме того, экстремальные значения здесь могут быть редкими экспериментальными продуктами и не отражать массовый рынок, а значит искажать статические модели и предсказания. С другой стороны, у столбца Rating выбросы несут информацию о таких крайних случаях, как исключительное качество продукта или совсем неудачный продукт. Такие данные могут быть ценны, особенно если целью является определение лучших и худших образцов для создания маркетинговых стратегий. Значит имеет смысл очистить от выбросов только столбец CocoaPercent.\n",
|
|||
|
"\n",
|
|||
|
"### Очищаем CocoaPercent от выбросов"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 534,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Количество удаленных строк: 186\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAusAAAJOCAYAAAAOKElgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA9GklEQVR4nO3deXyNZ+L///dJJCeJbHaSJogiirGkKFpLaau2tFrKaElr69Dqoqqqg7RjtNWpmo4uZhBVpfWpDh1USZmpZUoZS1GCWIrGHtqQRHJ9//DL+TlOdiKXej0fD49Hz33uc5/rvtxOX273ueMwxhgBAAAAsI5XaQ8AAAAAQO6IdQAAAMBSxDoAAABgKWIdAAAAsBSxDgAAAFiKWAcAAAAsRawDAAAAliLWAQAAAEsR6wAAAICliHUA19T+/fvlcDiUkJBQ2kNx89VXX6lx48by8/OTw+HQmTNnSntIKCVDhw7VPffcU+zXx8XFqUaNGtduQKXM4XBo/PjxrscffPCBIiMjlZ6eXnqDAuBCrAOWSkhIkMPhcPtVuXJltW/fXkuXLr3u41m1apXbWHx8fBQVFaV+/fpp37591+Q91q5dq/Hjx1/zkD558qR69eolf39/TZ06VbNnz1bZsmXzfc3evXs1ZMgQRUVFyc/PT8HBwWrdurWmTJmi8+fPX9PxlZQrjyE/Pz/VqVNHTz31lFJSUkp7eFdtx44dGj9+vPbv31/o1yQnJ+sf//iHXn75ZY/nzp49q/j4eDVq1EiBgYHy9/dXgwYNNGrUKB05cuQajtxucXFxysjI0IcffljaQwEgqUxpDwBA/l599VXVrFlTxhilpKQoISFBnTt31pdffqmuXbte9/EMHz5czZo1U2ZmpjZt2qRp06Zp8eLF2rZtm8LCwq5q22vXrlV8fLzi4uIUGhp6bQYsacOGDTp37pxee+01dezYscD1Fy9erJ49e8rpdKpfv35q0KCBMjIytHr1ao0cOVLbt2/XtGnTrtn4SlrOMXThwgWtXr1a77//vpYsWaIffvhBAQEBpT28YtuxY4fi4+PVrl27Qp/pnjJlimrWrKn27du7Ld+3b586duyogwcPqmfPnho8eLB8fX21detWTZ8+XV988YV2795dAnthHz8/P/Xv319vv/22nn76aTkcjtIeEnBTI9YBy91///26/fbbXY8HDBigKlWqaO7cuaUS63fddZcefvhhSdLjjz+uOnXqaPjw4Zo1a5ZGjx593cdTGMeOHZOkQv0FIDk5Wb1791b16tX1zTffqFq1aq7nhg0bpj179mjx4sUlNdQScfkxNHDgQFWoUEFvv/22Fi5cqD59+lzVttPS0m6Y4M/MzNScOXP05JNPui2/ePGievTooZSUFK1atUp33nmn2/MTJkzQG2+8cT2HWup69eqlN998UytXrtTdd99d2sMBbmpcBgPcYEJDQ+Xv768yZdz/rv3rr79qxIgRioiIkNPpVN26dfXWW2/JGCNJOn/+vKKjoxUdHe12GcepU6dUrVo1tWrVSllZWUUeT87/yJOTk/Nd75tvvtFdd92lsmXLKjQ0VLGxsdq5c6fr+fHjx2vkyJGSpJo1a7ou3SjoEof58+crJiZG/v7+qlixoh599FEdPnzY9Xy7du3Uv39/SVKzZs3kcDgUFxeX5/befPNN/fLLL5o+fbpbqOe49dZb9cwzz7geX7x4Ua+99ppq1aolp9OpGjVq6OWXX871et+lS5eqbdu2CgoKUnBwsJo1a6ZPPvmkSPsjSVu3blVcXJzrEp2qVavqiSee0MmTJ/Odqxy5/Z59/PHHrvctX768evfurUOHDrm9rl27dmrQoIE2btyoNm3aKCAgwHU5yYULFzR+/HjVqVNHfn5+qlatmnr06KG9e/e6Xp+dna133nlH9evXl5+fn6pUqaIhQ4bo9OnTbu9To0YNde3aVatXr1bz5s3l5+enqKgoffTRR651EhIS1LNnT0lS+/btXcfLqlWr8tzv1atX68SJEx7/uvL5559ry5YtGjNmjEeoS1JwcLAmTJiQ35QWet8WLlyoLl26KCwsTE6nU7Vq1dJrr73m8WcvZ6537Nih9u3bKyAgQOHh4XrzzTc93js9PV3jxo3TrbfeKqfTqYiICL344osex2B6erqee+45VapUSUFBQerevbt++umnXPcnJiZG5cuX18KFC/PdbwAlj1gHLJeamqoTJ07o+PHj2r59u/7whz/ol19+0aOPPupaxxij7t27a/LkyerUqZPefvtt1a1bVyNHjtTzzz8vSfL399esWbO0Z88ejRkzxvXaYcOGKTU1VQkJCfL29i7y+HJirEKFCnmus2LFCt133306duyYxo8fr+eff15r165V69atXTHeo0cP11neyZMna/bs2Zo9e7YqVaqU53YTEhLUq1cveXt7a+LEiRo0aJAWLFigO++803Xd+5gxYzR48GBJly4HmT17toYMGZLnNr/88ktFRUWpVatWhdr/gQMHauzYsWratKkmT56stm3bauLEierdu7fHWLt06aJTp05p9OjRev3119W4cWN99dVXRdofSVq+fLn27dunxx9/XO+++6569+6tefPmqXPnzq6/nOXnyt+zCRMmqF+/fqpdu7befvttPfvss0pMTFSbNm08vj9w8uRJ3X///WrcuLHeeecdtW/fXllZWeratavi4+MVExOjv/zlL3rmmWeUmpqqH374wfXaIUOGaOTIka5r/x9//HHNmTNH9913nzIzM93eZ8+ePXr44Yd1zz336C9/+YvKlSunuLg4bd++XZLUpk0bDR8+XJL08ssvu46XevXq5bnfa9eulcPhUJMmTdyWL1q0SJL02GOPFTh3eSnsviUkJCgwMFDPP/+8pkyZopiYGI0dO1YvvfSSxzZPnz6tTp06qVGjRvrLX/6i6OhojRo1yu07K9nZ2erevbveeustdevWTe+++64eeOABTZ48WY888ojb9gYOHKh33nlH9957r15//XX5+PioS5cuee5T06ZNtWbNmmLPCYBrxACw0syZM40kj19Op9MkJCS4rfvPf/7TSDJ/+tOf3JY//PDDxuFwmD179riWjR492nh5eZn//Oc/Zv78+UaSeeeddwocz8qVK40kM2PGDHP8+HFz5MgRs3jxYlOjRg3jcDjMhg0bjDHGJCcnG0lm5syZrtc2btzYVK5c2Zw8edK1bMuWLcbLy8v069fPtWzSpElGkklOTi5wPBkZGaZy5cqmQYMG5vz5867l//rXv4wkM3bsWNeynLnMGWNeUlNTjSQTGxtb4PsbY8zmzZuNJDNw4EC35S+88IKRZL755htjjDFnzpwxQUFBpkWLFm5jNcaY7OzsIu9PWlqax1jmzp1rJJn//Oc/Hvu9YsUKc/z4cXPo0CEzb948U6FCBePv729++ukns3//fuPt7W0mTJjgtr1t27aZMmXKuC1v27atkWQ++OADt3VnzJhhJJm3337bY1w5+/ftt98aSWbOnDluz3/11Vcey6tXr+6xL8eOHTNOp9OMGDHCtSzn+F25cqXH++bm0UcfNRUqVPBY3qRJExMSElKobRhjTP/+/U316tVdj4uyb7n93g0ZMsQEBASYCxcuuJblzPVHH33kWpaenm6qVq1qHnroIdey2bNnGy8vL/Ptt9+6bfODDz4wksyaNWuMMf//sTp06FC39X7/+98bSWbcuHEe4xo8eLDx9/fPZyYAXA+cWQcsN3XqVC1fvlzLly/Xxx9/rPbt22vgwIFasGCBa50lS5bI29vbdaYxx4gRI2SMcTsTN378eNWvX1/9+/fX0KFD1bZtW4/X5eeJJ55QpUqVFBYWpi5duujXX3/VrFmz3K6rv9zRo0e1efNmxcXFqXz58q7lv/vd73TPPfdoyZIlhX7vy33//fc6duyYhg4dKj8/P9fyLl26KDo6uljXlZ89e1aSFBQUVKj1c8ae868XOUaMGCFJrjEsX75c586d00svveQ2VkmuL+8VZX/8/f1d/33hwgWdOHFCd9xxhyRp06ZNHuPs2LGjKlWqpIiICPXu3VuBgYH64osvFB4ergU
|
|||
|
"text/plain": [
|
|||
|
"<Figure size 1500x600 with 1 Axes>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Выбираем столбцы для очистки\n",
|
|||
|
"columns_to_clean = ['CocoaPercent']\n",
|
|||
|
"\n",
|
|||
|
"# Функция для удаления выбросов\n",
|
|||
|
"def remove_outliers(df, columns):\n",
|
|||
|
" for col in columns:\n",
|
|||
|
" Q1 = df[col].quantile(0.25)\n",
|
|||
|
" Q3 = df[col].quantile(0.75)\n",
|
|||
|
" IQR = Q3 - Q1\n",
|
|||
|
" lower_bound = Q1 - 1.5 * IQR\n",
|
|||
|
" upper_bound = Q3 + 1.5 * IQR\n",
|
|||
|
" \n",
|
|||
|
" # Удаляем строки, содержащие выбросы\n",
|
|||
|
" df = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)]\n",
|
|||
|
" \n",
|
|||
|
" return df\n",
|
|||
|
"\n",
|
|||
|
"# Удаляем выбросы\n",
|
|||
|
"df_cleaned = remove_outliers(df, columns_to_clean)\n",
|
|||
|
"\n",
|
|||
|
"# Выводим количество удаленных строк\n",
|
|||
|
"print(f\"Количество удаленных строк: {len(df) - len(df_cleaned)}\")\n",
|
|||
|
"\n",
|
|||
|
"# Создаем диаграммы размаха для очищенных данных\n",
|
|||
|
"plt.figure(figsize=(15, 6))\n",
|
|||
|
"\n",
|
|||
|
"# Диаграмма размаха для CocoaPercent\n",
|
|||
|
"plt.subplot(1, 2, 1)\n",
|
|||
|
"sns.boxplot(x=df_cleaned['CocoaPercent'])\n",
|
|||
|
"plt.title('Box Plot of CocoaPercent (Cleaned)')\n",
|
|||
|
"plt.xlabel('Cocoa Percent')\n",
|
|||
|
"\n",
|
|||
|
"plt.tight_layout()\n",
|
|||
|
"plt.show()\n",
|
|||
|
"\n",
|
|||
|
"# Сохраняем очищенный датасет\n",
|
|||
|
"df_cleaned.to_csv(\"..//..//static//csv//flavors_of_cacao_cleaned.csv\", index=False)\n",
|
|||
|
"df = df_cleaned"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Видно, что выбросов практически не осталось.\n",
|
|||
|
"\n",
|
|||
|
"### Теперь проверим на пустые значения"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 535,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Company (Maker-if known) 0\n",
|
|||
|
"Specific Bean Originor Bar Name 0\n",
|
|||
|
"REF 0\n",
|
|||
|
"ReviewDate 0\n",
|
|||
|
"CocoaPercent 0\n",
|
|||
|
"CompanyLocation 0\n",
|
|||
|
"Rating 0\n",
|
|||
|
"BeanType 1\n",
|
|||
|
"Broad BeanOrigin 1\n",
|
|||
|
"dtype: int64\n",
|
|||
|
"\n",
|
|||
|
"Company (Maker-if known) False\n",
|
|||
|
"Specific Bean Originor Bar Name False\n",
|
|||
|
"REF False\n",
|
|||
|
"ReviewDate False\n",
|
|||
|
"CocoaPercent False\n",
|
|||
|
"CompanyLocation False\n",
|
|||
|
"Rating False\n",
|
|||
|
"BeanType True\n",
|
|||
|
"Broad BeanOrigin True\n",
|
|||
|
"dtype: bool\n",
|
|||
|
"\n",
|
|||
|
"BeanType процент пустых значений: %0.06\n",
|
|||
|
"Broad BeanOrigin процент пустых значений: %0.06\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Количество пустых значений признаков\n",
|
|||
|
"print(df.isnull().sum())\n",
|
|||
|
"\n",
|
|||
|
"print()\n",
|
|||
|
"\n",
|
|||
|
"# Есть ли пустые значения признаков\n",
|
|||
|
"print(df.isnull().any())\n",
|
|||
|
"\n",
|
|||
|
"print()\n",
|
|||
|
"\n",
|
|||
|
"# Процент пустых значений признаков\n",
|
|||
|
"for i in df.columns:\n",
|
|||
|
" null_rate = df[i].isnull().sum() / len(df) * 100\n",
|
|||
|
" if null_rate > 0:\n",
|
|||
|
" print(f\"{i} процент пустых значений: %{null_rate:.2f}\")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"В датасете имеется пара пустых значений. Удалим их."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 536,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"\n",
|
|||
|
"Количество пустых значений в каждом столбце после удаления:\n",
|
|||
|
"Company (Maker-if known) 0\n",
|
|||
|
"Specific Bean Originor Bar Name 0\n",
|
|||
|
"REF 0\n",
|
|||
|
"ReviewDate 0\n",
|
|||
|
"CocoaPercent 0\n",
|
|||
|
"CompanyLocation 0\n",
|
|||
|
"Rating 0\n",
|
|||
|
"BeanType 0\n",
|
|||
|
"Broad BeanOrigin 0\n",
|
|||
|
"dtype: int64\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Удаление пропущенных значений в столбцах BeanType и Broad BeanOrigin\n",
|
|||
|
"df = df.dropna(subset=['BeanType', 'Broad BeanOrigin'])\n",
|
|||
|
"\n",
|
|||
|
"# Проверка на пропущенные значения после удаления\n",
|
|||
|
"missing_values_after_drop = df.isnull().sum()\n",
|
|||
|
"\n",
|
|||
|
"# Вывод результатов после удаления\n",
|
|||
|
"print(\"\\nКоличество пустых значений в каждом столбце после удаления:\")\n",
|
|||
|
"print(missing_values_after_drop)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Пустых значений в датасете теперь нет.\n",
|
|||
|
"\n",
|
|||
|
"### Можно перейти к созданию выборок"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 537,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Размер обучающей выборки: (964, 8)\n",
|
|||
|
"Размер контрольной выборки: (321, 8)\n",
|
|||
|
"Размер тестовой выборки: (322, 8)\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Разделение на признаки (X) и целевую переменную (y)\n",
|
|||
|
"# Предположим, что Rating - это целевая переменная\n",
|
|||
|
"X = df.drop('Rating', axis=1)\n",
|
|||
|
"y = df['Rating']\n",
|
|||
|
"\n",
|
|||
|
"# Разбиение на обучающую и остальную выборку (контрольную + тестовую)\n",
|
|||
|
"X_train, X_rem, y_train, y_rem = train_test_split(X, y, train_size=0.6, random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"# Разбиение остатка на контрольную и тестовую выборки\n",
|
|||
|
"X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, test_size=0.5, random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"# Вывод размеров выборок\n",
|
|||
|
"print(\"Размер обучающей выборки:\", X_train.shape)\n",
|
|||
|
"print(\"Размер контрольной выборки:\", X_val.shape)\n",
|
|||
|
"print(\"Размер тестовой выборки:\", X_test.shape)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 538,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Распределение классов в обучающей выборке:\n",
|
|||
|
"Rating\n",
|
|||
|
"3.50 0.242739\n",
|
|||
|
"3.00 0.199170\n",
|
|||
|
"3.25 0.155602\n",
|
|||
|
"2.75 0.137967\n",
|
|||
|
"3.75 0.125519\n",
|
|||
|
"2.50 0.062241\n",
|
|||
|
"4.00 0.050830\n",
|
|||
|
"2.00 0.012448\n",
|
|||
|
"2.25 0.007261\n",
|
|||
|
"5.00 0.002075\n",
|
|||
|
"1.50 0.002075\n",
|
|||
|
"1.75 0.001037\n",
|
|||
|
"1.00 0.001037\n",
|
|||
|
"Name: proportion, dtype: float64\n",
|
|||
|
"\n",
|
|||
|
"Распределение классов в контрольной выборке:\n",
|
|||
|
"Rating\n",
|
|||
|
"3.50 0.211838\n",
|
|||
|
"3.00 0.168224\n",
|
|||
|
"3.25 0.165109\n",
|
|||
|
"2.75 0.137072\n",
|
|||
|
"3.75 0.127726\n",
|
|||
|
"2.50 0.074766\n",
|
|||
|
"4.00 0.074766\n",
|
|||
|
"2.00 0.021807\n",
|
|||
|
"2.25 0.009346\n",
|
|||
|
"1.50 0.006231\n",
|
|||
|
"1.00 0.003115\n",
|
|||
|
"Name: proportion, dtype: float64\n",
|
|||
|
"\n",
|
|||
|
"Распределение классов в тестовой выборке:\n",
|
|||
|
"Rating\n",
|
|||
|
"3.25 0.211180\n",
|
|||
|
"3.50 0.198758\n",
|
|||
|
"3.00 0.164596\n",
|
|||
|
"2.75 0.145963\n",
|
|||
|
"3.75 0.136646\n",
|
|||
|
"4.00 0.068323\n",
|
|||
|
"2.50 0.062112\n",
|
|||
|
"2.00 0.006211\n",
|
|||
|
"1.00 0.003106\n",
|
|||
|
"2.25 0.003106\n",
|
|||
|
"Name: proportion, dtype: float64\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Функция для анализа сбалансированности\n",
|
|||
|
"def analyze_balance(y_train, y_val, y_test):\n",
|
|||
|
" print(\"Распределение классов в обучающей выборке:\")\n",
|
|||
|
" print(y_train.value_counts(normalize=True))\n",
|
|||
|
" \n",
|
|||
|
" print(\"\\nРаспределение классов в контрольной выборке:\")\n",
|
|||
|
" print(y_val.value_counts(normalize=True))\n",
|
|||
|
" \n",
|
|||
|
" print(\"\\nРаспределение классов в тестовой выборке:\")\n",
|
|||
|
" print(y_test.value_counts(normalize=True))\n",
|
|||
|
"\n",
|
|||
|
"# Анализ сбалансированности\n",
|
|||
|
"analyze_balance(y_train, y_val, y_test)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Выборки несбалансированны в частности из-за того, что некоторые классы занимают крайне малую долю в данных. При необходимости получить сбалансированный набор можно использовать специальные методы, к примеру oversampling и undersampling. Но в данном случае просто так их использовать не получится, потому что задача модели состоит в том, чтобы предсказать числовые (регрессионые) значения, а большинство реализаций в таком случае применить не получится. К тому же в Rating мало уникальных значений, что вызовет проблемы при использовании методов, предназначенных для регрессии (таких как к примеру SMOGN). Поэтому здесь применение таких методов не является целесообразным.\n",
|
|||
|
"\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"## Датасет №2 (качество воды) \n",
|
|||
|
"\n",
|
|||
|
"Ссылка: https://www.kaggle.com/datasets/adityakadiwal/water-potability\n",
|
|||
|
"\n",
|
|||
|
"Проблемная область: качество питьевой воды и факторы, влияющие на ее безопасность для здоровья.\n",
|
|||
|
"\n",
|
|||
|
"Объекты наблюдения: водоемы, содержащие воду разного качества."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 539,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Index(['ph', 'Hardness', 'Solids', 'Chloramines', 'Sulfate', 'Conductivity',\n",
|
|||
|
" 'Organic_carbon', 'Trihalomethanes', 'Turbidity', 'Potability'],\n",
|
|||
|
" dtype='object')\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"import pandas as pd\n",
|
|||
|
"import matplotlib.pyplot as plt\n",
|
|||
|
"import seaborn as sns\n",
|
|||
|
"from sklearn.model_selection import train_test_split\n",
|
|||
|
"from imblearn.over_sampling import SMOTE\n",
|
|||
|
"\n",
|
|||
|
"# вывод всех столбцов\n",
|
|||
|
"df = pd.read_csv(\"..//..//static//csv//water_potability.csv\")\n",
|
|||
|
"print(df.columns)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Атрибуты: \n",
|
|||
|
"* ph – параметр для оценки кислотно-щелочного баланса воды;\n",
|
|||
|
"* Hardness – жесткость воды, определяемая содержанием кальция и магния;\n",
|
|||
|
"* Solids – общее количество растворенных веществ, указывающее на минерализацию воды;\n",
|
|||
|
"* Chloramines – концентрация хлора и хлораминов, использующихся для дезинфекции воды;\n",
|
|||
|
"* Sulfate – содержание сульфатов, присутствующих в воде;\n",
|
|||
|
"* Conductivity – электропроводность воды, измеряющая уровень ионов в растворе;\n",
|
|||
|
"* Organic_carbon – уровень органического углерода, происходящего из разлагающихся органических веществ;\n",
|
|||
|
"* Trihalomethanes – концентрация трихалометанов, образующихся при обработке хлором;\n",
|
|||
|
"* Turbidity – мутность воды, указывающая на количество взвешенных твердых частиц;\n",
|
|||
|
"* Potability – показатель пригодности воды для питья (1 – пригодна, 0 – непригодна).\n",
|
|||
|
"\n",
|
|||
|
"Примеры бизнес целей и целей технического проекта:\n",
|
|||
|
"1. Совершенствование систем очистки воды.\n",
|
|||
|
" * Бизнес-цель: разработка и внедрение инновационных технологий очистки воды, чтобы уменьшить расходы на водоочистные сооружения и повысить их эффективность.\n",
|
|||
|
" * Цель технического проекта: проектирование и тестирование новых фильтров и процессов очистки на основе данных о загрязнении воды.\n",
|
|||
|
"2. Интеграция данных для управления водными ресурсами.\n",
|
|||
|
" * Бизнес-цель: объединение данных о водных ресурсах для комплексного анализа и управления, что позволит более эффективно распределять ресурсы.\n",
|
|||
|
" * Цель технического проекта: разработка платформы для интеграции данных с различных датчиков и источников информации, использующей машинное обучение для прогнозирования изменений качества воды.\n",
|
|||
|
"3. Повышение осведомленности о качестве воды.\n",
|
|||
|
" * Бизнес-цель: информирование населения о состоянии водоемов и возможных рисках для здоровья.\n",
|
|||
|
" * Цель технического проекта: разработка платформы для публичного доступа к данным о качестве воды.\n",
|
|||
|
"\n",
|
|||
|
"Входные данные и целевой признак могут быть следующими:\n",
|
|||
|
"1. Входные данные:\n",
|
|||
|
" * pH значение;\n",
|
|||
|
" * Жесткость воды;\n",
|
|||
|
" * Общее количество растворенных веществ;\n",
|
|||
|
" * Концентрация хлора и хлораминов;\n",
|
|||
|
" * Содержание сульфатов;\n",
|
|||
|
" * Электропроводность;\n",
|
|||
|
" * Уровень органического углерода;\n",
|
|||
|
" * Концентрация трихалометанов;\n",
|
|||
|
" * Мутность воды.\n",
|
|||
|
"2. Целевой признак:\n",
|
|||
|
" * Пригодность воды для питья.\n",
|
|||
|
"\n",
|
|||
|
"Актуальность: анализ качества питьевой воды и факторов, влияющих на ее безопасность, играет очень важную роль в охране здоровья населения. Так мониторинг факторов, влияющих на качество воды, позволит предотвращать вспышки заболеваний и способствовать повышению уровня жизни.\n",
|
|||
|
"\n",
|
|||
|
"### Проверяем на выбросы"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 540,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Количество выбросов в столбце 'Hardness': 83\n",
|
|||
|
"Количество выбросов в столбце 'Solids': 47\n",
|
|||
|
"Количество выбросов в столбце 'Organic_carbon': 25\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABdIAAAPdCAYAAACOcJpIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAACO4UlEQVR4nOzdd5gV5d0//s8usIW69CJIU2mCWNCvsSARBWyYxBJbwJ5gjcYntgD2FjXGx54I2HuNFXtUwIIIKKIgqFGBAC697/z+8Lfn4bAwLAgsi6/XdXGxZ+aemXvm3nPms+8zZ05OkiRJAAAAAAAAq5Vb0R0AAAAAAIDNmSAdAAAAAABSCNIBAAAAACCFIB0AAAAAAFII0gEAAAAAIIUgHQAAAAAAUgjSAQAAAAAghSAdAAAAAABSCNIBAAAAACCFIB3gJ5g6dWrk5OTE0KFDK7orWV588cXo2rVrFBQURE5OThQXF1d0l9bqjTfeiJycnHjjjTcquisAAPyMqOnL2meffWKfffbJPF6XY9S/f/9o1arVRusbQEURpAObhaFDh0ZOTk7Wv0aNGkWPHj3ihRde2OT9KQ11S/9Vq1Yt2rRpE7/73e/iyy+/3CDbePfdd2Pw4MEbvCCeNWtWHHHEEVFYWBi33HJL3HvvvVGjRo3Vti097h988MFq5++zzz6x/fbbb9D+AQCwZVLTbzjrUtNHRIwbNy4OO+ywaNmyZRQUFMRWW20V++23X9x8880btF8AP2dVK7oDACu79NJLo3Xr1pEkSUyfPj2GDh0aBxxwQDz77LNx0EEHbfL+nHnmmdGtW7dYtmxZjB49Ou6888547rnnYty4cdGsWbOftO533303Lrnkkujfv38UFRVtmA5HxPvvvx/z5s2Lyy67LHr27LnB1gsAAOWhpv/p1qWmf/fdd6NHjx6x9dZbx8knnxxNmjSJb775JkaOHBk33XRTnHHGGT+5Py1btoxFixZFtWrVfvK6ACorQTqwWenTp0/ssssumccnnnhiNG7cOB588MEKKbr32muvOOywwyIi4vjjj4/tttsuzjzzzBg2bFhccMEFm7w/5TFjxoyIiA1ayG8ISZLE4sWLo7CwsKK7AgDARqSm/+nWpaa/4oorok6dOvH++++XaV+6np8qJycnCgoKNsi6ACort3YBNmtFRUVRWFgYVatmv++3YMGCOPfcc6NFixaRn58f7dq1i7/+9a+RJElERCxatCjat28f7du3j0WLFmWWmz17djRt2jR+8YtfxIoVK9a5P7/85S8jImLKlCmp7V577bXYa6+9okaNGlFUVBR9+/aNCRMmZOYPHjw4zjvvvIiIaN26debjplOnTk1d76OPPho777xzFBYWRoMGDeLYY4+Nb7/9NjN/n332iX79+kVERLdu3SInJyf69++/zvuZZsiQIfHLX/4yGjVqFPn5+dGxY8e47bbbyrRr1apVHHTQQfHSSy/FLrvsEoWFhXHHHXdERMR//vOfOPTQQ6NGjRrRqFGj+OMf/xhLliwps47SW8t8+umn0aNHj6hevXpstdVWce2115Zpu2TJkhg0aFBss802kZ+fHy1atIj/+Z//KbPe4cOHx5577hlFRUVRs2bNaNeuXVx44YVZbW6++ebo1KlTVK9ePerWrRu77LJLPPDAAz/lsAEA/Gyp6bNt6Jp+8uTJ0alTp9WG7o0aNcp6vHz58rjsssuibdu2kZ+fH61atYoLL7xwtbX4ytZ0j/Snnnoqtt9++ygoKIjtt98+nnzyydUu/9BDD8XOO+8ctWrVitq1a0fnzp3jpptuSt0mwObGFenAZmXOnDkxc+bMSJIkZsyYETfffHPMnz8/jj322EybJEnikEMOiddffz1OPPHE6Nq1a7z00ktx3nnnxbfffhs33nhjFBYWxrBhw2KPPfaIiy66KG644YaIiDjttNNizpw5MXTo0KhSpco692/y5MkREVG/fv01tnnllVeiT58+0aZNmxg8eHAsWrQobr755thjjz1i9OjR0apVq/j1r38dn3/+eTz44INx4403RoMGDSIiomHDhmtc79ChQ+P444+Pbt26xVVXXRXTp0+Pm266Kd5555346KOPoqioKC666KJo165d3HnnnZmP1LZt23at+1V63Fe1bNmyMtNuu+226NSpUxxyyCFRtWrVePbZZ2PAgAFRUlISp512WlbbiRMnxlFHHRWnnnpqnHzyydGuXbtYtGhR7LvvvvH111/HmWeeGc2aNYt77703XnvttdX27YcffojevXvHr3/96zjiiCPiscceiz//+c/RuXPn6NOnT0RElJSUxCGHHBJvv/12nHLKKdGhQ4cYN25c3HjjjfH555/HU089FRERn3zySRx00EHRpUuXuPTSSyM/Pz8mTZoU77zzTmZ7d911V5x55plx2GGHxVlnnRWLFy+OsWPHxqhRo+Loo49e67EEAPi5U9Nv2pq+ZcuWMWLEiBg/fvxav9/opJNOimHDhsVhhx0W5557bowaNSquuuqqmDBhwhpD8DV5+eWX4ze/+U107Ngxrrrqqpg1a1Ycf/zx0bx586x2w4cPj6OOOir23XffuOaaayIiYsKECfHOO+/EWWedtU7bBKhQCcBmYMiQIUlElPmXn5+fDB06NKvtU089lUREcvnll2dNP+yww5KcnJxk0qRJmWkXXHBBkpubm7z11lvJo48+mkRE8re//W2t/Xn99deTiEjuvvvu5L///W/y3XffJc8991zSqlWrJCcnJ3n//feTJEmSKVOmJBGRDBkyJLNs165dk0aNGiWzZs3KTPv444+T3Nzc5He/+11m2nXXXZdERDJlypS19mfp0qVJo0aNku233z5ZtGhRZvq//vWvJCKSgQMHZqaVHsvSPqZZ03Ff+V+nTp2yllm4cGGZ9fTq1Stp06ZN1rSWLVsmEZG8+OKLWdP/9re/JRGRPPLII5lpCxYsSLbZZpskIpLXX389M7179+5JRCT33HNPZtqSJUuSJk2aJL/5zW8y0+69994kNzc3+fe//521rdtvvz2JiOSdd95JkiRJbrzxxiQikv/+979rPCZ9+/Yts88AAKydmj7dxqrpX3755aRKlSpJlSpVkt133z35n//5n+Sll15Kli5dmtVuzJgxSUQkJ510Utb0P/3pT0lEJK+99lpmWvfu3ZPu3btnHq/pGDVt2jQpLi7O6ktEJC1btsxMO+uss5LatWsny5cvX+u+AGzO3NoF2KzccsstMXz48Bg+fHjcd9990aNHjzjppJPiiSeeyLR5/vnno0qVKnHmmWdmLXvuuedGkiTxwgsvZKYNHjw4OnXqFP369YsBAwZE9+7dyyyX5oQTToiGDRtGs2bN4sADD4wFCxbEsGHDsu75uLLvv/8+xowZE/3794969eplpnfp0iX222+/eP7558u97ZV98MEHMWPGjBgwYEDWvQkPPPDAaN++fTz33HPrtd5SKx/3lf916dKlTNuV73FeerVR9+7d48svv4w5c+ZktW3dunX06tUra9rzzz8fTZs2zdynMiKievXqccopp6y2bzVr1sy6eikvLy923XXX+PLLLzPTHn300ejQoUO0b98+Zs6cmflX+rHd119/PSL+7x6TTz/9dJSUlKx2e0VFRfGf//wn3n///dXOBwAgnZp+9TZWTb/ffvvFiBEj4pBDDomPP/44rr322ujVq1dstdVW8cwzz2Talfb7nHPOyVr+3HPPjYhYp+2XHqN+/fpFnTp1svrSsWPHrLZFRUWxYMGCGD58+DrvG8DmxK1dgM3KrrvumlXQHnXUUbHjjjvG6aefHgcddFDk5eXFV199Fc2aNYtatWplLduhQ4eIiPjqq68y0/Ly8uLuu++Obt26RUFBQQwZMiRycnLK3Z+BAwfGXnvtFVWqVIkGDRpEhw4dytzbcWWl227Xrl2ZeR06dIiXXnopFixYEDVq1Ch3H9a23vbt28fbb7+9Tutb1arHvVTdunXL3PLlnXfeiUGDBsWIESNi4cKFWfPmzJmTVUi3bt26zDq/+uqr2GabbcqMw+r2LSKiefPmZdrWrVs3xo4dm3n
|
|||
|
"text/plain": [
|
|||
|
"<Figure size 1500x1000 with 3 Axes>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Выбираем столбцы для анализа\n",
|
|||
|
"columns_to_check = ['Hardness', 'Solids', 'Organic_carbon']\n",
|
|||
|
"\n",
|
|||
|
"# Функция для подсчета выбросов\n",
|
|||
|
"def count_outliers(df, columns):\n",
|
|||
|
" outliers_count = {}\n",
|
|||
|
" for col in columns:\n",
|
|||
|
" Q1 = df[col].quantile(0.25)\n",
|
|||
|
" Q3 = df[col].quantile(0.75)\n",
|
|||
|
" IQR = Q3 - Q1\n",
|
|||
|
" lower_bound = Q1 - 1.5 * IQR\n",
|
|||
|
" upper_bound = Q3 + 1.5 * IQR\n",
|
|||
|
" \n",
|
|||
|
" # Считаем количество выбросов\n",
|
|||
|
" outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)]\n",
|
|||
|
" outliers_count[col] = len(outliers)\n",
|
|||
|
" \n",
|
|||
|
" return outliers_count\n",
|
|||
|
"\n",
|
|||
|
"# Подсчитываем выбросы\n",
|
|||
|
"outliers_count = count_outliers(df, columns_to_check)\n",
|
|||
|
"\n",
|
|||
|
"# Выводим количество выбросов для каждого столбца\n",
|
|||
|
"for col, count in outliers_count.items():\n",
|
|||
|
" print(f\"Количество выбросов в столбце '{col}': {count}\")\n",
|
|||
|
"\n",
|
|||
|
"# Создаем диаграммы размахов\n",
|
|||
|
"plt.figure(figsize=(15, 10))\n",
|
|||
|
"for i, col in enumerate(columns_to_check, 1):\n",
|
|||
|
" plt.subplot(2, 2, i)\n",
|
|||
|
" sns.boxplot(x=df[col])\n",
|
|||
|
" plt.title(f'Box Plot of {col}')\n",
|
|||
|
"plt.tight_layout()\n",
|
|||
|
"plt.show()"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"В каждом из выбранных столбцов присутствуют выбросы. Очистим их."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 541,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Количество удаленных строк: 145\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABdIAAAJOCAYAAACz9fURAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABtf0lEQVR4nO3dd5gV5fk/4GcpS69Kl67SBAuWIAoqKqAitmCIUewarIkaNUSxG7sGazQCMcbeYy8oithFUREREY0FDAg2EGTf3x/+9nw97DIsCOwu3vd1cemZec+c953ZOc/M58yZU5BSSgEAAAAAAJSqSnl3AAAAAAAAKjJBOgAAAAAAZBCkAwAAAABABkE6AAAAAABkEKQDAAAAAEAGQToAAAAAAGQQpAMAAAAAQAZBOgAAAAAAZBCkAwAAAABABkE6lcKHH34YBQUFMWbMmPLuSp5HHnkkNtlkk6hZs2YUFBTEvHnzyrtLy/X0009HQUFBPP300+XdlZ/lpZdeisLCwpg5c+ZKPX9tWQ/FDjzwwGjXrl3u8Zw5c6JOnTrx0EMPlV+nAFaSul/SdtttF9ttt13u8Yqso6VrxM/18ccfR82aNWPChAkr9fyKun1X1hlnnBEFBQW5x4sXL47WrVvH1VdfXY69AtYmFfV9szKeD/9cq7qmrmnFNet///tfeXclj2OLfI4tKi5B+i/MmDFjoqCgIO9f06ZNY/vtt4+HH354jfenOMws/le9evXo0KFDHHDAAfHBBx+sktd4/vnn44wzzljlRX3OnDkxZMiQqFWrVlx11VVx0003RZ06dUptW7zeX3nllVLnb7fddrHRRhut0v6t7UaMGBFDhw6Ntm3blph3zz33xMCBA2PdddeNwsLCaNmyZQwZMiSeeuqpcuhp+VhnnXXi0EMPjdNOO628uwKUI3V/1VmRuh8RMXny5Nhnn32ibdu2UbNmzWjVqlXstNNOMWrUqFXar/Jw1llnxVZbbRW9e/cuMe/pp5+OvfbaK5o3bx6FhYXRtGnTGDRoUNx9993l0NPyUb169fjjH/8Y5557bixcuLC8uwP8hLq46qxoXYyIePvtt+N3v/tdtGrVKmrUqBEtW7aM/fbbL95+++1V2jcqH8cW2RxbVBzVyrsDlI+zzjor2rdvHymlmDVrVowZMyZ22WWXeOCBB2K33XZb4/059thjY4sttojFixfHa6+9Fn//+9/jwQcfjMmTJ0fLli1/1rKff/75OPPMM+PAAw+Mhg0brpoOR8TLL78cX3/9dZx99tmx4447rrLlsnyTJk2KJ554Ip5//vm86SmlOPjgg2PMmDGx6aabxh//+Mdo3rx5fPbZZ3HPPfdEv379YsKECbH11luXU8/XrCOPPDL+9re/xVNPPRU77LBDeXcHKEfq/s+3InX/+eefj+233z7atGkThx12WDRv3jw+/vjjeOGFF+KKK66IY4455mf3p23btrFgwYKoXr36z17Wivjiiy9i7NixMXbs2BLzRo4cGWeddVZssMEGccQRR0Tbtm1jzpw58dBDD8Xee+8dN998c/z2t79do/0tLwcddFCccsop8e9//zsOPvjg8u4OsBR18edb0fPhu+++O4YOHRqNGzeOQw45JNq3bx8ffvhh/OMf/4g777wzbr311thzzz1XWf9Wl+uvvz6KiorKuxtrFccWZePYomIQpP9CDRw4MDbffPPc40MOOSSaNWsWt9xyS7kcOGy77baxzz77RMSPbw4bbrhhHHvssTF27Ng49dRT13h/ymL27NkREav0YGRVSCnFwoULo1atWuXdldVm9OjR0aZNm/jVr36VN/2SSy6JMWPGxPHHHx+XXnpp3lehRowYETfddFNUq/bLedvr0qVLbLTRRjFmzBhBOvzCqfs/34rU/XPPPTcaNGgQL7/8con2xcv5uQoKCqJmzZqrZFkr4l//+ldUq1YtBg0alDf9zjvvjLPOOiv22Wef+Pe//50X8J900knx6KOPxuLFi9d0d8tNw4YNY+edd44xY8Y42YUKSF38+VakLk6fPj3233//6NChQ4wfPz6aNGmSm3fcccfFtttuG/vvv3+8+eab0aFDh2Uu59tvv13uVe+r25r+AHtVqQjrblkcW5SNY4uKwa1diIgfd8hatWqVCBm//fbbOOGEE6J169ZRo0aN6NSpU1x88cWRUoqIiAULFkTnzp2jc+fOsWDBgtzz5s6dGy1atIitt946lixZssL9KQ79ZsyYkdnuqaeeim233Tbq1KkTDRs2jMGDB8eUKVNy888444w46aSTIiKiffv2ua/Mffjhh5nLveOOO6Jnz55Rq1atWHfddeN3v/tdfPLJJ7n52223XQwbNiwiIrbYYosoKCiIAw88cIXHmWX06NGxww47RNOmTaNGjRrRtWvXuOaaa0q0a9euXey2227x6KOPxuabbx61atWK6667LiIi/vvf/8Yee+wRderUiaZNm8Yf/vCH+P7770sso/jWMu+8805sv/32Ubt27WjVqlVceOGFJdp+//33MXLkyFh//fWjRo0a0bp16/jTn/5UYrmPP/54bLPNNtGwYcOoW7dudOrUKf785z/ntRk1alR069YtateuHY0aNYrNN988/v3vfy933dx7772xww475AXlCxYsiPPPPz86d+4cF198cd68Yvvvv39sueWWmct+8cUXY8CAAdGgQYOoXbt29O3bt8R92mbOnBnDhw+PTp06Ra1atWKdddaJX//61yX+roq/OjphwoT44x//GE2aNIk6derEnnvuGV988UWJ13744Ydzf8/16tWLXXfdtdSvOd57772x0UYbRc2aNWOjjTaKe+65Z5nj2WmnneKBBx7I7bMAEer+0lZ13Z8+fXp069at1HChadOmeY9/+OGHOPvss6Njx45Ro0aNaNeuXfz5z38utV7/1LLuBVrWGnHrrbdGz549o169elG/fv3o3r17XHHFFZmvWbz8rbbaKurWrZs3/bTTTovGjRvHjTfeWGrI0L9//+WGU++++27ss88+0bhx46hZs2Zsvvnmcf/99+e1mTt3bpx44onRvXv3qFu3btSvXz8GDhwYb7zxRl674tsl3H777XHuuefGeuutFzVr1ox+/frF+++/X+K1y1L/IyKee+652GKLLaJmzZrRsWPH3DFXaXbaaad47rnnYu7cuZnjBsqfuphvVdfFiy66KL777rv4+9//nheiR0Ssu+66cd1118W3336bd/5ZfI/od955J377299Go0aNYptttomIiKKiojjjjDOiZcuWUbt27dh+++3jnXfeiXbt2uX1Y3XUjNLukV5UVBRXXHFFdO/ePWrWrBlNmjSJAQMGLPPWrsvy7rvvxpAhQ6JJkyZRq1at6NSpU4wYMSI3f0XPQ5955pkYPnx4NG3aNNZbb728Nv/73/9iyJAhUb9+/VhnnXXiuOOOK3HLkLIeoxRnEs8991xsueWWUbNmzejQoUP885//LNO4HVs4tqhMfjmXZpJn/vz58b///S9SSjF79uwYNWpUfPPNN/G73/0u1yalFLvvvnuMGzcuDjnkkNhkk03i0UcfjZNOOik++eSTuOyyy6JWrVoxduzY6N27d4wYMSIuvfTSiIg46qijYv78+TFmzJioWrXqCvdv+vTpEfHjfZ6X5YknnoiBAwdGhw4d4owzzogFCxbEqFGjonfv3vHaa69Fu3btYq+99or33nsvbrnllrjsssti3XXXjYgoUbx/asyYMXHQQQfFFltsEeeff37MmjUrrrjiipgwYUK8/vrr0bBhwxgxYkR06tQp/v73v+e+FtixY8fljqt4vS+ttE9Rr7nmmujWrVvsvvvuUa1atXjggQdi+PDhUVRUFEcddVRe26lTp8bQoUPjiCOOiMMOOyw6deoUCxYsiH79+sVHH30Uxx57bLRs2TJuuummZd4n/Msvv4wBAwbEXnvtFUOGDIk777wzTj755OjevXsMHDgwIn48QNh9993jueeei8MPPzy6dOkSkydPjssuuyzee++9uPfeeyPix3vf7bbbbtGjR48466yzokaNGvH+++/nFY3rr78+jj3
|
|||
|
"text/plain": [
|
|||
|
"<Figure size 1500x600 with 3 Axes>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Выбираем столбцы для очистки\n",
|
|||
|
"columns_to_clean = ['Hardness', 'Solids', 'Organic_carbon']\n",
|
|||
|
"\n",
|
|||
|
"# Функция для удаления выбросов\n",
|
|||
|
"def remove_outliers(df, columns):\n",
|
|||
|
" for col in columns:\n",
|
|||
|
" Q1 = df[col].quantile(0.25)\n",
|
|||
|
" Q3 = df[col].quantile(0.75)\n",
|
|||
|
" IQR = Q3 - Q1\n",
|
|||
|
" lower_bound = Q1 - 1.5 * IQR\n",
|
|||
|
" upper_bound = Q3 + 1.5 * IQR\n",
|
|||
|
" \n",
|
|||
|
" # Удаляем строки, содержащие выбросы\n",
|
|||
|
" df = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)]\n",
|
|||
|
" \n",
|
|||
|
" return df\n",
|
|||
|
"\n",
|
|||
|
"# Удаляем выбросы\n",
|
|||
|
"df_cleaned = remove_outliers(df, columns_to_clean)\n",
|
|||
|
"\n",
|
|||
|
"# Выводим количество удаленных строк\n",
|
|||
|
"print(f\"Количество удаленных строк: {len(df) - len(df_cleaned)}\")\n",
|
|||
|
"\n",
|
|||
|
"# Создаем диаграммы размаха для очищенных данных\n",
|
|||
|
"plt.figure(figsize=(15, 6))\n",
|
|||
|
"\n",
|
|||
|
"# Диаграмма размаха для Hardness\n",
|
|||
|
"plt.subplot(1, 3, 1)\n",
|
|||
|
"sns.boxplot(x=df_cleaned['Hardness'])\n",
|
|||
|
"plt.title('Box Plot of Hardness (Cleaned)')\n",
|
|||
|
"plt.xlabel('Hardness')\n",
|
|||
|
"\n",
|
|||
|
"# Диаграмма размаха для Solids\n",
|
|||
|
"plt.subplot(1, 3, 2)\n",
|
|||
|
"sns.boxplot(x=df_cleaned['Solids'])\n",
|
|||
|
"plt.title('Box Plot of Solids (Cleaned)')\n",
|
|||
|
"plt.xlabel('Solids')\n",
|
|||
|
"\n",
|
|||
|
"# Диаграмма размаха для Organic_carbon\n",
|
|||
|
"plt.subplot(1, 3, 3)\n",
|
|||
|
"sns.boxplot(x=df_cleaned['Organic_carbon'])\n",
|
|||
|
"plt.title('Box Plot of Organic_carbon (Cleaned)')\n",
|
|||
|
"plt.xlabel('Organic_carbon')\n",
|
|||
|
"\n",
|
|||
|
"plt.tight_layout()\n",
|
|||
|
"plt.show()\n",
|
|||
|
"\n",
|
|||
|
"# Сохраняем очищенный датасет\n",
|
|||
|
"df_cleaned.to_csv(\"..//..//static//csv//water_potability_cleaned.csv\", index=False)\n",
|
|||
|
"df = df_cleaned"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Количество выбросов уменьшилось.\n",
|
|||
|
"\n",
|
|||
|
"### Теперь проверим на пустые значения"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 542,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"ph 466\n",
|
|||
|
"Hardness 0\n",
|
|||
|
"Solids 0\n",
|
|||
|
"Chloramines 0\n",
|
|||
|
"Sulfate 746\n",
|
|||
|
"Conductivity 0\n",
|
|||
|
"Organic_carbon 0\n",
|
|||
|
"Trihalomethanes 154\n",
|
|||
|
"Turbidity 0\n",
|
|||
|
"Potability 0\n",
|
|||
|
"dtype: int64\n",
|
|||
|
"\n",
|
|||
|
"ph True\n",
|
|||
|
"Hardness False\n",
|
|||
|
"Solids False\n",
|
|||
|
"Chloramines False\n",
|
|||
|
"Sulfate True\n",
|
|||
|
"Conductivity False\n",
|
|||
|
"Organic_carbon False\n",
|
|||
|
"Trihalomethanes True\n",
|
|||
|
"Turbidity False\n",
|
|||
|
"Potability False\n",
|
|||
|
"dtype: bool\n",
|
|||
|
"\n",
|
|||
|
"ph процент пустых значений: %14.88\n",
|
|||
|
"Sulfate процент пустых значений: %23.83\n",
|
|||
|
"Trihalomethanes процент пустых значений: %4.92\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Количество пустых значений признаков\n",
|
|||
|
"print(df.isnull().sum())\n",
|
|||
|
"\n",
|
|||
|
"print()\n",
|
|||
|
"\n",
|
|||
|
"# Есть ли пустые значения признаков\n",
|
|||
|
"print(df.isnull().any())\n",
|
|||
|
"\n",
|
|||
|
"print()\n",
|
|||
|
"\n",
|
|||
|
"# Процент пустых значений признаков\n",
|
|||
|
"for i in df.columns:\n",
|
|||
|
" null_rate = df[i].isnull().sum() / len(df) * 100\n",
|
|||
|
" if null_rate > 0:\n",
|
|||
|
" print(f\"{i} процент пустых значений: %{null_rate:.2f}\")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"В трех столбцах встречается большое число пустых значений. Поэтому вместо удаления заменим их значения на медиану."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 543,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"\n",
|
|||
|
"Количество пустых значений в каждом столбце после замены:\n",
|
|||
|
"ph 0\n",
|
|||
|
"Hardness 0\n",
|
|||
|
"Solids 0\n",
|
|||
|
"Chloramines 0\n",
|
|||
|
"Sulfate 0\n",
|
|||
|
"Conductivity 0\n",
|
|||
|
"Organic_carbon 0\n",
|
|||
|
"Trihalomethanes 0\n",
|
|||
|
"Turbidity 0\n",
|
|||
|
"Potability 0\n",
|
|||
|
"dtype: int64\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Замена значений\n",
|
|||
|
"df[\"ph\"] = df[\"ph\"].fillna(df[\"ph\"].median())\n",
|
|||
|
"df[\"Sulfate\"] = df[\"Sulfate\"].fillna(df[\"Sulfate\"].median())\n",
|
|||
|
"df[\"Trihalomethanes\"] = df[\"Trihalomethanes\"].fillna(df[\"Trihalomethanes\"].median())\n",
|
|||
|
"\n",
|
|||
|
"# Проверка на пропущенные значения после замены\n",
|
|||
|
"missing_values_after_drop = df.isnull().sum()\n",
|
|||
|
"\n",
|
|||
|
"# Вывод результатов после замены\n",
|
|||
|
"print(\"\\nКоличество пустых значений в каждом столбце после замены:\")\n",
|
|||
|
"print(missing_values_after_drop)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Пустых значений в датасете теперь нет.\n",
|
|||
|
"\n",
|
|||
|
"### Можно перейти к созданию выборок"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 544,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Размер обучающей выборки: (1878, 9)\n",
|
|||
|
"Размер контрольной выборки: (626, 9)\n",
|
|||
|
"Размер тестовой выборки: (627, 9)\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Разделение на признаки (X) и целевую переменную (y)\n",
|
|||
|
"# Предположим, что Potability - это целевая переменная\n",
|
|||
|
"X = df.drop('Potability', axis=1)\n",
|
|||
|
"y = df['Potability']\n",
|
|||
|
"\n",
|
|||
|
"# Разбиение на обучающую и остальную выборку (контрольную + тестовую)\n",
|
|||
|
"X_train, X_rem, y_train, y_rem = train_test_split(X, y, train_size=0.6, random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"# Разбиение остатка на контрольную и тестовую выборки\n",
|
|||
|
"X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, test_size=0.5, random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"# Вывод размеров выборок\n",
|
|||
|
"print(\"Размер обучающей выборки:\", X_train.shape)\n",
|
|||
|
"print(\"Размер контрольной выборки:\", X_val.shape)\n",
|
|||
|
"print(\"Размер тестовой выборки:\", X_test.shape)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 545,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Распределение классов в обучающей выборке:\n",
|
|||
|
"Potability\n",
|
|||
|
"0 0.613951\n",
|
|||
|
"1 0.386049\n",
|
|||
|
"Name: proportion, dtype: float64\n",
|
|||
|
"\n",
|
|||
|
"Распределение классов в контрольной выборке:\n",
|
|||
|
"Potability\n",
|
|||
|
"0 0.616613\n",
|
|||
|
"1 0.383387\n",
|
|||
|
"Name: proportion, dtype: float64\n",
|
|||
|
"\n",
|
|||
|
"Распределение классов в тестовой выборке:\n",
|
|||
|
"Potability\n",
|
|||
|
"0 0.614035\n",
|
|||
|
"1 0.385965\n",
|
|||
|
"Name: proportion, dtype: float64\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Функция для анализа сбалансированности\n",
|
|||
|
"def analyze_balance(y_train, y_val, y_test):\n",
|
|||
|
" print(\"Распределение классов в обучающей выборке:\")\n",
|
|||
|
" print(y_train.value_counts(normalize=True))\n",
|
|||
|
" \n",
|
|||
|
" print(\"\\nРаспределение классов в контрольной выборке:\")\n",
|
|||
|
" print(y_val.value_counts(normalize=True))\n",
|
|||
|
" \n",
|
|||
|
" print(\"\\nРаспределение классов в тестовой выборке:\")\n",
|
|||
|
" print(y_test.value_counts(normalize=True))\n",
|
|||
|
"\n",
|
|||
|
"# Анализ сбалансированности\n",
|
|||
|
"analyze_balance(y_train, y_val, y_test)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Такие выборки сложно назвать сбалансированными. Сделаем приращение данных методом выборки с избытком (oversampling)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 546,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Сбалансированность обучающей выборки после SMOTE:\n",
|
|||
|
"Potability\n",
|
|||
|
"1 0.5\n",
|
|||
|
"0 0.5\n",
|
|||
|
"Name: proportion, dtype: float64\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"smote = SMOTE(random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"# Применение SMOTE для балансировки обучающей выборки\n",
|
|||
|
"X_train_resampled, y_train_resampled = smote.fit_resample(X_train, y_train)\n",
|
|||
|
"\n",
|
|||
|
"# Проверка сбалансированности после SMOTE\n",
|
|||
|
"print(\"Сбалансированность обучающей выборки после SMOTE:\")\n",
|
|||
|
"print(y_train_resampled.value_counts(normalize=True))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Можно увидеть, что выборка была успешно сбалансирована."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"## Датасет №3 (данные о диабете) \n",
|
|||
|
"\n",
|
|||
|
"Ссылка: https://www.kaggle.com/datasets/akshaydattatraykhare/diabetes-dataset\n",
|
|||
|
"\n",
|
|||
|
"Проблемная область: диагностика диабета и выявление факторов, влияющих на риск его возникновения.\n",
|
|||
|
"\n",
|
|||
|
"Объекты наблюдения: женщины в возрасте от 21 года из группы индейцев племени Пима."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 547,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Index(['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin',\n",
|
|||
|
" 'BMI', 'DiabetesPedigreeFunction', 'Age', 'Outcome'],\n",
|
|||
|
" dtype='object')\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"import pandas as pd\n",
|
|||
|
"import matplotlib.pyplot as plt\n",
|
|||
|
"import seaborn as sns\n",
|
|||
|
"from sklearn.model_selection import train_test_split\n",
|
|||
|
"from imblearn.under_sampling import RandomUnderSampler\n",
|
|||
|
"\n",
|
|||
|
"# вывод всех столбцов\n",
|
|||
|
"df = pd.read_csv(\"..//..//static//csv//diabetes.csv\")\n",
|
|||
|
"print(df.columns)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Атрибуты: \n",
|
|||
|
"* Pregnancies – количество беременностей у пациентки;\n",
|
|||
|
"* Glucose – уровень глюкозы в крови;\n",
|
|||
|
"* BloodPressure – артериальное давление;\n",
|
|||
|
"* SkinThickness – толщина кожи;\n",
|
|||
|
"* Insulin – уровень инсулина в крови;\n",
|
|||
|
"* BMI – индекс массы тела (Body Mass Index);\n",
|
|||
|
"* DiabetesPedigreeFunction – вероятность наследственной предрасположенности к диабету;\n",
|
|||
|
"* Age – возраст пациентки;\n",
|
|||
|
"* Outcome – признак, показывающий, диагностирован ли диабет (1 – да, 0 – нет).\n",
|
|||
|
"\n",
|
|||
|
"Примеры бизнес целей и целей технического проекта:\n",
|
|||
|
"1. Разработка программ ранней диагностики диабета.\n",
|
|||
|
" * Бизнес-цель: создание системы раннего выявления пациентов с высоким риском диабета для снижения затрат на лечение и улучшения прогноза.\n",
|
|||
|
" * Цель технического проекта: создание алгоритмов машинного обучения для предсказания вероятности заболевания на основе медицинских данных.\n",
|
|||
|
"2. Оптимизация медицинского мониторинга пациентов.\n",
|
|||
|
" * Бизнес-цель: эффективное распределение ресурсов здравоохранения за счет фокусирования на группах риска.\n",
|
|||
|
" * Цель технического проекта: разработка платформы для интеграции медицинских данных, которая позволит отслеживать ключевые показатели здоровья и предсказывать осложнения.\n",
|
|||
|
"3. Повышение осведомленности о факторах риска диабета среди населения.\n",
|
|||
|
" * Бизнес-цель: внедрение образовательных кампаний, направленных на изменение образа жизни с целью профилактики диабета.\n",
|
|||
|
" * Цель технического проекта: создание системы оповещения пациентов с рекомендациями на основе их медицинских показателей.\n",
|
|||
|
"\n",
|
|||
|
"Входные данные и целевой признак могут быть следующими:\n",
|
|||
|
"1. Входные данные:\n",
|
|||
|
" * количество беременностей;\n",
|
|||
|
" * уровень глюкозы в крови;\n",
|
|||
|
" * артериальное давление;\n",
|
|||
|
" * толщина кожи;\n",
|
|||
|
" * уровень инсулина в крови;\n",
|
|||
|
" * индекс массы тела;\n",
|
|||
|
" * вероятность наследственной предрасположенности к диабету;\n",
|
|||
|
" * возраст.\n",
|
|||
|
"2. Целевой признак:\n",
|
|||
|
" * Диагностика диабета (1 – да, 0 – нет).\n",
|
|||
|
"\n",
|
|||
|
"Актуальность: анализ медицинских данных для ранней диагностики диабета играет ключевую роль в профилактике этого заболевания и управлении им. Выявление факторов риска позволяет принимать превентивные меры, снижая вероятность осложнений и улучшая качество жизни пациентов.\n",
|
|||
|
"\n",
|
|||
|
"### Проверяем на выбросы"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 548,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Количество выбросов в столбце 'Age': 9\n",
|
|||
|
"Количество выбросов в столбце 'BloodPressure': 45\n",
|
|||
|
"Количество выбросов в столбце 'BMI': 19\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABdIAAAPeCAYAAAAI5OjmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABxnUlEQVR4nOzdeZyd4/0//tdkH5FFREiEiDWKoLZG7HvE1to+SiVEqaV2xSfWNqpqqypCq6KVUkHtW9T2QVo7tdQaCUJC00RERGTu3x++OT8jcZuJJDOTPJ+PxzySc9/Xuc773Nfc51z3a+5zn6qiKIoAAAAAAABz1KyhCwAAAAAAgMZMkA4AAAAAACUE6QAAAAAAUEKQDgAAAAAAJQTpAAAAAABQQpAOAAAAAAAlBOkAAAAAAFBCkA4AAAAAACUE6QAAAAAAUEKQDtBIvfXWW6mqqsqwYcMaupRa7r777qyzzjpp06ZNqqqqMmnSpIYuCQCAJmhRm+9WVVXljDPOmCd91ceDDz6YqqqqPPjggwv8sQEWJoJ0YKE3bNiwVFVV1frp0qVLttxyy9x1110LvJ5ZE9lZPy1btsyKK66Y/fffP2+++eY8eYzHHnssZ5xxxjwPuf/zn/9kr732SnV1dS655JL8+c9/Ttu2bb/xfpdeemmqqqqy0UYbzdN6AAAw352X6jPfbWzbvT4GDhxYq+727dtn7bXXzvnnn5/p06c3dHkAjVKLhi4AYEH5+c9/np49e6YoiowfPz7Dhg3LjjvumNtuuy077bTTAq/nyCOPzAYbbJAZM2bk6aefzhVXXJE77rgj//rXv9KtW7dv1fdjjz2WM888MwMHDkzHjh3nTcFJnnjiiUyZMiW/+MUvss0229T5fsOHD88KK6yQxx9/PK+//npWXnnleVYTAABfMN/99uZmvtvYtntdtW7dOn/4wx+SJJMmTcqNN96Y448/Pk888USuu+66Bq4OoPERpAOLjH79+mX99dev3B40aFCWXnrpXHvttQ0ywd10002zxx57JEkOOOCArLrqqjnyyCNz9dVX5+STT17g9dTFhAkTkqReByujR4/OY489lptuuimHHHJIhg8fntNPP30+VQgAsOgy3/325ma+29i2e121aNEi++23X+X2YYcdlo022ih//etfc8EFF8zxjx1FUeTTTz9NdXX1giz1W/n8889TU1OTVq1aNXQpQBPn0i7AIqtjx46prq5Oixa1/6Y4derUHHfccVluueXSunXrrLbaajnvvPNSFEWSZNq0aenVq1d69eqVadOmVe43ceLEdO3aNRtvvHFmzpxZ73q22mqrJF8Ez2Xuv//+bLrppmnbtm06duyYXXfdNS+//HJl/RlnnJETTjghSdKzZ8/KxzXfeuut0n5HjBiR9dZbL9XV1encuXP222+/vPvuu5X1W2yxRQYMGJAk2WCDDVJVVZWBAwd+4/MaPnx4llhiifTv3z977LFHhg8fPsd2//nPf/KjH/0o7du3T8eOHTNgwIA899xzc7xu5r///e/sscce6dSpU9q0aZP1118/t9566zfWAgCwKDHfrW1+zXe/6uu2+5w888wz6devX9q3b5/FF188W2+9df7xj3/M1u7NN9/MnnvumU6dOmWxxRbL9773vdxxxx2ztXvnnXey2267pW3btunSpUuOOeaYOl+qpVmzZtliiy2SpLItV1hhhey000655557sv7666e6ujqXX355ki/OYj/66KMrv0crr7xyzjnnnNTU1NTq97rrrst6662Xdu3apX379llrrbVy0UUXVdbPmDEjZ555ZlZZZZW0adMmSy65ZDbZZJOMHDmy0maLLbao1PZlAwcOzAorrFC5Peu6++edd15+85vfZKWVVkrr1q3z0ksvJXEcAXw7zkgHFhmTJ0/Ohx9+mKIoMmHChFx88cX5+OOPa52FURRFdtlllzzwwAMZNGhQ1llnndxzzz054YQT8u677+bCCy9MdXV1rr766vTt2zeDBw/OBRdckCQ5/PDDM3ny5AwbNizNmzevd31vvPFGkmTJJZf82jb33Xdf+vXrlxVXXDFnnHFGpk2blosvvjh9+/bN008/nRVWWCE/+MEP8uqrr+baa6/NhRdemM6dOydJllpqqa/td9iwYTnggAOywQYb5Oyzz8748eNz0UUX5dFHH80zzzyTjh07ZvDgwVlttdVyxRVXVD6+utJKK33j8xo+fHh+8IMfpFWrVtlnn31y2WWX5YknnsgGG2xQaVNTU5Odd945jz/+eA499ND06tUrt9xyS+VA5stefPHF9O3bN8suu2xOOumktG3bNtdff31222233Hjjjfn+97//jTUBACyMzHcbZr5bl+0+Jy+++GI23XTTtG/fPj/72c/SsmXLXH755dliiy3y0EMPVb5faPz48dl4443zySef5Mgjj8ySSy6Zq6++OrvssktuuOGGyvx32rRp2XrrrTN27NgceeSR6datW/785z/n/vvv/8bnMMucxuiVV17JPvvsk0MOOSQ//vGPs9pqq+WTTz7J5ptvnnfffTeHHHJIll9++Tz22GM5+eST89577+U3v/lNkmTkyJHZZ599svXWW+ecc85Jkrz88st59NFHc9RRRyX54g8jZ599dg466KBsuOGG+eijj/Lkk0/m6aefzrbbblvn2r/sqquuyqeffpqDDz44rVu3TqdOnRxHAN9eAbCQu+qqq4oks/20bt26GDZsWK22N998c5GkGDJkSK3le+yxR1FVVVW8/vrrlWUnn3xy0axZs+Lhhx8uRowYUSQpfvOb33xjPQ888ECRpPjjH/9YfPDBB8W4ceOKO+64o1hhhRWKqqqq4oknniiKoihGjx5dJCmuuuqqyn3XWWedokuXLsV//vOfyrLnnnuuaNasWbH//vtXlp177rlFkmL06NHfWM9nn31WdOnSpVhzzTWLadOmVZbffvvtRZLitNNOqyybtS1n1fhNnnzyySJJMXLkyKIoiqKmpqbo3r17cdRRR9Vqd+ONN862/WbOnFlstdVWs22DrbfeulhrrbWKTz/9tLKspqam2HjjjYtVVlmlTnUBACxMzHfLza/5bn22e1EURZLi9NNPr9zebbfdilatWhVvvPFGZdm4ceOKdu3aFZtttlll2dFHH10kKf7v//6vsmzKlClFz549ixVWWKGYOXNmURRF8Zvf/KZIUlx//fWVdlOnTi1WXnnlIknxwAMPVJYPGDCgaNu2bfHBBx8UH3zwQfH6668Xv/zlL4uqqqqid+/elXY9evQokhR33313refyi1/8omjbtm3x6quv1lp+0kknFc2bNy/Gjh1bFEVRHHXUUUX79u2Lzz///Gu349prr13079//a9cXRVFsvvnmxeabbz7b8gEDBhQ9evSo3J71O9W+fftiwoQJtdo6jgC+LZd2ARYZl1xySUaOHJmRI0fmmmuuyZZbbpmDDjooN910U6XNnXfemebNm+fII4+sdd/jjjsuRVHkrrvuqiw744wzssYaa2TAgAE57LDDsvnmm892vzIHHnhgllpqqXTr1i39+/fP1KlTc/XVV9e6vuKXvffee3n22WczcODAdOrUqbK8d+/e2XbbbXPnnXfW+bG/7Mknn8yECRNy2GGHpU2bNpXl/fv3T69eveb4kdG6Gj58eJZeeulsueWWSZKqqqrsvffeue6662p9HPjuu+9Oy5Yt8+Mf/7iyrFmzZjn88MNr9Tdx4sTcf//92WuvvTJlypR8+OGH+fDDD/Of//wn22+/fV577bVaH88FAFiUmO/O2fyc7yZ12+5fNXPmzNx7773ZbbfdsuKKK1aWd+3aNT/84Q/zyCOP5KOPPkryxZhtuOGG2WSTTSrtFl988Rx88MF56623KpctufPOO9O1a9fKdemTZLHFFsvBBx88xxqmTp2apZZaKksttVRWXnnl/O///m/69OmTv/3tb7Xa9ezZM9tvv32tZSNGjMimm26aJZZYojIn//DDD7PNNttk5syZefjhh5N8cZmbqVOn1rpMy1d17NgxL774Yl577bWvbVNfu+++e61PKDiOAOYFl3YBFhk
|
|||
|
"text/plain": [
|
|||
|
"<Figure size 1500x1000 with 3 Axes>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Выбираем столбцы для анализа\n",
|
|||
|
"columns_to_check = ['Age', 'BloodPressure', 'BMI']\n",
|
|||
|
"\n",
|
|||
|
"# Функция для подсчета выбросов\n",
|
|||
|
"def count_outliers(df, columns):\n",
|
|||
|
" outliers_count = {}\n",
|
|||
|
" for col in columns:\n",
|
|||
|
" Q1 = df[col].quantile(0.25)\n",
|
|||
|
" Q3 = df[col].quantile(0.75)\n",
|
|||
|
" IQR = Q3 - Q1\n",
|
|||
|
" lower_bound = Q1 - 1.5 * IQR\n",
|
|||
|
" upper_bound = Q3 + 1.5 * IQR\n",
|
|||
|
" \n",
|
|||
|
" # Считаем количество выбросов\n",
|
|||
|
" outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)]\n",
|
|||
|
" outliers_count[col] = len(outliers)\n",
|
|||
|
" \n",
|
|||
|
" return outliers_count\n",
|
|||
|
"\n",
|
|||
|
"# Подсчитываем выбросы\n",
|
|||
|
"outliers_count = count_outliers(df, columns_to_check)\n",
|
|||
|
"\n",
|
|||
|
"# Выводим количество выбросов для каждого столбца\n",
|
|||
|
"for col, count in outliers_count.items():\n",
|
|||
|
" print(f\"Количество выбросов в столбце '{col}': {count}\")\n",
|
|||
|
"\n",
|
|||
|
"# Создаем диаграммы размахов\n",
|
|||
|
"plt.figure(figsize=(15, 10))\n",
|
|||
|
"for i, col in enumerate(columns_to_check, 1):\n",
|
|||
|
" plt.subplot(2, 2, i)\n",
|
|||
|
" sns.boxplot(x=df[col])\n",
|
|||
|
" plt.title(f'Box Plot of {col}')\n",
|
|||
|
"plt.tight_layout()\n",
|
|||
|
"plt.show()"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"В каждом из выбранных столбцов присутствуют выбросы. Очистим их."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 549,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Количество удаленных строк: 61\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABdIAAAJOCAYAAACz9fURAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABY+klEQVR4nO3dd5gV5fk//nsX2EIvgjRBioJBbFiCKGhQFBH1Y/3aAioRRYMtKkoUG2IvsYGxYBQxgjUKKjYMaGJFjRUURUXRiCBdYOf3h7898bDLUGRZ2H29rmsv3Zk5c+55ZpjnmffOmZOTJEkSAAAAAABAqXLLuwAAAAAAANiQCdIBAAAAACCFIB0AAAAAAFII0gEAAAAAIIUgHQAAAAAAUgjSAQAAAAAghSAdAAAAAABSCNIBAAAAACCFIB0AAAAAAFII0qn0Pvvss8jJyYmRI0eWdylZnnrqqdhuu+2ioKAgcnJyYs6cOeVd0hr74osvoqCgICZPnrxWr99Q983auuiiiyInJyfz+9KlS2OzzTaLW2+9tRyrAvjZhnrOLav+MCcnJy666KJ1sq418eKLL0ZOTk68+OKL6/29KxrjjGzGGcCGbkM9727s194DBgyIvffee61f37dv39h8883XXUHlbMUx3vDhw6NFixaxZMmS8iuKCkOQzjozcuTIyMnJyfpp1KhR7LnnnjF+/Pj1Xk/xhWrxT7Vq1aJ169bx+9//Pj799NN18h4vv/xyXHTRReu8o/3+++/j8MMPj8LCwrjlllvi3nvvjRo1aqzydbfeemvk5OTELrvssk7rWVuXXHJJ7LLLLtGlS5cS81588cU4+OCDo3HjxpGXlxeNGjWK3r17x8MPP1wOlZaPatWqxZlnnhlDhw6NxYsXl3c5wDqiP1x31qQ/3NDafU307ds3q+7atWvHtttuG9dee62LvhTGGemMM6Di2tD6PGON0tu9eJl+/fqVur7Bgwdnlvnvf/+bmd63b9+oWbPmatU/ffr0uOOOO+L8888vMe/HH3+Miy++OLbddtuoWbNmFBYWxtZbbx3nnntuzJw5c7XWXxH07ds3fvrppxgxYkR5l0IFULW8C6DiueSSS6JVq1aRJEnMmjUrRo4cGfvtt1/84x//iP3333+91zNw4MDYaaedYunSpfHmm2/G7bffHk8++WS8++670bRp01+17pdffjkuvvji6Nu3b9StW3fdFBwRr732WsybNy8uvfTS2GuvvVb7daNGjYrNN988Xn311Zg2bVq0bdt2ndW0pr777ru455574p577ikxb8iQIXHJJZfEFltsEf3794+WLVvG999/H+PGjYtDDjkkRo0aFUcddVQ5VL3+HXfccTFo0KC4//774/jjjy/vcoB1SH/4661Nf7ihtfvqys/PjzvuuCMiIubMmRMPPfRQ/OlPf4rXXnstHnjggXKubsNjnLF6jDOgYtvQ+jxjjZLtXlBQEA899FDceuutkZeXlzVv9OjRUVBQ8Kv+2HnjjTdGq1atYs8998ya/umnn8Zee+0VM2bMiMMOOyxOPPHEyMvLi3feeSfuvPPOeOSRR+Ljjz9e6/fdmBQUFESfPn3iuuuuiz/+8Y9Zn96CNSVIZ53r2bNn7LjjjpnfTzjhhNh0001j9OjR5dKZ77777nHooYdGxM8XE1tuuWUMHDgw7rnnnjjvvPPWez2r49tvv42IWKMBwvTp0+Pll1+Ohx9+OPr37x+jRo2KIUOGlFGFq3bfffdF1apVo3fv3lnTx44dG5dcckkceuihcf/990e1atUy884+++x4+umnY+nSpeu73HJTt27d6NGjR4wcOdIFLlQw+sNfb236ww2t3VdX1apV45hjjsn8PmDAgNhll13i73//e1x33XWlBhBJksTixYujsLBwfZb6qyxbtiyKiopKhAlryjhj9RhnQMW2ofV5xhol233fffeNxx9/PMaPHx8HHnhgZvrLL78c06dPj0MOOSQeeuihtap96dKlMWrUqDjppJOypi9btiwOPvjgmDVrVrz44oux2267Zc0fOnRoXHnllWv1nhurww8/PK666qp44YUX4ne/+115l8NGzKNdKHN169aNwsLCqFo1++82CxYsiLPOOis222yzyM/Pj3bt2sU111wTSZJERMSiRYuiffv20b59+1i0aFHmdbNnz44mTZrErrvuGsuXL1/jeopPmtOnT09d7vnnn4/dd989atSoEXXr1o0DDzwwPvjgg8z8iy66KM4+++yIiGjVqlXmI1mfffZZ6nrHjBkTnTp1isLCwthkk03imGOOia+++iozf4899og+ffpERMROO+0UOTk50bdv31Vu16hRo6JevXrRq1evOPTQQ2PUqFGlLvf999/HscceG7Vr1466detGnz594u233y71WXUffvhhHHrooVG/fv0oKCiIHXfcMR5//PFV1hIR8eijj8Yuu+xS4iNpF1xwQdSvXz/uuuuurIvbYvvss88qB32rU9fs2bPjT3/6U3Ts2DFq1qwZtWvXjp49e8bbb7+dtVzxxxAffPDBGDp0aDRv3jwKCgqie/fuMW3atBLv/e9//zv23XffqFOnTlSvXj26detW6rNZJ02aFDvttFMUFBREmzZtUj9Gtvfee8ekSZNi9uzZqdsNbNz0h9nKqj9c0cravTRvvfVW9OzZM2rXrh01a9aM7t27x7/+9a8Sy3366adx2GGHRf369aN69erx29/+Np588skSy3355Zdx0EEHRY0aNaJRo0ZxxhlnrPajWnJzc2OPPfaIiMi05eabbx77779/PP3007HjjjtGYWFhpn+ZM2dOnH766ZnjqG3btnHllVdGUVFR1nofeOCB6NSpU9SqVStq164dHTt2jBtvvDEzf+nSpXHxxRfHFltsEQUFBdGgQYPYbbfdYsKECZll9thjj0xtv7TiM1aLn4V7zTXXxA033BBt2rSJ/Pz8eP/99yPCOMM4A1jXjDWybQhjjWbNmkXXrl3j/vvvz5o+atSo6NixY2y99dZr/H7FJk2aFP/9739L3En/0EMPxdtvvx2DBw8uEaJHRNSuXTuGDh2auu6ioqK44YYbokOHDlFQUBCbbrpp9O/fP3744Yes5R577LHo1atXNG3aNPLz86NNmzZx6aWXljhe9thjj9h6663j/fffjz333DOqV68ezZo1i6uuuqrEey9ZsiSGDBkSbdu2jfz8/Nhss83inHPOKTGGWrJkSZxxxhnRsGHDqFWrVhxwwAHx5Zdflro9nTp1ivr168djjz2Wut2wKu5IZ52bO3du/Pe//40kSeLbb7+Nm266KebPn591l1WSJHHAAQfECy+8ECeccEJst9128fTTT8fZZ58dX331VVx//fVRWFgY99xzT3Tp0iUGDx4c1113XUREnHLKKTF37twYOXJkVKlSZY3r++STTyIiokGDBitd5tlnn42ePXtG69at46KLLopFixbFTTfdFF26dIk333wzNt988zj44IPj448/jtGjR8f1118fm2yySURENGzYcKXrHTlyZBx33HGx0047xbBhw2LWrFlx4403xuTJk+Ott96KunXrxuDBg6Ndu3Zx++23Zz4y1qZNm1Vu16hRo+Lggw+OvLy8OPLII+O2226L1157LXbaaafMMkVFRdG7d+949dVX4+STT4727dvHY489lhk8/NJ7770XXbp0iWbNmsWgQYOiRo0a8eCDD8ZBBx0UDz30UPzf//3fSmtZunRpvPbaa3HyySdnTZ86dWp8+OGHcfzxx0etWrVWuU2lWd26Pv3003j00UfjsMMOi1atWsWsWbNixIgR0a1bt3j//fdL3Nl3xRVXRG5ubvzpT3+KuXPnxlVXXRVHH310/Pvf/84s8/zzz0fPnj2jU6dOMWTIkMjNzY277747fve738U///nP2HnnnSMi4t13340ePXpEw4YN46KLLoply5bFkCFDYtNNNy11mzp16hRJksTLL7+8Qd8tCawZ/WH59Ier0+6lee+992L33XeP2rVrxznnnBPVqlWLESNGxB577BETJ07MfP/IrFmzYtddd42FCxfGwIEDo0GDBnH
|
|||
|
"text/plain": [
|
|||
|
"<Figure size 1500x600 with 3 Axes>"
|
|||
|
]
|
|||
|
},
|
|||
|
"metadata": {},
|
|||
|
"output_type": "display_data"
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Выбираем столбцы для очистки\n",
|
|||
|
"columns_to_clean = ['Age', 'BloodPressure', 'BMI']\n",
|
|||
|
"\n",
|
|||
|
"# Функция для удаления выбросов\n",
|
|||
|
"def remove_outliers(df, columns):\n",
|
|||
|
" for col in columns:\n",
|
|||
|
" Q1 = df[col].quantile(0.25)\n",
|
|||
|
" Q3 = df[col].quantile(0.75)\n",
|
|||
|
" IQR = Q3 - Q1\n",
|
|||
|
" lower_bound = Q1 - 1.5 * IQR\n",
|
|||
|
" upper_bound = Q3 + 1.5 * IQR\n",
|
|||
|
" \n",
|
|||
|
" # Удаляем строки, содержащие выбросы\n",
|
|||
|
" df = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)]\n",
|
|||
|
" \n",
|
|||
|
" return df\n",
|
|||
|
"\n",
|
|||
|
"# Удаляем выбросы\n",
|
|||
|
"df_cleaned = remove_outliers(df, columns_to_clean)\n",
|
|||
|
"\n",
|
|||
|
"# Выводим количество удаленных строк\n",
|
|||
|
"print(f\"Количество удаленных строк: {len(df) - len(df_cleaned)}\")\n",
|
|||
|
"\n",
|
|||
|
"# Создаем диаграммы размаха для очищенных данных\n",
|
|||
|
"plt.figure(figsize=(15, 6))\n",
|
|||
|
"\n",
|
|||
|
"# Диаграмма размаха для Age\n",
|
|||
|
"plt.subplot(1, 3, 1)\n",
|
|||
|
"sns.boxplot(x=df_cleaned['Age'])\n",
|
|||
|
"plt.title('Box Plot of Age (Cleaned)')\n",
|
|||
|
"plt.xlabel('Age')\n",
|
|||
|
"\n",
|
|||
|
"# Диаграмма размаха для BloodPressure\n",
|
|||
|
"plt.subplot(1, 3, 2)\n",
|
|||
|
"sns.boxplot(x=df_cleaned['BloodPressure'])\n",
|
|||
|
"plt.title('Box Plot of BloodPressure (Cleaned)')\n",
|
|||
|
"plt.xlabel('BloodPressure')\n",
|
|||
|
"\n",
|
|||
|
"# Диаграмма размаха для BMI\n",
|
|||
|
"plt.subplot(1, 3, 3)\n",
|
|||
|
"sns.boxplot(x=df_cleaned['BMI'])\n",
|
|||
|
"plt.title('Box Plot of BMI (Cleaned)')\n",
|
|||
|
"plt.xlabel('BMI')\n",
|
|||
|
"\n",
|
|||
|
"plt.tight_layout()\n",
|
|||
|
"plt.show()\n",
|
|||
|
"\n",
|
|||
|
"# Сохраняем очищенный датасет\n",
|
|||
|
"df_cleaned.to_csv(\"..//..//static//csv//diabetes_cleaned.csv\", index=False)\n",
|
|||
|
"df = df_cleaned"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Количество выбросов уменьшилось.\n",
|
|||
|
"\n",
|
|||
|
"### Теперь проверим на пустые значения"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 550,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Pregnancies 0\n",
|
|||
|
"Glucose 0\n",
|
|||
|
"BloodPressure 0\n",
|
|||
|
"SkinThickness 0\n",
|
|||
|
"Insulin 0\n",
|
|||
|
"BMI 0\n",
|
|||
|
"DiabetesPedigreeFunction 0\n",
|
|||
|
"Age 0\n",
|
|||
|
"Outcome 0\n",
|
|||
|
"dtype: int64\n",
|
|||
|
"\n",
|
|||
|
"Pregnancies False\n",
|
|||
|
"Glucose False\n",
|
|||
|
"BloodPressure False\n",
|
|||
|
"SkinThickness False\n",
|
|||
|
"Insulin False\n",
|
|||
|
"BMI False\n",
|
|||
|
"DiabetesPedigreeFunction False\n",
|
|||
|
"Age False\n",
|
|||
|
"Outcome False\n",
|
|||
|
"dtype: bool\n",
|
|||
|
"\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Количество пустых значений признаков\n",
|
|||
|
"print(df.isnull().sum())\n",
|
|||
|
"\n",
|
|||
|
"print()\n",
|
|||
|
"\n",
|
|||
|
"# Есть ли пустые значения признаков\n",
|
|||
|
"print(df.isnull().any())\n",
|
|||
|
"\n",
|
|||
|
"print()\n",
|
|||
|
"\n",
|
|||
|
"# Процент пустых значений признаков\n",
|
|||
|
"for i in df.columns:\n",
|
|||
|
" null_rate = df[i].isnull().sum() / len(df) * 100\n",
|
|||
|
" if null_rate > 0:\n",
|
|||
|
" print(f\"{i} процент пустых значений: %{null_rate:.2f}\")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Пустых значений в датасете нет. \n",
|
|||
|
"\n",
|
|||
|
"### Можно перейти к созданию выборок"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 551,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Размер обучающей выборки: (424, 8)\n",
|
|||
|
"Размер контрольной выборки: (141, 8)\n",
|
|||
|
"Размер тестовой выборки: (142, 8)\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Разделение на признаки (X) и целевую переменную (y)\n",
|
|||
|
"# Предположим, что Outcome - это целевая переменная\n",
|
|||
|
"X = df.drop('Outcome', axis=1)\n",
|
|||
|
"y = df['Outcome']\n",
|
|||
|
"\n",
|
|||
|
"# Разбиение на обучающую и остальную выборку (контрольную + тестовую)\n",
|
|||
|
"X_train, X_rem, y_train, y_rem = train_test_split(X, y, train_size=0.6, random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"# Разбиение остатка на контрольную и тестовую выборки\n",
|
|||
|
"X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, test_size=0.5, random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"# Вывод размеров выборок\n",
|
|||
|
"print(\"Размер обучающей выборки:\", X_train.shape)\n",
|
|||
|
"print(\"Размер контрольной выборки:\", X_val.shape)\n",
|
|||
|
"print(\"Размер тестовой выборки:\", X_test.shape)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 552,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Распределение классов в обучающей выборке:\n",
|
|||
|
"Outcome\n",
|
|||
|
"0 0.658019\n",
|
|||
|
"1 0.341981\n",
|
|||
|
"Name: proportion, dtype: float64\n",
|
|||
|
"\n",
|
|||
|
"Распределение классов в контрольной выборке:\n",
|
|||
|
"Outcome\n",
|
|||
|
"0 0.680851\n",
|
|||
|
"1 0.319149\n",
|
|||
|
"Name: proportion, dtype: float64\n",
|
|||
|
"\n",
|
|||
|
"Распределение классов в тестовой выборке:\n",
|
|||
|
"Outcome\n",
|
|||
|
"0 0.640845\n",
|
|||
|
"1 0.359155\n",
|
|||
|
"Name: proportion, dtype: float64\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"# Функция для анализа сбалансированности\n",
|
|||
|
"def analyze_balance(y_train, y_val, y_test):\n",
|
|||
|
" print(\"Распределение классов в обучающей выборке:\")\n",
|
|||
|
" print(y_train.value_counts(normalize=True))\n",
|
|||
|
" \n",
|
|||
|
" print(\"\\nРаспределение классов в контрольной выборке:\")\n",
|
|||
|
" print(y_val.value_counts(normalize=True))\n",
|
|||
|
" \n",
|
|||
|
" print(\"\\nРаспределение классов в тестовой выборке:\")\n",
|
|||
|
" print(y_test.value_counts(normalize=True))\n",
|
|||
|
"\n",
|
|||
|
"# Анализ сбалансированности\n",
|
|||
|
"analyze_balance(y_train, y_val, y_test)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Такие выборки сложно назвать сбалансированными. В этот раз используем метод выборки с недостатком (undersampling)."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 553,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Сбалансированность обучающей выборки после undersampling:\n",
|
|||
|
"Outcome\n",
|
|||
|
"0 0.5\n",
|
|||
|
"1 0.5\n",
|
|||
|
"Name: proportion, dtype: float64\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"undersampler = RandomUnderSampler(random_state=42)\n",
|
|||
|
"\n",
|
|||
|
"X_train_resampled, y_train_resampled = undersampler.fit_resample(X_train, y_train)\n",
|
|||
|
"\n",
|
|||
|
"print(\"Сбалансированность обучающей выборки после undersampling:\")\n",
|
|||
|
"print(y_train_resampled.value_counts(normalize=True))"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Можно увидеть, что выборка была успешно сбалансирована."
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"metadata": {
|
|||
|
"kernelspec": {
|
|||
|
"display_name": "aimenv",
|
|||
|
"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.12.5"
|
|||
|
}
|
|||
|
},
|
|||
|
"nbformat": 4,
|
|||
|
"nbformat_minor": 2
|
|||
|
}
|