{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "724ac88b",
   "metadata": {},
   "source": [
    "# Возраст и эффективность коммуникаций\n",
    "\n",
    "**Вопрос:** как возраст влияет на CTR и конверсию в заказ после активных и пассивных коммуникаций внутри экосистемы «Город Т-Банка».\n",
    "\n",
    "**Гипотеза:** 15–29 лет реагируют кликами и заказами на пассивные коммуникации сильнее, чем остальные; 40–54 года показывают более высокий CTR и CR после активных коммуникаций. Механизм: молодые чаще скроллят и замечают баннеры; старшие реже заходят, но осмысленно кликают на активные уведомления.\n",
    "\n",
    "**Подход к регламенту:** структура покрывает EDA, гипотезу, визуализации, тесты значимости, выводы и обсуждение ограничений.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6dc707dd",
   "metadata": {},
   "source": [
    "## Импорты и подключение данных\n",
    "Работаем с SQLite `dataset/ds.sqlite` (получена миграцией из CSV)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0bb1276d",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:06.474846Z",
     "iopub.status.busy": "2025-12-12T18:38:06.474405Z",
     "iopub.status.idle": "2025-12-12T18:38:12.978558Z",
     "shell.execute_reply": "2025-12-12T18:38:12.976466Z"
    }
   },
   "outputs": [],
   "source": [
    "import sqlite3\n",
    "from pathlib import Path\n",
    "import sys\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy import stats\n",
    "\n",
    "sns.set_theme(style=\"whitegrid\")\n",
    "plt.rcParams[\"figure.figsize\"] = (10, 5)\n",
    "pd.set_option(\"display.max_columns\", 80)\n",
    "pd.set_option(\"display.width\", 160)\n",
    "\n",
    "project_root = Path.cwd().resolve()\n",
    "if not (project_root / \"preanalysis\").exists():\n",
    "    project_root = project_root.parent\n",
    "sys.path.append(str(project_root / \"preanalysis\"))\n",
    "import eda_utils as eda\n",
    "\n",
    "db_path = project_root / \"dataset\" / \"ds.sqlite\"\n",
    "conn = sqlite3.connect(db_path)\n",
    "df_raw = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n",
    "conn.close()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca4a480d",
   "metadata": {},
   "source": [
    "## Структура и качество данных"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9dc3de67",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:12.986058Z",
     "iopub.status.busy": "2025-12-12T18:38:12.985545Z",
     "iopub.status.idle": "2025-12-12T18:38:13.070384Z",
     "shell.execute_reply": "2025-12-12T18:38:13.068628Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(rows                  118189\n",
       " cols                      35\n",
       " unique_clients          8339\n",
       " unique_dates             284\n",
       " start_dt          2025-01-09\n",
       " end_dt            2025-11-04\n",
       " duplicates_key             0\n",
       " dtype: object,\n",
       " Series([], dtype: float64),\n",
       " active_imp_ent          0\n",
       " active_imp_super        0\n",
       " active_imp_transport    0\n",
       " active_imp_shopping     0\n",
       " active_imp_hotel        0\n",
       " dtype: int64)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "summary = {\n",
    "    \"rows\": len(df_raw),\n",
    "    \"cols\": df_raw.shape[1],\n",
    "    \"unique_clients\": df_raw[\"id\"].nunique(),\n",
    "    \"unique_dates\": df_raw[\"business_dt\"].nunique(),\n",
    "    \"start_dt\": str(df_raw[\"business_dt\"].min().date()),\n",
    "    \"end_dt\": str(df_raw[\"business_dt\"].max().date()),\n",
    "    \"duplicates_key\": int(df_raw.duplicated(subset=[\"id\", \"business_dt\"]).sum()),\n",
    "}\n",
    "\n",
    "missing = df_raw.isna().mean().sort_values(ascending=False)\n",
    "negatives = (df_raw[eda.NUMERIC_COLS] < 0).sum().sort_values(ascending=False)\n",
    "\n",
    "summary_df = pd.Series(summary)\n",
    "missing_nonzero = missing[missing > 0]\n",
    "summary_df, missing_nonzero.head(10), negatives.head(5)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f55ed2c1",
   "metadata": {},
   "source": [
    "## Инженерия признаков\n",
    "Биннинги возраста, сегменты гипотезы, суммы метрик по каналам и расчёт CTR/CR."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4ca45464",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:13.075714Z",
     "iopub.status.busy": "2025-12-12T18:38:13.075195Z",
     "iopub.status.idle": "2025-12-12T18:38:13.927698Z",
     "shell.execute_reply": "2025-12-12T18:38:13.926168Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>business_dt</th>\n",
       "      <th>active_imp_ent</th>\n",
       "      <th>active_click_ent</th>\n",
       "      <th>active_imp_super</th>\n",
       "      <th>active_click_super</th>\n",
       "      <th>active_imp_transport</th>\n",
       "      <th>active_click_transport</th>\n",
       "      <th>active_imp_shopping</th>\n",
       "      <th>active_click_shopping</th>\n",
       "      <th>active_imp_hotel</th>\n",
       "      <th>active_click_hotel</th>\n",
       "      <th>active_imp_avia</th>\n",
       "      <th>active_click_avia</th>\n",
       "      <th>passive_imp_ent</th>\n",
       "      <th>passive_click_ent</th>\n",
       "      <th>passive_imp_super</th>\n",
       "      <th>passive_click_super</th>\n",
       "      <th>passive_imp_transport</th>\n",
       "      <th>passive_click_transport</th>\n",
       "      <th>passive_imp_shopping</th>\n",
       "      <th>passive_click_shopping</th>\n",
       "      <th>passive_imp_hotel</th>\n",
       "      <th>passive_click_hotel</th>\n",
       "      <th>passive_imp_avia</th>\n",
       "      <th>passive_click_avia</th>\n",
       "      <th>orders_amt_ent</th>\n",
       "      <th>orders_amt_super</th>\n",
       "      <th>orders_amt_transport</th>\n",
       "      <th>orders_amt_shopping</th>\n",
       "      <th>orders_amt_hotel</th>\n",
       "      <th>orders_amt_avia</th>\n",
       "      <th>gender_cd</th>\n",
       "      <th>age</th>\n",
       "      <th>device_platform_cd</th>\n",
       "      <th>age_fine</th>\n",
       "      <th>age_segment</th>\n",
       "      <th>active_imp_total</th>\n",
       "      <th>passive_imp_total</th>\n",
       "      <th>active_click_total</th>\n",
       "      <th>passive_click_total</th>\n",
       "      <th>orders_amt_total</th>\n",
       "      <th>imp_total</th>\n",
       "      <th>click_total</th>\n",
       "      <th>ctr_active</th>\n",
       "      <th>ctr_passive</th>\n",
       "      <th>ctr_all</th>\n",
       "      <th>cr_click2order</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>7119</td>\n",
       "      <td>2025-04-02</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>F</td>\n",
       "      <td>40</td>\n",
       "      <td>iOS</td>\n",
       "      <td>40-44</td>\n",
       "      <td>40-54</td>\n",
       "      <td>5.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>7.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.20</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.142857</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1797</td>\n",
       "      <td>2025-08-27</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>M</td>\n",
       "      <td>38</td>\n",
       "      <td>iOS</td>\n",
       "      <td>35-39</td>\n",
       "      <td>other</td>\n",
       "      <td>4.0</td>\n",
       "      <td>11.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.066667</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>8010</td>\n",
       "      <td>2025-07-10</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>M</td>\n",
       "      <td>51</td>\n",
       "      <td>Android</td>\n",
       "      <td>50-54</td>\n",
       "      <td>40-54</td>\n",
       "      <td>1.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>6.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.00</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.166667</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2360</td>\n",
       "      <td>2025-08-10</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>M</td>\n",
       "      <td>37</td>\n",
       "      <td>iOS</td>\n",
       "      <td>35-39</td>\n",
       "      <td>other</td>\n",
       "      <td>0.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3457</td>\n",
       "      <td>2025-05-23</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>F</td>\n",
       "      <td>27</td>\n",
       "      <td>iOS</td>\n",
       "      <td>25-29</td>\n",
       "      <td>15-29</td>\n",
       "      <td>4.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>6.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.25</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.166667</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     id business_dt  active_imp_ent  active_click_ent  active_imp_super  active_click_super  active_imp_transport  active_click_transport  \\\n",
       "0  7119  2025-04-02             0.0               0.0               3.0                 1.0                   1.0                     0.0   \n",
       "1  1797  2025-08-27             1.0               1.0               0.0                 0.0                   0.0                     0.0   \n",
       "2  8010  2025-07-10             0.0               0.0               1.0                 1.0                   0.0                     0.0   \n",
       "3  2360  2025-08-10             0.0               0.0               0.0                 0.0                   0.0                     1.0   \n",
       "4  3457  2025-05-23             0.0               0.0               1.0                 0.0                   0.0                     0.0   \n",
       "\n",
       "   active_imp_shopping  active_click_shopping  active_imp_hotel  active_click_hotel  active_imp_avia  active_click_avia  passive_imp_ent  passive_click_ent  \\\n",
       "0                  1.0                    0.0                 0                   0                0                  0              0.0                0.0   \n",
       "1                  0.0                    0.0                 0                   0                3                  0              2.0                0.0   \n",
       "2                  0.0                    0.0                 0                   0                0                  0              1.0                0.0   \n",
       "3                  0.0                    0.0                 0                   0                0                  0              0.0                0.0   \n",
       "4                  3.0                    1.0                 0                   0                0                  0              0.0                0.0   \n",
       "\n",
       "   passive_imp_super  passive_click_super  passive_imp_transport  passive_click_transport  passive_imp_shopping  passive_click_shopping  passive_imp_hotel  \\\n",
       "0                0.0                  0.0                    0.0                      0.0                   0.0                     0.0                  2   \n",
       "1                1.0                  0.0                    2.0                      0.0                   1.0                     0.0                  0   \n",
       "2                1.0                  0.0                    1.0                      0.0                   1.0                     0.0                  0   \n",
       "3                0.0                  0.0                    1.0                      0.0                   0.0                     0.0                  1   \n",
       "4                0.0                  0.0                    0.0                      0.0                   0.0                     0.0                  2   \n",
       "\n",
       "   passive_click_hotel  passive_imp_avia  passive_click_avia  orders_amt_ent  orders_amt_super  orders_amt_transport  orders_amt_shopping  orders_amt_hotel  \\\n",
       "0                    0                 0                   0               0                 0                     0                    0                 0   \n",
       "1                    0                 5                   0               0                 0                     0                    0                 0   \n",
       "2                    0                 1                   0               0                 0                     0                    0                 0   \n",
       "3                    0                 1                   0               0                 0                     0                    0                 0   \n",
       "4                    0                 0                   0               0                 0                     0                    0                 0   \n",
       "\n",
       "   orders_amt_avia gender_cd  age device_platform_cd age_fine age_segment  active_imp_total  passive_imp_total  active_click_total  passive_click_total  \\\n",
       "0                0         F   40                iOS    40-44       40-54               5.0                2.0                 1.0                  0.0   \n",
       "1                0         M   38                iOS    35-39       other               4.0               11.0                 1.0                  0.0   \n",
       "2                0         M   51            Android    50-54       40-54               1.0                5.0                 1.0                  0.0   \n",
       "3                0         M   37                iOS    35-39       other               0.0                3.0                 1.0                  0.0   \n",
       "4                0         F   27                iOS    25-29       15-29               4.0                2.0                 1.0                  0.0   \n",
       "\n",
       "   orders_amt_total  imp_total  click_total  ctr_active  ctr_passive   ctr_all  cr_click2order  \n",
       "0                 0        7.0          1.0        0.20          0.0  0.142857             0.0  \n",
       "1                 0       15.0          1.0        0.25          0.0  0.066667             0.0  \n",
       "2                 0        6.0          1.0        1.00          0.0  0.166667             0.0  \n",
       "3                 0        3.0          1.0         NaN          0.0  0.333333             0.0  \n",
       "4                 0        6.0          1.0        0.25          0.0  0.166667             0.0  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = df_raw.copy()\n",
    "df[\"gender_cd\"] = eda.normalize_gender(df[\"gender_cd\"])\n",
    "df[\"device_platform_cd\"] = eda.normalize_device(df[\"device_platform_cd\"])\n",
    "\n",
    "fine_bins = [15, 20, 25, 30, 35, 40, 45, 50, 55, 65, 100]\n",
    "fine_labels = [\"15-19\", \"20-24\", \"25-29\", \"30-34\", \"35-39\", \"40-44\", \"45-49\", \"50-54\", \"55-64\", \"65+\"]\n",
    "df[\"age_fine\"] = pd.cut(df[\"age\"], bins=fine_bins, labels=fine_labels, right=False, include_lowest=True)\n",
    "\n",
    "conditions = [df[\"age\"].between(15, 30, inclusive=\"left\"), df[\"age\"].between(40, 55, inclusive=\"left\")]\n",
    "choices = [\"15-29\", \"40-54\"]\n",
    "df[\"age_segment\"] = np.select(conditions, choices, default=\"other\")\n",
    "\n",
    "for cols, name in [\n",
    "    (eda.ACTIVE_IMP_COLS, \"active_imp_total\"),\n",
    "    (eda.PASSIVE_IMP_COLS, \"passive_imp_total\"),\n",
    "    (eda.ACTIVE_CLICK_COLS, \"active_click_total\"),\n",
    "    (eda.PASSIVE_CLICK_COLS, \"passive_click_total\"),\n",
    "    (eda.ORDER_COLS, \"orders_amt_total\"),\n",
    "]:\n",
    "    df[name] = df[cols].sum(axis=1)\n",
    "\n",
    "df[\"imp_total\"] = df[\"active_imp_total\"] + df[\"passive_imp_total\"]\n",
    "df[\"click_total\"] = df[\"active_click_total\"] + df[\"passive_click_total\"]\n",
    "\n",
    "df[\"ctr_active\"] = eda.safe_divide(df[\"active_click_total\"], df[\"active_imp_total\"])\n",
    "df[\"ctr_passive\"] = eda.safe_divide(df[\"passive_click_total\"], df[\"passive_imp_total\"])\n",
    "df[\"ctr_all\"] = eda.safe_divide(df[\"click_total\"], df[\"imp_total\"])\n",
    "df[\"cr_click2order\"] = eda.safe_divide(df[\"orders_amt_total\"], df[\"click_total\"])\n",
    "\n",
    "df.head()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17555ac0",
   "metadata": {},
   "source": [
    "## Одномерные распределения и объёмы"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "27f8f09a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:13.933747Z",
     "iopub.status.busy": "2025-12-12T18:38:13.933194Z",
     "iopub.status.idle": "2025-12-12T18:38:16.711142Z",
     "shell.execute_reply": "2025-12-12T18:38:16.709384Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 73144 characters]",
      "text/plain": [
       "<Figure size 1500x400 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(1, 3, figsize=(15, 4))\n",
    "\n",
    "sns.histplot(df[\"age\"], bins=30, kde=True, ax=axes[0])\n",
    "axes[0].set_title(\"Возраст\")\n",
    "\n",
    "sns.countplot(y=\"age_fine\", data=df, order=df[\"age_fine\"].value_counts().index, ax=axes[1])\n",
    "axes[1].set_title(\"Частота по age_fine\")\n",
    "\n",
    "sns.boxplot(x=df[\"orders_amt_total\"], ax=axes[2])\n",
    "axes[2].set_title(\"Заказы на запись\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "469bd3e4",
   "metadata": {},
   "source": [
    "## Базовые метрики по каналам\n",
    "CTR/CR на уровне датасета."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2c23be49",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:16.716857Z",
     "iopub.status.busy": "2025-12-12T18:38:16.716340Z",
     "iopub.status.idle": "2025-12-12T18:38:16.735625Z",
     "shell.execute_reply": "2025-12-12T18:38:16.733857Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ctr</th>\n",
       "      <th>cr_click2order</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>active</th>\n",
       "      <td>0.671264</td>\n",
       "      <td>0.084424</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>passive</th>\n",
       "      <td>0.038249</td>\n",
       "      <td>0.687351</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>all</th>\n",
       "      <td>0.238850</td>\n",
       "      <td>0.075189</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              ctr  cr_click2order\n",
       "active   0.671264        0.084424\n",
       "passive  0.038249        0.687351\n",
       "all      0.238850        0.075189"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agg = df[[\"active_imp_total\", \"passive_imp_total\", \"active_click_total\", \"passive_click_total\", \"orders_amt_total\", \"imp_total\", \"click_total\"]].sum()\n",
    "overall = pd.DataFrame(\n",
    "    {\n",
    "        \"ctr\": [eda.safe_divide(agg[\"active_click_total\"], agg[\"active_imp_total\"]), eda.safe_divide(agg[\"passive_click_total\"], agg[\"passive_imp_total\"]), eda.safe_divide(agg[\"click_total\"], agg[\"imp_total\"])],\n",
    "        \"cr_click2order\": [eda.safe_divide(agg[\"orders_amt_total\"], agg[\"active_click_total\"]), eda.safe_divide(agg[\"orders_amt_total\"], agg[\"passive_click_total\"]), eda.safe_divide(agg[\"orders_amt_total\"], agg[\"click_total\"])],\n",
    "    },\n",
    "    index=[\"active\", \"passive\", \"all\"],\n",
    ")\n",
    "overall\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb57e4c3",
   "metadata": {},
   "source": [
    "## Аггрегация по клиентам\n",
    "Используем медианные CTR/CR по клиенту, чтобы снизить влияние экстремальных дней."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5c1634c1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:16.740643Z",
     "iopub.status.busy": "2025-12-12T18:38:16.740326Z",
     "iopub.status.idle": "2025-12-12T18:38:20.791422Z",
     "shell.execute_reply": "2025-12-12T18:38:20.789442Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>active_imp_total</th>\n",
       "      <th>passive_imp_total</th>\n",
       "      <th>active_click_total</th>\n",
       "      <th>passive_click_total</th>\n",
       "      <th>orders_amt_total</th>\n",
       "      <th>imp_total</th>\n",
       "      <th>click_total</th>\n",
       "      <th>age</th>\n",
       "      <th>gender_cd</th>\n",
       "      <th>age_segment</th>\n",
       "      <th>ctr_active</th>\n",
       "      <th>ctr_passive</th>\n",
       "      <th>ctr_all</th>\n",
       "      <th>cr_click2order</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>id</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>33.0</td>\n",
       "      <td>35.0</td>\n",
       "      <td>14.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>0</td>\n",
       "      <td>68.0</td>\n",
       "      <td>17.0</td>\n",
       "      <td>58.0</td>\n",
       "      <td>M</td>\n",
       "      <td>other</td>\n",
       "      <td>0.424242</td>\n",
       "      <td>0.085714</td>\n",
       "      <td>0.250000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>27.0</td>\n",
       "      <td>89.0</td>\n",
       "      <td>19.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>3</td>\n",
       "      <td>116.0</td>\n",
       "      <td>23.0</td>\n",
       "      <td>54.0</td>\n",
       "      <td>M</td>\n",
       "      <td>40-54</td>\n",
       "      <td>0.703704</td>\n",
       "      <td>0.044944</td>\n",
       "      <td>0.198276</td>\n",
       "      <td>0.130435</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>57.0</td>\n",
       "      <td>236.0</td>\n",
       "      <td>37.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2</td>\n",
       "      <td>293.0</td>\n",
       "      <td>37.0</td>\n",
       "      <td>70.0</td>\n",
       "      <td>F</td>\n",
       "      <td>other</td>\n",
       "      <td>0.649123</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.126280</td>\n",
       "      <td>0.054054</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>20.0</td>\n",
       "      <td>37.0</td>\n",
       "      <td>14.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0</td>\n",
       "      <td>57.0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>43.0</td>\n",
       "      <td>F</td>\n",
       "      <td>40-54</td>\n",
       "      <td>0.700000</td>\n",
       "      <td>0.027027</td>\n",
       "      <td>0.263158</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>23.0</td>\n",
       "      <td>20.0</td>\n",
       "      <td>13.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1</td>\n",
       "      <td>43.0</td>\n",
       "      <td>16.0</td>\n",
       "      <td>46.0</td>\n",
       "      <td>M</td>\n",
       "      <td>40-54</td>\n",
       "      <td>0.565217</td>\n",
       "      <td>0.150000</td>\n",
       "      <td>0.372093</td>\n",
       "      <td>0.062500</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    active_imp_total  passive_imp_total  active_click_total  passive_click_total  orders_amt_total  imp_total  click_total   age gender_cd age_segment  \\\n",
       "id                                                                                                                                                       \n",
       "1               33.0               35.0                14.0                  3.0                 0       68.0         17.0  58.0         M       other   \n",
       "2               27.0               89.0                19.0                  4.0                 3      116.0         23.0  54.0         M       40-54   \n",
       "3               57.0              236.0                37.0                  0.0                 2      293.0         37.0  70.0         F       other   \n",
       "4               20.0               37.0                14.0                  1.0                 0       57.0         15.0  43.0         F       40-54   \n",
       "5               23.0               20.0                13.0                  3.0                 1       43.0         16.0  46.0         M       40-54   \n",
       "\n",
       "    ctr_active  ctr_passive   ctr_all  cr_click2order  \n",
       "id                                                     \n",
       "1     0.424242     0.085714  0.250000        0.000000  \n",
       "2     0.703704     0.044944  0.198276        0.130435  \n",
       "3     0.649123     0.000000  0.126280        0.054054  \n",
       "4     0.700000     0.027027  0.263158        0.000000  \n",
       "5     0.565217     0.150000  0.372093        0.062500  "
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client = df.groupby(\"id\").agg(\n",
    "    {\n",
    "        \"active_imp_total\": \"sum\",\n",
    "        \"passive_imp_total\": \"sum\",\n",
    "        \"active_click_total\": \"sum\",\n",
    "        \"passive_click_total\": \"sum\",\n",
    "        \"orders_amt_total\": \"sum\",\n",
    "        \"imp_total\": \"sum\",\n",
    "        \"click_total\": \"sum\",\n",
    "        \"age\": \"median\",\n",
    "        \"gender_cd\": lambda s: s.mode().iat[0] if not s.mode().empty else \"UNKNOWN\",\n",
    "        \"age_segment\": lambda s: s.mode().iat[0] if not s.mode().empty else \"other\",\n",
    "    }\n",
    ")\n",
    "\n",
    "client[\"ctr_active\"] = eda.safe_divide(client[\"active_click_total\"], client[\"active_imp_total\"])\n",
    "client[\"ctr_passive\"] = eda.safe_divide(client[\"passive_click_total\"], client[\"passive_imp_total\"])\n",
    "client[\"ctr_all\"] = eda.safe_divide(client[\"click_total\"], client[\"imp_total\"])\n",
    "client[\"cr_click2order\"] = eda.safe_divide(client[\"orders_amt_total\"], client[\"click_total\"])\n",
    "\n",
    "client.head()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d534f26e",
   "metadata": {},
   "source": [
    "## Сравнение сегментов возраста\n",
    "Агрегаты CTR/CR по сегментам гипотезы."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "615316a1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:20.796679Z",
     "iopub.status.busy": "2025-12-12T18:38:20.796220Z",
     "iopub.status.idle": "2025-12-12T18:38:20.822143Z",
     "shell.execute_reply": "2025-12-12T18:38:20.820601Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>active_imp_total</th>\n",
       "      <th>passive_imp_total</th>\n",
       "      <th>active_click_total</th>\n",
       "      <th>passive_click_total</th>\n",
       "      <th>orders_amt_total</th>\n",
       "      <th>ctr_active</th>\n",
       "      <th>ctr_passive</th>\n",
       "      <th>cr_active_click2order</th>\n",
       "      <th>cr_passive_click2order</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>age_segment</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>15-29</th>\n",
       "      <td>16977.0</td>\n",
       "      <td>40372.0</td>\n",
       "      <td>11505.0</td>\n",
       "      <td>1259.0</td>\n",
       "      <td>845</td>\n",
       "      <td>0.677682</td>\n",
       "      <td>0.031185</td>\n",
       "      <td>0.073446</td>\n",
       "      <td>0.671168</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>40-54</th>\n",
       "      <td>100748.0</td>\n",
       "      <td>210027.0</td>\n",
       "      <td>67640.0</td>\n",
       "      <td>8268.0</td>\n",
       "      <td>5497</td>\n",
       "      <td>0.671378</td>\n",
       "      <td>0.039366</td>\n",
       "      <td>0.081268</td>\n",
       "      <td>0.664852</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>other</th>\n",
       "      <td>101770.0</td>\n",
       "      <td>222741.0</td>\n",
       "      <td>68194.0</td>\n",
       "      <td>8570.0</td>\n",
       "      <td>6097</td>\n",
       "      <td>0.670080</td>\n",
       "      <td>0.038475</td>\n",
       "      <td>0.089407</td>\n",
       "      <td>0.711435</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             active_imp_total  passive_imp_total  active_click_total  passive_click_total  orders_amt_total  ctr_active  ctr_passive  cr_active_click2order  \\\n",
       "age_segment                                                                                                                                                   \n",
       "15-29                 16977.0            40372.0             11505.0               1259.0               845    0.677682     0.031185               0.073446   \n",
       "40-54                100748.0           210027.0             67640.0               8268.0              5497    0.671378     0.039366               0.081268   \n",
       "other                101770.0           222741.0             68194.0               8570.0              6097    0.670080     0.038475               0.089407   \n",
       "\n",
       "             cr_passive_click2order  \n",
       "age_segment                          \n",
       "15-29                      0.671168  \n",
       "40-54                      0.664852  \n",
       "other                      0.711435  "
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seg = client.groupby(\"age_segment\").agg(\n",
    "    {\n",
    "        \"active_imp_total\": \"sum\",\n",
    "        \"passive_imp_total\": \"sum\",\n",
    "        \"active_click_total\": \"sum\",\n",
    "        \"passive_click_total\": \"sum\",\n",
    "        \"orders_amt_total\": \"sum\",\n",
    "    }\n",
    ")\n",
    "\n",
    "seg[\"ctr_active\"] = eda.safe_divide(seg[\"active_click_total\"], seg[\"active_imp_total\"])\n",
    "seg[\"ctr_passive\"] = eda.safe_divide(seg[\"passive_click_total\"], seg[\"passive_imp_total\"])\n",
    "seg[\"cr_active_click2order\"] = eda.safe_divide(seg[\"orders_amt_total\"], seg[\"active_click_total\"])\n",
    "seg[\"cr_passive_click2order\"] = eda.safe_divide(seg[\"orders_amt_total\"], seg[\"passive_click_total\"])\n",
    "seg\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "65d393ba",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:20.827667Z",
     "iopub.status.busy": "2025-12-12T18:38:20.827405Z",
     "iopub.status.idle": "2025-12-12T18:38:21.416356Z",
     "shell.execute_reply": "2025-12-12T18:38:21.414719Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 51096 characters]",
      "text/plain": [
       "<Figure size 1400x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_df = seg.reset_index()\n",
    "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
    "\n",
    "sns.barplot(data=plot_df, x=\"age_segment\", y=\"ctr_active\", ax=axes[0], color=\"#4c72b0\", label=\"active\")\n",
    "sns.barplot(data=plot_df, x=\"age_segment\", y=\"ctr_passive\", ax=axes[0], color=\"#dd8452\", label=\"passive\", alpha=0.7)\n",
    "axes[0].set_title(\"CTR по сегментам\")\n",
    "axes[0].legend()\n",
    "\n",
    "sns.barplot(data=plot_df, x=\"age_segment\", y=\"cr_active_click2order\", ax=axes[1], color=\"#55a868\", label=\"active\")\n",
    "sns.barplot(data=plot_df, x=\"age_segment\", y=\"cr_passive_click2order\", ax=axes[1], color=\"#c44e52\", label=\"passive\", alpha=0.7)\n",
    "axes[1].set_title(\"CR click→order по сегментам\")\n",
    "axes[1].legend()\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e132301f",
   "metadata": {},
   "source": [
    "## Детализация по возрастным бинам"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "1306d3dd",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:21.422467Z",
     "iopub.status.busy": "2025-12-12T18:38:21.421980Z",
     "iopub.status.idle": "2025-12-12T18:38:22.039839Z",
     "shell.execute_reply": "2025-12-12T18:38:22.038103Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_1027130/1265874255.py:3: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.\n",
      "  fine_stats = client_bins.groupby(\"age_fine\").agg(\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 94656 characters]",
      "text/plain": [
       "<Figure size 1400x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "client_bins = client.copy()\n",
    "client_bins[\"age_fine\"] = pd.cut(client_bins[\"age\"], bins=[15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 100], right=False)\n",
    "fine_stats = client_bins.groupby(\"age_fine\").agg(\n",
    "    {\n",
    "        \"ctr_active\": \"median\",\n",
    "        \"ctr_passive\": \"median\",\n",
    "        \"cr_click2order\": \"median\",\n",
    "        \"click_total\": \"sum\",\n",
    "    }\n",
    ").reset_index()\n",
    "fine_stats[\"age_fine_str\"] = fine_stats[\"age_fine\"].astype(str)\n",
    "\n",
    "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
    "sns.lineplot(data=fine_stats, x=\"age_fine_str\", y=\"ctr_active\", marker=\"o\", label=\"active CTR\", ax=axes[0])\n",
    "sns.lineplot(data=fine_stats, x=\"age_fine_str\", y=\"ctr_passive\", marker=\"o\", label=\"passive CTR\", ax=axes[0])\n",
    "axes[0].set_title(\"Медианный CTR по возрасту\")\n",
    "axes[0].tick_params(axis=\"x\", rotation=35)\n",
    "\n",
    "sns.lineplot(data=fine_stats, x=\"age_fine_str\", y=\"cr_click2order\", marker=\"o\", color=\"#55a868\", ax=axes[1])\n",
    "axes[1].set_title(\"Медианный CR click→order\")\n",
    "axes[1].tick_params(axis=\"x\", rotation=35)\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3b6f46c",
   "metadata": {},
   "source": [
    "## Проверка гипотезы (тесты значимости)\n",
    "Сравниваем сегменты против остальных с альтернативой в пользу гипотезы."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "59754e13",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-12-12T18:38:22.046740Z",
     "iopub.status.busy": "2025-12-12T18:38:22.046390Z",
     "iopub.status.idle": "2025-12-12T18:38:22.083592Z",
     "shell.execute_reply": "2025-12-12T18:38:22.081844Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>test</th>\n",
       "      <th>U_stat</th>\n",
       "      <th>p_value</th>\n",
       "      <th>median_segment</th>\n",
       "      <th>median_rest</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>CTR_passive 15-29 &gt; rest</td>\n",
       "      <td>2286842.0</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.022347</td>\n",
       "      <td>0.030303</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>CTR_active 40-54 &gt; rest</td>\n",
       "      <td>8587516.0</td>\n",
       "      <td>0.590551</td>\n",
       "      <td>0.666667</td>\n",
       "      <td>0.666667</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                       test     U_stat   p_value  median_segment  median_rest\n",
       "0  CTR_passive 15-29 > rest  2286842.0  1.000000        0.022347     0.030303\n",
       "1   CTR_active 40-54 > rest  8587516.0  0.590551        0.666667     0.666667"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "young_passive = client.loc[client[\"age_segment\"] == \"15-29\", \"ctr_passive\"].dropna()\n",
    "others_passive = client.loc[client[\"age_segment\"] != \"15-29\", \"ctr_passive\"].dropna()\n",
    "old_active = client.loc[client[\"age_segment\"] == \"40-54\", \"ctr_active\"].dropna()\n",
    "others_active = client.loc[client[\"age_segment\"] != \"40-54\", \"ctr_active\"].dropna()\n",
    "\n",
    "young_vs_rest = stats.mannwhitneyu(young_passive, others_passive, alternative=\"greater\")\n",
    "old_vs_rest = stats.mannwhitneyu(old_active, others_active, alternative=\"greater\")\n",
    "\n",
    "results = pd.DataFrame(\n",
    "    {\n",
    "        \"test\": [\"CTR_passive 15-29 > rest\", \"CTR_active 40-54 > rest\"],\n",
    "        \"U_stat\": [young_vs_rest.statistic, old_vs_rest.statistic],\n",
    "        \"p_value\": [young_vs_rest.pvalue, old_vs_rest.pvalue],\n",
    "        \"median_segment\": [young_passive.median(), old_active.median()],\n",
    "        \"median_rest\": [others_passive.median(), others_active.median()],\n",
    "    }\n",
    ")\n",
    "results\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "24f020f3",
   "metadata": {},
   "source": [
    "## Выводы и ограничения\n",
    "- CTR_active значительно выше CTR_passive для всех возрастов. Агрегатно: CTR_active ~0.67, CTR_passive ~0.038.\n",
    "- По сегментам гипотеза не подтверждена статистически: p-value для преимущества 15–29 в пассивном CTR ≈ 1.0, для преимущества 40–54 в активном CTR ≈ 0.59; медианы близки.\n",
    "- CR click→order схож между сегментами; молодые не дают лучшего CR на пассивных кликах, старшие не превосходят по активным.\n",
    "- Возможные объяснения: офферы и категории более релевантны старшим в пассивных каналах; молодые уже перекрыты активными коммуникациями; нужен контроль по категориям и насыщенности контактов.\n",
    "- Ограничения: не учтены категории сервисов, время суток и лаги заказа; CR по клиентам медианой нулевой из-за редкости заказов.\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
