diff --git a/alternative/category_mix_uplift/analysis.ipynb b/alternative/category_mix_uplift/analysis.ipynb deleted file mode 100644 index 18b2dd0..0000000 --- a/alternative/category_mix_uplift/analysis.ipynb +++ /dev/null @@ -1,541 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Категорийный микс и вероятность заказа\n", - "\n", - "**Вопрос:** влияет ли высокая доля показов в развлечениях (ent) при контроле объёма на вероятность заказа?\n", - "\n", - "**Гипотеза:** клиенты с высокой долей коммуникаций в ent чаще оформляют заказы, даже при одинаковом объёме контактов. Проверяем через ML-классификацию `has_order`." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:34:48.794887Z", - "iopub.status.busy": "2025-12-12T19:34:48.794342Z", - "iopub.status.idle": "2025-12-12T19:34:55.568140Z", - "shell.execute_reply": "2025-12-12T19:34:55.565812Z" - } - }, - "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 sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.linear_model import LogisticRegression\n", - "from sklearn.metrics import roc_auc_score\n", - "from sklearn.impute import SimpleImputer\n", - "\n", - "sns.set_theme(style=\"whitegrid\")\n", - "plt.rcParams[\"figure.figsize\"] = (10, 5)\n", - "\n", - "project_root = Path.cwd().resolve()\n", - "while not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\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 = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n", - "conn.close()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:34:55.575403Z", - "iopub.status.busy": "2025-12-12T19:34:55.574914Z", - "iopub.status.idle": "2025-12-12T19:34:58.188645Z", - "shell.execute_reply": "2025-12-12T19:34:58.187063Z" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
idimp_totalclick_totalorders_amt_totalimp_cat_entimp_cat_superimp_cat_transportimp_cat_shoppingimp_cat_hotelimp_cat_aviaagegender_cddevice_platform_cdhas_ordershare_imp_entshare_imp_supershare_imp_transportshare_imp_shoppingshare_imp_hotelshare_imp_avia
0168.017.0013.017.010.014.012258.0MAndroid00.1911760.2500000.1470590.2058820.1764710.029412
12116.023.0314.014.025.015.0341454.0MAndroid10.1206900.1206900.2155170.1293100.2931030.120690
23293.037.0246.031.084.071.0253670.0FAndroid10.1569970.1058020.2866890.2423210.0853240.122867
3457.015.009.011.06.011.061443.0FAndroid00.1578950.1929820.1052630.1929820.1052630.245614
4543.016.013.08.06.08.071146.0MAndroid10.0697670.1860470.1395350.1860470.1627910.255814
\n", - "
" - ], - "text/plain": [ - " id imp_total click_total orders_amt_total imp_cat_ent imp_cat_super \\\n", - "0 1 68.0 17.0 0 13.0 17.0 \n", - "1 2 116.0 23.0 3 14.0 14.0 \n", - "2 3 293.0 37.0 2 46.0 31.0 \n", - "3 4 57.0 15.0 0 9.0 11.0 \n", - "4 5 43.0 16.0 1 3.0 8.0 \n", - "\n", - " imp_cat_transport imp_cat_shopping imp_cat_hotel imp_cat_avia age \\\n", - "0 10.0 14.0 12 2 58.0 \n", - "1 25.0 15.0 34 14 54.0 \n", - "2 84.0 71.0 25 36 70.0 \n", - "3 6.0 11.0 6 14 43.0 \n", - "4 6.0 8.0 7 11 46.0 \n", - "\n", - " gender_cd device_platform_cd has_order share_imp_ent share_imp_super \\\n", - "0 M Android 0 0.191176 0.250000 \n", - "1 M Android 1 0.120690 0.120690 \n", - "2 F Android 1 0.156997 0.105802 \n", - "3 F Android 0 0.157895 0.192982 \n", - "4 M Android 1 0.069767 0.186047 \n", - "\n", - " share_imp_transport share_imp_shopping share_imp_hotel share_imp_avia \n", - "0 0.147059 0.205882 0.176471 0.029412 \n", - "1 0.215517 0.129310 0.293103 0.120690 \n", - "2 0.286689 0.242321 0.085324 0.122867 \n", - "3 0.105263 0.192982 0.105263 0.245614 \n", - "4 0.139535 0.186047 0.162791 0.255814 " - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cats = [\"ent\", \"super\", \"transport\", \"shopping\", \"hotel\", \"avia\"]\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", - "cat_cols = []\n", - "for c in cats:\n", - " df[f\"imp_cat_{c}\"] = df[f\"active_imp_{c}\"] + df[f\"passive_imp_{c}\"]\n", - " cat_cols.append(f\"imp_cat_{c}\")\n", - "\n", - "client = df.groupby(\"id\").agg(\n", - " {\n", - " **{col: \"sum\" for col in [\"imp_total\", \"click_total\", \"orders_amt_total\"] + cat_cols},\n", - " \"age\": \"median\",\n", - " \"gender_cd\": lambda s: s.mode().iat[0],\n", - " \"device_platform_cd\": lambda s: s.mode().iat[0],\n", - " }\n", - ").reset_index()\n", - "\n", - "client[\"has_order\"] = (client[\"orders_amt_total\"] > 0).astype(int)\n", - "for c in cats:\n", - " client[f\"share_imp_{c}\"] = eda.safe_divide(client[f\"imp_cat_{c}\"], client[\"imp_total\"])\n", - "\n", - "client.head()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Визуализация: заказы vs доля ent" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:34:58.290489Z", - "iopub.status.busy": "2025-12-12T19:34:58.290200Z", - "iopub.status.idle": "2025-12-12T19:34:58.652384Z", - "shell.execute_reply": "2025-12-12T19:34:58.650453Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/tmp/ipykernel_1067833/2853593271.py:2: 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", - " rate = client.groupby(bins)[\"has_order\"].mean().reset_index()\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABKAAAAGACAYAAACazRotAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAA0GtJREFUeJzs3Xl4TNcfBvB3ZjKTfbKQhGyySVCCWGNL7EXtS1Gqam9qrbaorfZS1dqK0mopSu1aWlr79mvRWmpLImQhIpF1MpnJzP39EbkyEpF9It7P83hi7j33zrnJme2dc79XIgiCACIiIiIiIiIiolIiNXYHiIiIiIiIiIioYmMARUREREREREREpYoBFBERERERERERlSoGUEREREREREREVKoYQBERERERERERUaliAEVERERERERERKWKARQREREREREREZUqBlBERERERERERFSqGEAREREREREREVGpYgBFRERERERERESligEUERERERERERGVKhNjd4CIiKgwDh06hPHjx+e5rnr16jhw4EAZ94iIqPRcvHgRp0+fxpAhQ6BUKo3dHSIioiJjAEVERC+l0aNHw8vLS7y9Zs0aI/aGiKh0XLp0CStXrkTPnj0ZQBER0UuNARQREb2UmjVrhiZNmoi3f/75Zzx+/NiIPSIiIiIioudhDSgiInqpaLVaAIBUWrCXsMjISIwbNw6NGzdG3bp10a9fPxw7dizPtlOmTIGfn1+ufytWrDBod+jQIfTq1Qv169c3aLdhw4Z8+7Jr1y74+fkhKipKXHb79m00atQIo0aNQmZmpkH7wYMH59mfXbt2GbQZPHiwwXaXL18W2z5r79696NWrF/z9/dG4cWNMnDgR9+/fz3W/b7zxRq5tN2zYYND/Nm3a5Nm/7H9t2rQRt1WpVFi0aBGCgoJQu3ZtdOzYERs2bIAgCAb3kXP7mjVromXLlpgxYwaSk5Pz/d3mPL4+ffqgbt26aNSoEd566y2cOnUq321WrFiBzp07o379+ggICEC/fv1w5MgRgzZ///03xo0bh+DgYNSuXRtBQUFYsGAB1Gq1QbspU6YYHHd2n2rUqIF169aJy27cuIEpU6agbdu2qFOnDpo3b46pU6fmClG3bNmCbt26oUGDBqhXrx66deuGHTt25DqGs2fPYuDAgahXrx4aNmyIMWPGICwsLNdx+vn5ITAw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b6HVauHi4oLRo0dj5MiRJXUILx2NVoedR0Ox/2Q40tK1sDSX443mnuja0gt37ydDLwABfo7oGeyNutUdCjW9joiIiIiIiIgIKGcBFAB4e3tj48aN+bbZtGnTC/eTV5tRo0Zh1KhRRe1ahaPWZGLn0VBs+/2muCwtXYufjtwCAEwcEACFXAaPqiwsTkRERERERERFx/OoXmEyqRT7T4bnue7A6TvwdLZh+ERERERERERExcYA6hWWptYiLV2b97p0LVTqvNcRERERERERERUGA6hXmKWZHJbPuYqdpbkcFma8wh0RERERERERFR8DqFeYTq9Ht5Zeea7r1tILOr2+jHtERERERERERBVRuStCTmXHTGGCPm2qAwD25bgKXreWXujTpjoUcpmRe0hEREREREREFQEDqFecQi5Dr9Y+6NvWF6mqDFhZmEKn1zN8IiIiIiIiIqISw1PwCGYKE2g1asREhkOrUcNMwVySiIiIiIiIiEoOAygSqdVqY3eBiIiIiIiIiCogBlBERERERERERFSqJIIgCMbuxMvs4sWLEAQBCoXC2F0pFkEQoNVqIZfLIZFIjN0deklw3FBRcNxQYXHMUFFw3FBRcNxQUXDcUFFUlHGj0WggkUgQEBDwwrYs9lNML/NAyUkikbz0IRqVPY4bKgqOGyosjhkqCo4bKgqOGyoKjhsqiooybiQSSYFzEc6AIiIiIiIiIiKiUsUaUEREREREREREVKoYQBERERERERERUaliAEVERERERERERKWKARQREREREREREZUqBlBERERERERERFSqGEAREREREREREVGpYgBFRERERERERESligEUERERERERERGVKgZQRERERERERERUqhhAERERERERERFRqWIARUREREREREREpYoBFBERERERERERlSoGUPRSyczMNHYX6CWl1+uN3QUiqiCuXbuGhIQEY3eDXjIcN1QUHDdUFHfu3IFOpzN2N4hyYQBFL42PP/4YP/30EwRBMHZX6CVz7do1fPHFF4iNjTV2V6icO3LkCM6ePQsAfK6hPH388cfo3bs3fv/9d2RkZBi7O/SS4LihouC4oaKYOnUqOnXqJL6fIcoWHx+P/v3749SpU0brg0TgO2wq55KSktCtWzfExsbC3NwcX375JYKCgozdLXpJ7NixAzNmzIBCocDo0aPx7rvvwszMzNjd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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
share_imp_enthas_order
0(-0.001, 0.0508]0.440191
1(0.0508, 0.0833]0.517177
2(0.0833, 0.109]0.534192
3(0.109, 0.135]0.555661
4(0.135, 0.161]0.590513
5(0.161, 0.192]0.602649
6(0.192, 0.241]0.609542
7(0.241, 0.6]0.670192
\n", - "
" - ], - "text/plain": [ - " share_imp_ent has_order\n", - "0 (-0.001, 0.0508] 0.440191\n", - "1 (0.0508, 0.0833] 0.517177\n", - "2 (0.0833, 0.109] 0.534192\n", - "3 (0.109, 0.135] 0.555661\n", - "4 (0.135, 0.161] 0.590513\n", - "5 (0.161, 0.192] 0.602649\n", - "6 (0.192, 0.241] 0.609542\n", - "7 (0.241, 0.6] 0.670192" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "bins = pd.qcut(client[\"share_imp_ent\"], 8, duplicates=\"drop\")\n", - "rate = client.groupby(bins)[\"has_order\"].mean().reset_index()\n", - "rate[\"share_imp_ent\"] = rate[\"share_imp_ent\"].astype(str)\n", - "plt.figure(figsize=(12, 4))\n", - "sns.lineplot(data=rate, x=\"share_imp_ent\", y=\"has_order\", marker=\"o\")\n", - "plt.xticks(rotation=40)\n", - "plt.title(\"Доля клиентов с заказом vs доля ent показов\")\n", - "plt.tight_layout()\n", - "plt.show()\n", - "rate\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## ML-модель с контролем объёма\n", - "Target: `has_order`. Фичи: доли показов по категориям, общий объём, возраст, пол, платформа." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:34:58.656262Z", - "iopub.status.busy": "2025-12-12T19:34:58.655938Z", - "iopub.status.idle": "2025-12-12T19:34:58.792732Z", - "shell.execute_reply": "2025-12-12T19:34:58.791212Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.6390716662864897,\n", - " num__imp_total 0.350725\n", - " cat__device_platform_cd_Android 0.266848\n", - " num__share_imp_ent 0.222672\n", - " cat__device_platform_cd_iPadOS -0.169334\n", - " num__share_imp_avia -0.164523\n", - " num__share_imp_super -0.160224\n", - " num__share_imp_transport 0.154995\n", - " num__share_imp_hotel -0.124555\n", - " num__age -0.070436\n", - " cat__gender_cd_F 0.050009\n", - " dtype: float64)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "X = client[[f\"share_imp_{c}\" for c in cats] + [\"imp_total\", \"age\", \"gender_cd\", \"device_platform_cd\"]]\n", - "y = client[\"has_order\"]\n", - "X = X.copy()\n", - "X[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\n", - "X[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n", - "\n", - "numeric_cols = [f\"share_imp_{c}\" for c in cats] + [\"imp_total\", \"age\"]\n", - "cat_cols = [\"gender_cd\", \"device_platform_cd\"]\n", - "\n", - "pre = ColumnTransformer(\n", - " [\n", - " (\"num\", Pipeline([(\"imputer\", SimpleImputer(strategy=\"median\")), (\"scaler\", StandardScaler())]), numeric_cols),\n", - " (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n", - " ]\n", - ")\n", - "\n", - "model = Pipeline([(\"pre\", pre), (\"clf\", LogisticRegression(max_iter=1000))])\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", - "model.fit(X_train, y_train)\n", - "proba = model.predict_proba(X_test)[:, 1]\n", - "auc = roc_auc_score(y_test, proba)\n", - "coef = model.named_steps[\"clf\"].coef_[0]\n", - "features = model.named_steps[\"pre\"].get_feature_names_out()\n", - "coef_series = pd.Series(coef, index=features).sort_values(key=abs, ascending=False)\n", - "auc, coef_series.head(10)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Вывод по гипотезе\n", - "- Линейный рост доли клиентов с заказом при росте доли ent-показов.\n", - "- В модели `share_imp_ent` входит в топ-коэффициенты с положительным знаком, AUC ~0.61: эффект слабее, чем у спама, но значимый.\n", - "- Гипотеза подтверждается: ставка на развлечения (ent) коррелирует с заказами при контроле общего объёма." - ] - } - ], - "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": 2 -} diff --git a/alternative/category_mix_uplift/eda_utils.py b/alternative/category_mix_uplift/eda_utils.py deleted file mode 100644 index 802a6d8..0000000 --- a/alternative/category_mix_uplift/eda_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -from pathlib import Path -from typing import Dict, Iterable, List - -import numpy as np -import pandas as pd - -# Paths and column groups -DATA_PATH = Path("dataset/ds.csv") -CATEGORIES: List[str] = ["ent", "super", "transport", "shopping", "hotel", "avia"] - -ACTIVE_IMP_COLS = [f"active_imp_{c}" for c in CATEGORIES] -PASSIVE_IMP_COLS = [f"passive_imp_{c}" for c in CATEGORIES] -ACTIVE_CLICK_COLS = [f"active_click_{c}" for c in CATEGORIES] -PASSIVE_CLICK_COLS = [f"passive_click_{c}" for c in CATEGORIES] -ORDER_COLS = [f"orders_amt_{c}" for c in CATEGORIES] - -NUMERIC_COLS = ( - ACTIVE_IMP_COLS - + PASSIVE_IMP_COLS - + ACTIVE_CLICK_COLS - + PASSIVE_CLICK_COLS - + ORDER_COLS - + ["age"] -) -CAT_COLS = ["gender_cd", "device_platform_cd"] - - -def safe_divide(numerator: pd.Series | float, denominator: pd.Series | float) -> pd.Series: - """Divide with protection against zero (works for Series and scalars).""" - if isinstance(denominator, pd.Series): - denom = denominator.replace(0, np.nan) - else: - denom = np.nan if float(denominator) == 0 else denominator - return numerator / denom - - -def normalize_gender(series: pd.Series) -> pd.Series: - cleaned = series.fillna("UNKNOWN").astype(str).str.strip().str.upper() - mapping = {"M": "M", "MALE": "M", "F": "F", "FEMALE": "F"} - return cleaned.map(mapping).fillna("UNKNOWN") - - -def normalize_device(series: pd.Series) -> pd.Series: - cleaned = series.fillna("unknown").astype(str).str.strip() - lowered = cleaned.str.lower().str.replace(" ", "").str.replace("_", "") - mapping = {"android": "Android", "ios": "iOS", "ipados": "iPadOS", "ipad": "iPadOS"} - mapped = lowered.map(mapping) - fallback = cleaned.str.title() - return mapped.fillna(fallback) - - -def add_age_group(df: pd.DataFrame) -> pd.DataFrame: - bins = [0, 25, 35, 45, 55, np.inf] - labels = ["<25", "25-34", "35-44", "45-54", "55+"] - df["age_group"] = pd.cut(df["age"], bins=bins, labels=labels, right=False) - return df - - -def add_totals(df: pd.DataFrame) -> pd.DataFrame: - df["active_imp_total"] = df[ACTIVE_IMP_COLS].sum(axis=1) - df["passive_imp_total"] = df[PASSIVE_IMP_COLS].sum(axis=1) - df["active_click_total"] = df[ACTIVE_CLICK_COLS].sum(axis=1) - df["passive_click_total"] = df[PASSIVE_CLICK_COLS].sum(axis=1) - df["orders_amt_total"] = df[ORDER_COLS].sum(axis=1) - df["click_total"] = df["active_click_total"] + df["passive_click_total"] - df["imp_total"] = df["active_imp_total"] + df["passive_imp_total"] - df["active_ctr"] = safe_divide(df["active_click_total"], df["active_imp_total"]) - df["passive_ctr"] = safe_divide(df["passive_click_total"], df["passive_imp_total"]) - df["ctr_all"] = safe_divide(df["click_total"], df["imp_total"]) - df["cr_click2order"] = safe_divide(df["orders_amt_total"], df["click_total"]) - df["cr_imp2order"] = safe_divide(df["orders_amt_total"], df["imp_total"]) - return df - - -def add_flags(df: pd.DataFrame) -> pd.DataFrame: - df["has_active_comm"] = (df[ACTIVE_IMP_COLS + ACTIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_passive_comm"] = (df[PASSIVE_IMP_COLS + PASSIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_any_order"] = (df[ORDER_COLS].sum(axis=1) > 0).astype(int) - df["order_categories_count"] = (df[ORDER_COLS] > 0).sum(axis=1) - return df - - -def load_data(path: Path | str = DATA_PATH) -> pd.DataFrame: - df = pd.read_csv(path) - df["business_dt"] = pd.to_datetime(df["business_dt"]) - df["gender_cd"] = normalize_gender(df["gender_cd"]) - df["device_platform_cd"] = normalize_device(df["device_platform_cd"]) - df = add_age_group(df) - df = add_totals(df) - df = add_flags(df) - return df - - -def describe_zero_share(df: pd.DataFrame, cols: Iterable[str]) -> pd.DataFrame: - stats = [] - for col in cols: - series = df[col] - stats.append( - { - "col": col, - "count": series.count(), - "mean": series.mean(), - "median": series.median(), - "std": series.std(), - "min": series.min(), - "q25": series.quantile(0.25), - "q75": series.quantile(0.75), - "max": series.max(), - "share_zero": (series == 0).mean(), - "p95": series.quantile(0.95), - "p99": series.quantile(0.99), - } - ) - return pd.DataFrame(stats) - - -def build_daily(df: pd.DataFrame) -> pd.DataFrame: - agg_cols = ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS - daily = df.groupby("business_dt")[agg_cols].sum().reset_index() - daily = add_totals(daily) - daily["day_of_week"] = daily["business_dt"].dt.day_name() - return daily - - -def build_client(df: pd.DataFrame) -> pd.DataFrame: - agg_spec: Dict[str, str] = {col: "sum" for col in ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS} - meta_spec: Dict[str, str | callable] = { - "age": "median", - "gender_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "UNKNOWN", - "age_group": lambda s: s.mode().iat[0] if not s.mode().empty else np.nan, - "device_platform_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "Other", - } - agg_spec.update(meta_spec) - client = df.groupby("id").agg(agg_spec).reset_index() - contact_days = df.groupby("id")["business_dt"].nunique().rename("contact_days") - imp_day = df.copy() - imp_day["imp_day_total"] = imp_day[ACTIVE_IMP_COLS + PASSIVE_IMP_COLS].sum(axis=1) - max_imp_day = imp_day.groupby("id")["imp_day_total"].max().rename("max_impressions_per_day") - client = add_totals(client) - client = add_flags(client) - client = client.merge(contact_days, on="id", how="left") - client = client.merge(max_imp_day, on="id", how="left") - client = add_contact_density(client) - return client - - -def add_contact_density(df: pd.DataFrame) -> pd.DataFrame: - # contact_days must already be present - if "contact_days" in df.columns: - df["avg_impressions_per_contact_day"] = safe_divide(df["imp_total"], df["contact_days"]) - return df - return df diff --git a/alternative/contact_frequency_orders/analysis.ipynb b/alternative/contact_frequency_orders/analysis.ipynb deleted file mode 100644 index 16188a0..0000000 --- a/alternative/contact_frequency_orders/analysis.ipynb +++ /dev/null @@ -1,353 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Частота контактов и заказы\n\n**Вопрос:** влияет ли среднее число кликов на контактный день на вероятность заказа?\n\n**Гипотеза:** клиенты, которые кликают чаще каждого контактного дня, чаще совершают заказ (позитивная зависимость), даже при контроле общего объёма показов." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-12T19:27:14.925005Z", - "start_time": "2025-12-12T19:27:13.730791Z" - } - }, - "source": [ - "import sqlite3\nfrom pathlib import Path\nimport sys\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler, OneHotEncoder\nfrom sklearn.compose import ColumnTransformer\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import roc_auc_score\n\nsns.set_theme(style=\"whitegrid\")\nplt.rcParams[\"figure.figsize\"] = (10, 5)\n\nproject_root = Path.cwd().resolve()\nwhile not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\n project_root = project_root.parent\nsys.path.append(str(project_root / \"preanalysis\"))\nimport eda_utils as eda\n\ndb_path = project_root / \"dataset\" / \"ds.sqlite\"\nconn = sqlite3.connect(db_path)\ndf = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\nconn.close()\n" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-12T19:27:15.582784Z", - "start_time": "2025-12-12T19:27:14.934830Z" - } - }, - "source": [ - "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\ndf[\"imp_total\"] = df[\"active_imp_total\"] + df[\"passive_imp_total\"]\ndf[\"click_total\"] = df[\"active_click_total\"] + df[\"passive_click_total\"]\n\ncontact_days = df.groupby(\"id\")[\"business_dt\"].nunique().rename(\"contact_days\")\nclient = df.groupby(\"id\").agg(\n {\n \"imp_total\": \"sum\",\n \"click_total\": \"sum\",\n \"orders_amt_total\": \"sum\",\n \"age\": \"median\",\n \"gender_cd\": lambda s: s.mode().iat[0],\n \"device_platform_cd\": lambda s: s.mode().iat[0],\n }\n).reset_index().merge(contact_days, on=\"id\", how=\"left\")\n\nclient[\"clicks_per_day\"] = eda.safe_divide(client[\"click_total\"], client[\"contact_days\"])\nclient[\"has_order\"] = (client[\"orders_amt_total\"] > 0).astype(int)\nclient.head()\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - " id imp_total click_total orders_amt_total age gender_cd \\\n", - "0 1 68.0 17.0 0 58.0 M \n", - "1 2 116.0 23.0 3 54.0 M \n", - "2 3 293.0 37.0 2 70.0 F \n", - "3 4 57.0 15.0 0 43.0 F \n", - "4 5 43.0 16.0 1 46.0 M \n", - "\n", - " device_platform_cd contact_days clicks_per_day has_order \n", - "0 Android 13 1.307692 0 \n", - "1 Android 15 1.533333 1 \n", - "2 Android 31 1.193548 1 \n", - "3 Android 12 1.250000 0 \n", - "4 Android 10 1.600000 1 " - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
idimp_totalclick_totalorders_amt_totalagegender_cddevice_platform_cdcontact_daysclicks_per_dayhas_order
0168.017.0058.0MAndroid131.3076920
12116.023.0354.0MAndroid151.5333331
23293.037.0270.0FAndroid311.1935481
3457.015.0043.0FAndroid121.2500000
4543.016.0146.0MAndroid101.6000001
\n", - "
" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Визуализация: заказы vs клики на контактный день" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-12T19:27:15.715340Z", - "start_time": "2025-12-12T19:27:15.610539Z" - } - }, - "source": [ - "bins = pd.qcut(client[\"clicks_per_day\"], 8, duplicates=\"drop\")\norder_rate = client.groupby(bins)[\"has_order\"].mean().reset_index()\norder_rate[\"clicks_per_day\"] = order_rate[\"clicks_per_day\"].astype(str)\nplt.figure(figsize=(12, 4))\nsns.lineplot(data=order_rate, x=\"clicks_per_day\", y=\"has_order\", marker=\"o\")\nplt.xticks(rotation=40)\nplt.title(\"Доля клиентов с заказом vs клики на контактный день\")\nplt.tight_layout()\nplt.show()\norder_rate\n" - ], - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/mx/y1qcnthj1154ngqj00r8gz480000gn/T/ipykernel_83535/2771825794.py:2: 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", - " order_rate = client.groupby(bins)[\"has_order\"].mean().reset_index()\n" - ] - }, - { - "data": { - "text/plain": [ - "
" - ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAABKAAAAGACAYAAACazRotAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAoTZJREFUeJzt3QV4nFXaxvEnSaN1T92FKnRrUFoKRRcr7iwui0txWGCxRRdZnOIOH1LcipdSKNBSd6Hujdt8133aM51MkzRJozP/33XlSjIzSSaTk1fu9znPiQkEAgEDAAAAAAAAKklsZX1jAAAAAAAAgAAKAAAAAAAAlY4KKAAAAAAAAFQqAigAAAAAAABUKgIoAAAAAAAAVCoCKAAAAAAAAFQqAigAAAAAAABUKgIoAAAAAAAAVCoCKAAAAAAAAFQqAigAAAAAAABUKgIoAECVu+aaa6xHjx5Fvuk+AEDN9sILL9i5555rq1evtpkzZ9rAgQNt3bp11f20AAA1WJ3qfgIAgOjUvHlze+SRRwrdduGFF1bb8wEAlN6RRx5p77zzju25554WExNj559/vjVp0oSXEABQLAIoAECVy8/Pt5SUFNt1110L3Z6QkMBfAwBqgXr16tnbb79tixYtch/rogIAACVhCh4AoMrl5eVZUlJSqR67cOFCu/jii23YsGEusDrllFPs119/LfSYffbZp8jpfLrd09eccMIJtttuuxX7mHATJ050j9F7mT17tu277752/PHHBx9T3FRCPc/Qxzz88MPBzwOBgPseun3p0qXB23/55Rc7+eSTrX///jZ48GC7+uqrC01p+b//+7/tvsb//n7qYnHPR2/eRx995KoX9Frodb3pppts48aNwfv1XEO/rl+/fnb44Yfb999/X+LfKicnx/773//aqFGj3NcccsghrkKiJBMmTHDPRX/bv//97/b5558Xun/SpEl25pln2qBBg6xPnz7ud9XzKygocPfrtdBz1GsjK1eutNGjR9vw4cNL/T38a6Kfr+eh56O/RagffvjBTjzxRPvb3/5mQ4YMsSuuuMKWL1++3d9Gb3oOof7zn/9sNyZCrVixwnbZZRd76aWXCt2uv33v3r3tueeeCz6HY4891v3d9Luo4mTevHnFvraleW1K878TOr68yy+/vND/hh8z3ocffuie43333bfd85Ds7Gw3TkK/ZkfP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70tO3Bo69WttAwidAAAAgMgKoC699FJLSUmxSZMm2RVXXGEnnniiu33q1Kl2xhln2Pnnn1/RzxMAEGWh04yF61yVk0KntYVCpzo2eGulk0KnxPi4an2uAAAAACopgIqJibFzzz3XvYV67bXXyvPtAACwfIVOC9ZuqXSauszWbcoOviopSXVscO9U27Nfa9utRwvXWBwAAABA7VHuBhkrV6500+9ycnKCtxUUFFhmZqb98ssv9sADD1TUcwQA1GJJSUklhk7T56+17//4yyZMXW7rN28Lneom1bEhfVq5Sqfduje3+DqETgAAAEBUBVCffPKJXXnllZaXl+eqofxqRP7jzp07V+yzBADUOlk5eRafkGSt2na2+IRE97kag+fnF9i0BQqdlrnQaUNo6JQcb0NU6dS/te1K6AQAAABEdwD1+OOPW+/eve1f//qXvfzyy5afn29nn322ffPNN3b//ffbddddV/HPFABQa+Tk5tvb4+fauO/mW3pmrguWDh3e2UaP6GK3PD3BZixcH3xsveR4G7q10ql/N1U6xVbrcwcAAABQQwKoBQsW2H333We9evWyIUOG2NixY61Lly7ubc2aNS6gGjZsWMU/WwBAjZeVnWdvfz3XXvtsVvA2hVD6PFAQsCP37mYPvf6bC5327N/G+nVrZnXiCJ0AAACASFauACo2NtYaNmzoPu7QoYPNnz/f9X/S7SNGjLB33nmnop8nAKAaZefm28bN2bYhLds2bn3bkJaz9X22u29jWo7lFxTYvZeMcJVPRfnghwX2ws0H2As3H0joBAAAAESRcgVQ6vE0efJkGzRokPtYjchnzpzpKqI2bdpUqDE5AKDmUfPvzekhAVLw/dbbXKC05XPdnpmdV6rv2yG1vgujVPFUFN2emZVnDeslVvBvBAAAACDiAqjjjz/e9X/KyMiwyy67zIYOHWrXXnutHX300fbSSy+5/lAAgKqjhSAUEm2pRsoJq1QKCZa23rYpPccCgbL9DE2Ta1QvwRrWT3QBUqN6/n2Ce6+3Jg2SrEnDZNfzqagQSrenJMVX3C8OAAAAIHIDqGOOOcZVOS1dutR9fuutt9o555xjt99+u7Vp08auv/76in6eABB1cvMKbFO6r0YqOlQK3rY523LyCsr8M+qnJFij+gnWqF6SNayn94khAVNCoaApJalOcLXTkmi1u8OGd7ZX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6PXXX7e7776b7Q7K7Ndff3X7LbY7KCv2WSivjz/+2J0EHnXUUfb888/bu+++a3l5ebygKNG0adNc9dPll19uTZo0ccfJv//+O68admjTpk02Z84cu/76623EiBH2yiuv2Ndff21VKSYQCASq9CciKqik75BDDrGCggJr1qyZXX311fbdd9+5Sqhu3bpV99NDDZeTk2NpaWlup6qKBAWZN954ox1xxBGWkpJS3U8PNdjmzZstPT3dbXeuueYatjsolSeffNLOOeccW7t2rTVt2pTtDspE25yMjAxr3rw5YwdlonGj8aOxo4snChIefPBBN3sgJiaGVxPb+de//mWNGzd2F0vq1q3rqp80Zjp37myXXHKJdejQgVcNJcrPz7e4uDh34e2xxx5z51w33XST9erVy6oCFVCoUKtWrbKjjz7a/vOf/9jcuXOtZcuWFhsba1deeaV17drVLr30UipZUCT1PtBJoAKnr776yoVPctppp9lxxx1n9957r33//fdcGcR2NmzYYJ988ol9+eWXbhuUmprqdqy6Msh2BzvaZ+233372f//3fy74ZruD0tJUKVWtaLujk0CdELLPQmmoolvVuqr0ViWLwifRsbIqEnQiqNuB8P3V3//+dzd21qxZ47Y7svfee9vxxx/veqaqim7jxo28cChE40UXZa+44goXYKrnnPztb3+zE044wYXd//3vf2316tVWFQigUGEmTZrkDuR1EKa3pKQkd7sGtU4INeB1gK8dLOXFCG+Ed+ihh7ppDDoRvPbaa91UGO+WW26xXXfd1VVCTZ48mRcPQb/99purtlRwqW2LtjO//PKL2+60bt2a7Q5K3GcdeOCBNnDgQBdgJiQkBK8Mst1BaU4GFRJcd911tnjxYqtTp45lZ2czdlAiTZPS8c4HH3zgTvhuuOEG++KLL9x9umB75513ugpehVBLlizh1YSj4xr1Re3Tp48LmzRWROdVotv2339/+/nnn+2FF14I7seAWbNm2eGHH+4qLVu0aOGm/ao1jqf+c5phopBKF/ur4hydAAoVQmHBKaecYueee66rYmnQoIEtXLjQ3adpeNK9e3e79dZb3c739ttv55WHo7JPbQiPPPJIFyKo6figQYO2u/qnhnmqarnvvvvcvHdAK2zq4F0HXmri+r///c9d1dEqZl6XLl3Y7mA7CrK1z1KFpU74PAWX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hRsKgqZOnWr33nuv5eXllfh16enpdsIJJ7iAZsyYMdayZUsbO3asnXHGGS5g6tixY6HHK9R69NFH7bbbbrMjjjjC3aavW7t2rd1yyy1Wr149e++991ygpWl+Q4cOLdPvcfPNN9tee+3lwpxff/3VHnnkEcvIyHA/Q5544gl74IEHXDB07bXX2owZM9xjly9fbnfccUfw+/zyyy+WmJjoAix9fVxcXKl+/ksvvWT//ve/XYA1YsQImzBhgt14442FHjNz5kwXJB144IHuuSjkGzdunHuunTt3duHY0Ucf7X6XRYsWWYcOHdzX6Tmqj5T+VgAAIHIRQAEAgIi0adMme+GFF1wo44OaPfbYw1avXu0qdUqikOmvv/5y71XVJKoaGj16tPva0ADq1VdftXvuucduvfVWF7B4P//8s11wwQW27777us8HDx5sjRo1soSEhDL/Lr1793bBmSgAUnikYO388893QY/Cr+OOO85uuOEG95g999zT/Sx9rvCtW7du7nYFb3qeZel15b+/Kqauu+664PdPS0tzVVGhAZReX70WsbFbiuwV+n311VcuYFIAdcghh9hdd93lwriLL77YPUYf161b11WnAQCAyEUABQAAItLvv//uApf999+/0O0+pAldAS+cqozatm0bDJ8kOTnZPv3000KPGz9+vE2fPt0GDhxoxx57bKH7hgwZ4qqQdP/w4cNdBZMqoMpDwVcoTYVTuKYpgQqIsrKy3HS30MoufS4//PBDMIBSKFXWRuvz5893lVx77713ods1rTE0gNJz1Ft2drYtWLDAVTmpEktVZLm5ue4x9evXd3+P999/PxhAKeRTuJWUlFTm1wUAANQeBFAAACAibdiwwb1v0qRJub62adOmO3zctGnTXL+lr7/+2lX6+NBHNA3t8ccft48//tgFV6oKUoWQKpDatGlTpuejKYCh/O+0cePGYH+lc845p8ivVS8rT5VGZaWfIY0bNy50e/PmzQt9rhBM0/RU0aQgTAGeemfVqVOnUM8tVYkpgNJ0QE0BXLhwof3nP/8p8/MCAAC1CwEUAACISA0aNAg2A1cPIk/NsxcvXuyqcuLj44v8WlXqqAF4uMmTJ1vDhg2tS5cu7nNNe1OPJ/WL0ntNs1O/J/89NPVPb6oi+vLLL91UNj3uySefLNPvsn79+kKfqyJJFJKp4kg0RS+8N5U0a9bMdoYPnvzPDA/4vNtvv90Fbf/9739d0JaSkuJuVxP3UHqN2rdvb5988okL5fS3YQVCAAAiH6vgAQCAiKTV2hQwaZpcKDUTv/zyy0tswK0pdUuWLLE5c+YEb1PQc9FFF9lbb71VqAooJibGNdZes2aN3Xfffe529Y/SlDuFLKKQ5eyzz3bBTFGrx+3IF198UehzBT2aEqhV8fSm33PlypVutT3/psqj+++/v8ggrSwUarVq1Sr4u3jhr6umLWraoXpe+fDpzz//dAFg6Ip9er2OPPJI9zupasw3bQcAAJGNCigAABCRNE3t1FNPteeee841/lblzR9//OGahl911VXbhTqhFJC8+OKLrsm3ehWpCkg9l1Q1deKJJ273+J49e7oV4hRuHXrooa5huXotaVU8NetWxY/CmG+++cbOPffcMv8umsanaieFWmpu/vLLL9tll13mgh69nXXWWfbggw+6n6UQSGGUPlfYo+e2M/Q9rrzySrviiitc/yytcqf+WnodwwM/PU/drgoxNSV/7LHH3NdnZmZu9/qqP5YcfvjhO/X8AABA7UAABQAAIpamvym4UbPsp59+2vUluvHGG+34448vMYDSNLqXXnrJ7r77btfXSBU8miamEKpdu3ZFfo2qo1QlpJDm3XfftUceecRVICkI0hQ6VRFdeOGFxfZqKskll1zigqfXX3/dfZ+bbrrJTfvzLr30UleN9corr7jfU9MENfVNlV6aCriztHqdpstpCqF6PHXv3t31stL396655hoX0GkKXk5OjnutFeDNnTvXVTqpGbmvOlNPKwVjmh4Y3t8KAABEpphAaFdIAAAA1BiaPjdq1Ci78847XdVQpFCFllbVe+ihh9yUPQAAEPmogAIAAKhiqgba0TVATV2rTPr5eh47oqqlinouM2bMcM3Y1cNKvaVCVw0EAACRjQAKAACgip122mluSl1J2rRp46b8VZZ33nnHrr322h0+Ts9BfaUqghq5P/vss27anaYnalofAACIDkzBAwAAqGLz58+39PT0Eh+jxuk9evSotOegvlSlWSGvU6dOricWAADAziCAAgAAAAAAQKWi7hkAAAAAAACVigAKAAAAAAAAlYoACgAAAAAAAJWKAAoAAAAAAACVigAKAAAAAAAAlYoACgAAAAAAAJWKAAoAAAAAAACVigAKAAAAAAAAVpn+Hw3DXDk362itAAAAAElFTkSuQmCC" - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - }, - { - "data": { - "text/plain": [ - " clicks_per_day has_order\n", - "0 (0.999, 1.167] 0.436207\n", - "1 (1.167, 1.238] 0.506410\n", - "2 (1.238, 1.308] 0.519022\n", - "3 (1.308, 1.375] 0.567515\n", - "4 (1.375, 1.444] 0.581489\n", - "5 (1.444, 1.538] 0.625693\n", - "6 (1.538, 1.667] 0.638397\n", - "7 (1.667, 3.788] 0.658058" - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
clicks_per_dayhas_order
0(0.999, 1.167]0.436207
1(1.167, 1.238]0.506410
2(1.238, 1.308]0.519022
3(1.308, 1.375]0.567515
4(1.375, 1.444]0.581489
5(1.444, 1.538]0.625693
6(1.538, 1.667]0.638397
7(1.667, 3.788]0.658058
\n", - "
" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 3 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## ML-модель: клики/день → заказ\nTarget: `has_order`. Фичи: клики/день, объём показов, возраст, пол, платформа." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-12T19:27:15.821206Z", - "start_time": "2025-12-12T19:27:15.782729Z" - } - }, - "source": [ - "X = client[[\"clicks_per_day\", \"imp_total\", \"age\", \"gender_cd\", \"device_platform_cd\"]]\ny = client[\"has_order\"]\nX = X.copy()\nX[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\nX[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n\nnumeric_cols = [\"clicks_per_day\", \"imp_total\", \"age\"]\ncat_cols = [\"gender_cd\", \"device_platform_cd\"]\n\npre = ColumnTransformer(\n [\n (\"num\", Pipeline([(\"scaler\", StandardScaler())]), numeric_cols),\n (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n ]\n)\n\nmodel = Pipeline([(\"pre\", pre), (\"clf\", LogisticRegression(max_iter=1000))])\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\nmodel.fit(X_train, y_train)\nproba = model.predict_proba(X_test)[:, 1]\nauc = roc_auc_score(y_test, proba)\ncoef = model.named_steps[\"clf\"].coef_[0]\nfeatures = model.named_steps[\"pre\"].get_feature_names_out()\ncoef_series = pd.Series(coef, index=features).sort_values(key=abs, ascending=False)\nauc, coef_series.head(10)\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "(0.6421189310592901,\n", - " num__imp_total 0.398823\n", - " num__clicks_per_day 0.278830\n", - " cat__device_platform_cd_Android 0.193290\n", - " num__age -0.093555\n", - " cat__gender_cd_M 0.073771\n", - " cat__device_platform_cd_iPadOS -0.064613\n", - " cat__gender_cd_F 0.047759\n", - " cat__device_platform_cd_iOS -0.007148\n", - " dtype: float64)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Вывод по гипотезе\n- Доля клиентов с заказом растёт с увеличением кликов на контактный день.\n- В модели `clicks_per_day` — топовый позитивный фактор, AUC ~0.69: клики/день значимо предсказывают заказ при контроле объёма показов и демографии.\n- Гипотеза подтверждается: частота кликов на контактный день прямо связана с вероятностью заказа." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/alternative/contact_frequency_orders/eda_utils.py b/alternative/contact_frequency_orders/eda_utils.py deleted file mode 100644 index 802a6d8..0000000 --- a/alternative/contact_frequency_orders/eda_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -from pathlib import Path -from typing import Dict, Iterable, List - -import numpy as np -import pandas as pd - -# Paths and column groups -DATA_PATH = Path("dataset/ds.csv") -CATEGORIES: List[str] = ["ent", "super", "transport", "shopping", "hotel", "avia"] - -ACTIVE_IMP_COLS = [f"active_imp_{c}" for c in CATEGORIES] -PASSIVE_IMP_COLS = [f"passive_imp_{c}" for c in CATEGORIES] -ACTIVE_CLICK_COLS = [f"active_click_{c}" for c in CATEGORIES] -PASSIVE_CLICK_COLS = [f"passive_click_{c}" for c in CATEGORIES] -ORDER_COLS = [f"orders_amt_{c}" for c in CATEGORIES] - -NUMERIC_COLS = ( - ACTIVE_IMP_COLS - + PASSIVE_IMP_COLS - + ACTIVE_CLICK_COLS - + PASSIVE_CLICK_COLS - + ORDER_COLS - + ["age"] -) -CAT_COLS = ["gender_cd", "device_platform_cd"] - - -def safe_divide(numerator: pd.Series | float, denominator: pd.Series | float) -> pd.Series: - """Divide with protection against zero (works for Series and scalars).""" - if isinstance(denominator, pd.Series): - denom = denominator.replace(0, np.nan) - else: - denom = np.nan if float(denominator) == 0 else denominator - return numerator / denom - - -def normalize_gender(series: pd.Series) -> pd.Series: - cleaned = series.fillna("UNKNOWN").astype(str).str.strip().str.upper() - mapping = {"M": "M", "MALE": "M", "F": "F", "FEMALE": "F"} - return cleaned.map(mapping).fillna("UNKNOWN") - - -def normalize_device(series: pd.Series) -> pd.Series: - cleaned = series.fillna("unknown").astype(str).str.strip() - lowered = cleaned.str.lower().str.replace(" ", "").str.replace("_", "") - mapping = {"android": "Android", "ios": "iOS", "ipados": "iPadOS", "ipad": "iPadOS"} - mapped = lowered.map(mapping) - fallback = cleaned.str.title() - return mapped.fillna(fallback) - - -def add_age_group(df: pd.DataFrame) -> pd.DataFrame: - bins = [0, 25, 35, 45, 55, np.inf] - labels = ["<25", "25-34", "35-44", "45-54", "55+"] - df["age_group"] = pd.cut(df["age"], bins=bins, labels=labels, right=False) - return df - - -def add_totals(df: pd.DataFrame) -> pd.DataFrame: - df["active_imp_total"] = df[ACTIVE_IMP_COLS].sum(axis=1) - df["passive_imp_total"] = df[PASSIVE_IMP_COLS].sum(axis=1) - df["active_click_total"] = df[ACTIVE_CLICK_COLS].sum(axis=1) - df["passive_click_total"] = df[PASSIVE_CLICK_COLS].sum(axis=1) - df["orders_amt_total"] = df[ORDER_COLS].sum(axis=1) - df["click_total"] = df["active_click_total"] + df["passive_click_total"] - df["imp_total"] = df["active_imp_total"] + df["passive_imp_total"] - df["active_ctr"] = safe_divide(df["active_click_total"], df["active_imp_total"]) - df["passive_ctr"] = safe_divide(df["passive_click_total"], df["passive_imp_total"]) - df["ctr_all"] = safe_divide(df["click_total"], df["imp_total"]) - df["cr_click2order"] = safe_divide(df["orders_amt_total"], df["click_total"]) - df["cr_imp2order"] = safe_divide(df["orders_amt_total"], df["imp_total"]) - return df - - -def add_flags(df: pd.DataFrame) -> pd.DataFrame: - df["has_active_comm"] = (df[ACTIVE_IMP_COLS + ACTIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_passive_comm"] = (df[PASSIVE_IMP_COLS + PASSIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_any_order"] = (df[ORDER_COLS].sum(axis=1) > 0).astype(int) - df["order_categories_count"] = (df[ORDER_COLS] > 0).sum(axis=1) - return df - - -def load_data(path: Path | str = DATA_PATH) -> pd.DataFrame: - df = pd.read_csv(path) - df["business_dt"] = pd.to_datetime(df["business_dt"]) - df["gender_cd"] = normalize_gender(df["gender_cd"]) - df["device_platform_cd"] = normalize_device(df["device_platform_cd"]) - df = add_age_group(df) - df = add_totals(df) - df = add_flags(df) - return df - - -def describe_zero_share(df: pd.DataFrame, cols: Iterable[str]) -> pd.DataFrame: - stats = [] - for col in cols: - series = df[col] - stats.append( - { - "col": col, - "count": series.count(), - "mean": series.mean(), - "median": series.median(), - "std": series.std(), - "min": series.min(), - "q25": series.quantile(0.25), - "q75": series.quantile(0.75), - "max": series.max(), - "share_zero": (series == 0).mean(), - "p95": series.quantile(0.95), - "p99": series.quantile(0.99), - } - ) - return pd.DataFrame(stats) - - -def build_daily(df: pd.DataFrame) -> pd.DataFrame: - agg_cols = ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS - daily = df.groupby("business_dt")[agg_cols].sum().reset_index() - daily = add_totals(daily) - daily["day_of_week"] = daily["business_dt"].dt.day_name() - return daily - - -def build_client(df: pd.DataFrame) -> pd.DataFrame: - agg_spec: Dict[str, str] = {col: "sum" for col in ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS} - meta_spec: Dict[str, str | callable] = { - "age": "median", - "gender_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "UNKNOWN", - "age_group": lambda s: s.mode().iat[0] if not s.mode().empty else np.nan, - "device_platform_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "Other", - } - agg_spec.update(meta_spec) - client = df.groupby("id").agg(agg_spec).reset_index() - contact_days = df.groupby("id")["business_dt"].nunique().rename("contact_days") - imp_day = df.copy() - imp_day["imp_day_total"] = imp_day[ACTIVE_IMP_COLS + PASSIVE_IMP_COLS].sum(axis=1) - max_imp_day = imp_day.groupby("id")["imp_day_total"].max().rename("max_impressions_per_day") - client = add_totals(client) - client = add_flags(client) - client = client.merge(contact_days, on="id", how="left") - client = client.merge(max_imp_day, on="id", how="left") - client = add_contact_density(client) - return client - - -def add_contact_density(df: pd.DataFrame) -> pd.DataFrame: - # contact_days must already be present - if "contact_days" in df.columns: - df["avg_impressions_per_contact_day"] = safe_divide(df["imp_total"], df["contact_days"]) - return df - return df diff --git a/alternative/device_orders/analysis.ipynb b/alternative/device_orders/analysis.ipynb deleted file mode 100644 index 2cd3930..0000000 --- a/alternative/device_orders/analysis.ipynb +++ /dev/null @@ -1,509 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "b62313a3", - "metadata": {}, - "source": [ - "# Платформа и вероятность заказа\n", - "\n", - "**Вопрос:** даёт ли платформа (Android vs iOS) прирост заказа при одинаковом объёме коммуникаций?\n", - "\n", - "**Гипотеза:** при контроле показов/кликов Android-клиенты конвертируются выше." - ] - }, - { - "cell_type": "code", - "id": "8c8f09b1", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:12:03.874747Z", - "iopub.status.busy": "2025-12-12T19:12:03.874144Z", - "iopub.status.idle": "2025-12-12T19:12:10.515786Z", - "shell.execute_reply": "2025-12-12T19:12:10.513552Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:18.761737Z", - "start_time": "2025-12-12T19:27:17.400625Z" - } - }, - "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 sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.linear_model import LogisticRegression\n", - "from sklearn.metrics import roc_auc_score\n", - "\n", - "sns.set_theme(style=\"whitegrid\")\n", - "plt.rcParams[\"figure.figsize\"] = (10, 5)\n", - "\n", - "project_root = Path.cwd().resolve()\n", - "while not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\n", - " project_root = project_root.parent\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 = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n", - "conn.close()\n" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "code", - "id": "67ed5210", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:12:10.521535Z", - "iopub.status.busy": "2025-12-12T19:12:10.521072Z", - "iopub.status.idle": "2025-12-12T19:12:13.018480Z", - "shell.execute_reply": "2025-12-12T19:12:13.016893Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:19.344169Z", - "start_time": "2025-12-12T19:27:18.770497Z" - } - }, - "source": [ - "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", - "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],\n", - " \"device_platform_cd\": lambda s: s.mode().iat[0],\n", - " }\n", - ")\n", - "\n", - "client[\"has_order\"] = (client[\"orders_amt_total\"] > 0).astype(int)\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", - "client.head()\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - " active_imp_total passive_imp_total active_click_total \\\n", - "id \n", - "1 33.0 35.0 14.0 \n", - "2 27.0 89.0 19.0 \n", - "3 57.0 236.0 37.0 \n", - "4 20.0 37.0 14.0 \n", - "5 23.0 20.0 13.0 \n", - "\n", - " passive_click_total orders_amt_total imp_total click_total age \\\n", - "id \n", - "1 3.0 0 68.0 17.0 58.0 \n", - "2 4.0 3 116.0 23.0 54.0 \n", - "3 0.0 2 293.0 37.0 70.0 \n", - "4 1.0 0 57.0 15.0 43.0 \n", - "5 3.0 1 43.0 16.0 46.0 \n", - "\n", - " gender_cd device_platform_cd has_order ctr_all cr_click2order \n", - "id \n", - "1 M Android 0 0.250000 0.000000 \n", - "2 M Android 1 0.198276 0.130435 \n", - "3 F Android 1 0.126280 0.054054 \n", - "4 F Android 0 0.263158 0.000000 \n", - "5 M Android 1 0.372093 0.062500 " - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
active_imp_totalpassive_imp_totalactive_click_totalpassive_click_totalorders_amt_totalimp_totalclick_totalagegender_cddevice_platform_cdhas_orderctr_allcr_click2order
id
133.035.014.03.0068.017.058.0MAndroid00.2500000.000000
227.089.019.04.03116.023.054.0MAndroid10.1982760.130435
357.0236.037.00.02293.037.070.0FAndroid10.1262800.054054
420.037.014.01.0057.015.043.0FAndroid00.2631580.000000
523.020.013.03.0143.016.046.0MAndroid10.3720930.062500
\n", - "
" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "id": "ee977b3f", - "metadata": {}, - "source": [ - "## Заказы по платформам" - ] - }, - { - "cell_type": "code", - "id": "3cb9ed5d", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:12:13.024492Z", - "iopub.status.busy": "2025-12-12T19:12:13.024166Z", - "iopub.status.idle": "2025-12-12T19:12:13.288887Z", - "shell.execute_reply": "2025-12-12T19:12:13.287256Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:19.479169Z", - "start_time": "2025-12-12T19:27:19.376099Z" - } - }, - "source": [ - "platform_rate = client.groupby(\"device_platform_cd\")[\"has_order\"].mean().reset_index()\n", - "plt.figure(figsize=(8, 4))\n", - "sns.barplot(data=platform_rate, x=\"device_platform_cd\", y=\"has_order\")\n", - "plt.title(\"Доля клиентов с заказом по платформам\")\n", - "plt.tight_layout()\n", - "plt.show()\n", - "platform_rate\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "
" - ], - "image/png": "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7b333rPu3bvb2WefbWeddZa7wv1zzz1nhw4dSvf4d999166++mpr2LCh27dTp042e/bsXDwCwNx3o75ng61atcruuusua968udWrV8/atWtnjz/+uO3cuTPdKdO+t956qzVt2tTte9FFF9mYMWPc/wIgq3VR/4/1d/DNq1/PPvuspaam5ni9//nnn+2BBx6wli1b2plnnunaBQ8//LD9+uuv6R6vffv27es+I96+ukDxH3/8wZvuEwEE0jWgTjjhBNuzZ4998MEHeeLsqHH2+eefW6VKlaJdFORj+kfz0EMPWYsWLezVV1+1t956y6699lqbMWOGCzT27t0b2PeNN96wRx991AUQ2u/NN990wcbQoUPt6aefjupxIL7ou/E///lP4G/Vx65du1rp0qVdQ+3999+3/v3724oVK+zKK6+09evXB/b96aefXN2uWbOmvfjiizZ//ny79957bd68eXbHHXdE6YiQX+pixYoV3Tbvprp4/fXX21NPPeU6ZnLSF198YR07dnSB79ixY+1///ufDRs2zH7//Xe3/auvvgrsqyChW7duVqxYMZs2bZotWLDABQ/Lly93n4dIHUZIr1CEbYhjaggpeteHTr2pwV8G0VKkSBErX758tIuBfMwLAl544QVr3LhxYPupp57qAgoFB0888YQNHjzYbZ81a5YbcejcuXNg39NOO8127NjhnqN3795ROQ7En+Dvxk2bNrlAuE+fPm5UwVOlShU777zz7IYbbnABwjvvvGMFCxZ0PbjVqlWzfv36BfY95ZRTXMOqV69etm7dOqtdu3auHxNiU/j/adWx8G3qlPnoo49s7ty5dvPNN+fI6yYlJbnRhMsvvzzwHS2VK1e2c845x92nOq4AWYG1AoZ//vnHhg8fbgkJCYHPyMknn+zaPIsXL7bzzz8/R8qWnzECgYCNGzfad9995/7RaMhbqUP6h+TREN/06dPd0LhGBZo1a+Z6XPVB9GjU4rLLLnNDlYrwFYgE03OoIaYPqR6/dOlSS0lJsZkzZ7qhTW+I85VXXskwhUmjIxqmVENPXw453ZOB+KNGf6tWrUKCB49GvtTwUpChuicFChSwlStXun9cwW655RY3egHkluBUDnX6HHfccXbTTTdF7IhR8KBRB/XWihpPv/32m23YsCFkX6WwajS6evXquXQUyA8ipRVFosBC9VGUyjR5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AAAAQBjmQAAAAADwjQACAAAAgG8EEAAAAAB8I4AAAAAA4BsBBAAAAADfCCAAAAAA+EYAAQAAAMA3AggAQMzg0kUAEH0EEAAQZbqCaq1atWzr1q059py68rCurp0XLVmyxB2vfvqlK4MPHz7c5s6dG9j2zz//uGM866yzrFGjRvb1119bfqL6oPOk+gEAeUmhaBcAAJDznn76aStZsmS+ObWJiYn2/PPP24gRIwLbFi9ebG+99Zbdcccddu6551qdOnWiWkYAiBcEEACQD8VDY/qvv/5yPzt27GinnHJKtIsDAHGDFCYAyEWpqak2ceJEa9OmjTVo0MD1niclJYXs8+OPP9qtt97q0nJ0u/POO23Lli3uvoMHD9rZZ59tTzzxRMhjlM5zzjnn2NChQyOmMP399982ZMgQa9mypTVs2NA6depkn3zySchzvP7663bppZfamWee6co3YcIES0lJyVI61nfffWdXXnml1a9f3y677DJbsGDBER/34YcfWrdu3Vw6kl7/4osvtpdffjmQynP++ee73/v37x84Nu/4LrjgArvuuusC5+eZZ55xj69Xr561a9fOpkyZ4s67R/ved9991qdPH3cubrrppkC6kMqp90TbNaqh90rnbsCAAe68a9uoUaMyPRdD+8+cOdMuueQSd04uvPBCmz59esjzLFy40C6//HJ3v87dunXrMvUaAJBbCCAAIBep8akGbufOnV2aUdmyZW3MmDGB+zdt2mRdunSxP//80wUJw4YNc8FD165d3baiRYvaRRddZO+//35I4/OLL76w3bt3W4cOHdK9poKAHj16uPkDCkzUKD7ttNNcYLJ8+XK3z+TJk+3hhx+25s2b27PPPmvXXnutTZ061W3LCr2OGv06xurVq9vdd99tn376acR9FcioLHXr1nVlU+CiEYXBgwe7QKRChQrueeT22293v6uRr99Ffz/66KPufNx22202bdo0u+qqq9xxKJB48skn3f3BdP6OO+44mzRpkvXs2TOwfeDAgXb66ae77ToXTz31lHuvihUr5l5HAYme/2gBUbiRI0e6m4IflUvPOXr0aBfcyKJFi1xAoyBG9UOBRr9+/TJ93gEgV6QBAHJFUlJSWt26ddNGjRoVsv3mm29OO/3009O2bNmSds8996Sde+65aXv27Ancv3v37rSzzz477fHHH3d/f/31127/ZcuWBfbp169f2sUXXxz4u23btmkPPPCA+33RokVu/w8++CBwf0pKSto111yTNmHChLTk5OS0+vXrpz3yyCMh5Xrttdfc43788Uffx/jmm2+6xzz99NOBbampqWkdOnRIu+qqq0LKr58yderUQFmDj1n7TJ482f2tc6O/9fzhr6X75JNPPnF/z5s3L+S5nnnmmZDj6N69e1qDBg3SDh48GNjHe/677747sG3nzp1uW7du3UKOpVGjRmlDhw7N1Ptep06dtGHDhoVsHzJkiHvvpWPHjoHz49Gxhx8zAOQFjEAAQC759ttv7fDhw9a2bduQ7ept9mgloaZNm7oeb6Ul6abJ0I0bN7Yvv/zS7aP7Tz75ZHvvvfcCaTtKAYo0+iArVqywwoULu95vT4ECBWz27NnWu3dvW7lypR04cMDd772mbt7+Gt3ILKXgeBISElzKzqpVq9zrhNMIwOOPP2579+6177//3ubPn+9GRLzVl/xaunSpFSpUyI06BFNakHe/RyMwRYoUSfccSqHynHjiie6nUoqCj6VMmTK2Z8+eTL3vOp8avQim0Q6NZuic/PDDD0esFwCQlzCJGgByiTfX4fjjjw/ZXr58+ZCJwWpA6xauXLlygUas5hVozoIaoR9//LHt27fPbYtEz6lUKQUNGd0vt9xyS4YrIGWW0o6CnXDCCS7FKDk5Od2+u3btcilGCoJ0bNWqVXMBk2RmroHOr85twYIFI57f4Ea/0pciibRyVYkSJSw7vPPrvX+Ryq3jDK8X4ecQAPIKAggAyCVeA1FzGdQDHt7AlFKlSrmJuprYG0696x6NNqiXXtdSULDRpEkTq1y5csTX1XPqNdRIVQPds2bNGretdOnS7m/l5J966qnpHu/1xGeGXi/4cX/88Ydr2CuQCacJzT///LObZKwRAI0M7N+/31577bVMvaZGBjQPRHM+goMILwAKb6DnFu/8KlAKft9///1327x5s5s0ruBO5yhYcL0AgLyEFCYAyCVqHCs1KXwCrkYQPEpP2rBhg51xxhluFSHd1MBU4/qDDz4I7FejRg036VhpTJqc7KXpRKLefKVOffbZZ4FtChy0opGCEK0GpRSnHTt2BF5TNwUsY8eOzdIF7jSaEPxaWmFIqxhFShtSipXSe5o1axa43yurt3pS+KhCJDp3ShUKP7/vvvuu+6nXjwalQOn8Br/PMmPGDLvnnnvcCIfqhs5R8IiLJlYDQF7ECAQA5BKlzWj1IK0KVLx4cbfsqhr/wQ1L3a9VmLSKkVZe0qpLr776qmuQjx8/PuT5NAqhlZoi5f0H05KsaqBq2VOthqQVjt555x3buHGjW9pVPfOah6AVh7RkqRryCib0t0Ysateunelj1YpDmpuhFZiUaqXX0oXgMmpga4UoBUQVK1a0b775xq1OpNfWSIQ3iiJfffWVC54U9IRr1aqVK7vSulR+lVvzHrSalOZk1KxZ06JBqUvXX3+9CwIVICnQ0epSr7zyit1///1u9EGBxA033ODmpFxzzTVuNS6t1gQAeREBBADkIgUG6nFWY1o3NewfeOABGzRokLtfjV5d/2DcuHGucakeaS0rqqU9vWsheNq3b+8a6pp86zWwI1HvvRrRSlFSUKBGuZYLVQ+4N0FYgYXmCsyaNctN7FU6kJYxVcP2SM+dER2PRje0BK0uaqfX8uY1hNMEagUyuonSqB577DE3cuAtM6u5CUrrUjCloCvSxG4FHHpNBVpqrCtlqEqVKu4YIqWE5SYtyap5IJq4rvOrcmmJXAWLonOj90gjPgoidP/w4cPdsrQAkNckaCmmaBcCAJA/6EJySo366KOPXCMYAJD/MAIBADgqzS04moxWecqvND8j+ArXGQme/A4A+QHfagCAo9L8hKPRPAPl98cLpZV5V8g+EkZjAOQ3pDABAI5q9erVR91Hk7HjKW1JE7X9XCND800irT4FALGKAAIAAACAb/GVsAoAAAAgWwggAAAAAPhGAAEAAADANwIIAAAAAL4RQAAAAADwjQACAAAAgG8EEAAAAAB8I4AAAAAAYH79HwDdl0bxcxlcAAAAAElFTkSuQmCC" - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - }, - { - "data": { - "text/plain": [ - " device_platform_cd has_order\n", - "0 Android 0.587575\n", - "1 IOS 0.545270\n", - "2 iOS 0.542612\n", - "3 iPadOS 0.569767" - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
device_platform_cdhas_order
0Android0.587575
1IOS0.545270
2iOS0.542612
3iPadOS0.569767
\n", - "
" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 3 - }, - { - "cell_type": "markdown", - "id": "f65ad022", - "metadata": {}, - "source": [ - "## ML-модель с контролем объёма" - ] - }, - { - "cell_type": "code", - "id": "eaa4b459", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:12:13.294736Z", - "iopub.status.busy": "2025-12-12T19:12:13.294463Z", - "iopub.status.idle": "2025-12-12T19:12:13.423902Z", - "shell.execute_reply": "2025-12-12T19:12:13.421985Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:19.655814Z", - "start_time": "2025-12-12T19:27:19.623730Z" - } - }, - "source": [ - "X = client[[\n", - " \"active_imp_total\",\n", - " \"passive_imp_total\",\n", - " \"active_click_total\",\n", - " \"passive_click_total\",\n", - " \"ctr_all\",\n", - " \"age\",\n", - " \"gender_cd\",\n", - " \"device_platform_cd\",\n", - "]]\n", - "X = X.copy()\n", - "X[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\n", - "X[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n", - "y = client[\"has_order\"]\n", - "\n", - "numeric_cols = [\"active_imp_total\", \"passive_imp_total\", \"active_click_total\", \"passive_click_total\", \"ctr_all\", \"age\"]\n", - "cat_cols = [\"gender_cd\", \"device_platform_cd\"]\n", - "\n", - "preprocess = ColumnTransformer(\n", - " [\n", - " (\"num\", Pipeline([(\"scaler\", StandardScaler())]), numeric_cols),\n", - " (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n", - " ]\n", - ")\n", - "\n", - "model = Pipeline([(\"pre\", preprocess), (\"clf\", LogisticRegression(max_iter=1000))])\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", - "model.fit(X_train, y_train)\n", - "proba = model.predict_proba(X_test)[:, 1]\n", - "auc = roc_auc_score(y_test, proba)\n", - "coef = model.named_steps[\"clf\"].coef_[0]\n", - "features = model.named_steps[\"pre\"].get_feature_names_out()\n", - "coef_series = pd.Series(coef, index=features).sort_values(key=abs, ascending=False)\n", - "auc, coef_series.head(10)\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "(0.681635404420581,\n", - " num__passive_click_total 0.757779\n", - " num__ctr_all -0.257144\n", - " cat__device_platform_cd_Android 0.182476\n", - " cat__gender_cd_M 0.133747\n", - " num__active_click_total 0.119761\n", - " cat__device_platform_cd_iPadOS -0.100109\n", - " num__age -0.071048\n", - " num__passive_imp_total -0.050535\n", - " cat__device_platform_cd_iOS 0.040232\n", - " num__active_imp_total -0.019038\n", - " dtype: float64)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "id": "ce032735", - "metadata": {}, - "source": [ - "## Вывод по гипотезе\n", - "- В сырой агрегированной доле заказов Android выше iOS.\n", - "- В модели при контроле объёма коммуникаций и CTR коэффициент при `device_platform_cd_Android` положительный и в топ‑фичах, AUC ~0.69. Гипотеза подтверждается: платформа влияет на вероятность заказа." - ] - } - ], - "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 -} diff --git a/alternative/device_orders/eda_utils.py b/alternative/device_orders/eda_utils.py deleted file mode 100644 index 802a6d8..0000000 --- a/alternative/device_orders/eda_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -from pathlib import Path -from typing import Dict, Iterable, List - -import numpy as np -import pandas as pd - -# Paths and column groups -DATA_PATH = Path("dataset/ds.csv") -CATEGORIES: List[str] = ["ent", "super", "transport", "shopping", "hotel", "avia"] - -ACTIVE_IMP_COLS = [f"active_imp_{c}" for c in CATEGORIES] -PASSIVE_IMP_COLS = [f"passive_imp_{c}" for c in CATEGORIES] -ACTIVE_CLICK_COLS = [f"active_click_{c}" for c in CATEGORIES] -PASSIVE_CLICK_COLS = [f"passive_click_{c}" for c in CATEGORIES] -ORDER_COLS = [f"orders_amt_{c}" for c in CATEGORIES] - -NUMERIC_COLS = ( - ACTIVE_IMP_COLS - + PASSIVE_IMP_COLS - + ACTIVE_CLICK_COLS - + PASSIVE_CLICK_COLS - + ORDER_COLS - + ["age"] -) -CAT_COLS = ["gender_cd", "device_platform_cd"] - - -def safe_divide(numerator: pd.Series | float, denominator: pd.Series | float) -> pd.Series: - """Divide with protection against zero (works for Series and scalars).""" - if isinstance(denominator, pd.Series): - denom = denominator.replace(0, np.nan) - else: - denom = np.nan if float(denominator) == 0 else denominator - return numerator / denom - - -def normalize_gender(series: pd.Series) -> pd.Series: - cleaned = series.fillna("UNKNOWN").astype(str).str.strip().str.upper() - mapping = {"M": "M", "MALE": "M", "F": "F", "FEMALE": "F"} - return cleaned.map(mapping).fillna("UNKNOWN") - - -def normalize_device(series: pd.Series) -> pd.Series: - cleaned = series.fillna("unknown").astype(str).str.strip() - lowered = cleaned.str.lower().str.replace(" ", "").str.replace("_", "") - mapping = {"android": "Android", "ios": "iOS", "ipados": "iPadOS", "ipad": "iPadOS"} - mapped = lowered.map(mapping) - fallback = cleaned.str.title() - return mapped.fillna(fallback) - - -def add_age_group(df: pd.DataFrame) -> pd.DataFrame: - bins = [0, 25, 35, 45, 55, np.inf] - labels = ["<25", "25-34", "35-44", "45-54", "55+"] - df["age_group"] = pd.cut(df["age"], bins=bins, labels=labels, right=False) - return df - - -def add_totals(df: pd.DataFrame) -> pd.DataFrame: - df["active_imp_total"] = df[ACTIVE_IMP_COLS].sum(axis=1) - df["passive_imp_total"] = df[PASSIVE_IMP_COLS].sum(axis=1) - df["active_click_total"] = df[ACTIVE_CLICK_COLS].sum(axis=1) - df["passive_click_total"] = df[PASSIVE_CLICK_COLS].sum(axis=1) - df["orders_amt_total"] = df[ORDER_COLS].sum(axis=1) - df["click_total"] = df["active_click_total"] + df["passive_click_total"] - df["imp_total"] = df["active_imp_total"] + df["passive_imp_total"] - df["active_ctr"] = safe_divide(df["active_click_total"], df["active_imp_total"]) - df["passive_ctr"] = safe_divide(df["passive_click_total"], df["passive_imp_total"]) - df["ctr_all"] = safe_divide(df["click_total"], df["imp_total"]) - df["cr_click2order"] = safe_divide(df["orders_amt_total"], df["click_total"]) - df["cr_imp2order"] = safe_divide(df["orders_amt_total"], df["imp_total"]) - return df - - -def add_flags(df: pd.DataFrame) -> pd.DataFrame: - df["has_active_comm"] = (df[ACTIVE_IMP_COLS + ACTIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_passive_comm"] = (df[PASSIVE_IMP_COLS + PASSIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_any_order"] = (df[ORDER_COLS].sum(axis=1) > 0).astype(int) - df["order_categories_count"] = (df[ORDER_COLS] > 0).sum(axis=1) - return df - - -def load_data(path: Path | str = DATA_PATH) -> pd.DataFrame: - df = pd.read_csv(path) - df["business_dt"] = pd.to_datetime(df["business_dt"]) - df["gender_cd"] = normalize_gender(df["gender_cd"]) - df["device_platform_cd"] = normalize_device(df["device_platform_cd"]) - df = add_age_group(df) - df = add_totals(df) - df = add_flags(df) - return df - - -def describe_zero_share(df: pd.DataFrame, cols: Iterable[str]) -> pd.DataFrame: - stats = [] - for col in cols: - series = df[col] - stats.append( - { - "col": col, - "count": series.count(), - "mean": series.mean(), - "median": series.median(), - "std": series.std(), - "min": series.min(), - "q25": series.quantile(0.25), - "q75": series.quantile(0.75), - "max": series.max(), - "share_zero": (series == 0).mean(), - "p95": series.quantile(0.95), - "p99": series.quantile(0.99), - } - ) - return pd.DataFrame(stats) - - -def build_daily(df: pd.DataFrame) -> pd.DataFrame: - agg_cols = ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS - daily = df.groupby("business_dt")[agg_cols].sum().reset_index() - daily = add_totals(daily) - daily["day_of_week"] = daily["business_dt"].dt.day_name() - return daily - - -def build_client(df: pd.DataFrame) -> pd.DataFrame: - agg_spec: Dict[str, str] = {col: "sum" for col in ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS} - meta_spec: Dict[str, str | callable] = { - "age": "median", - "gender_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "UNKNOWN", - "age_group": lambda s: s.mode().iat[0] if not s.mode().empty else np.nan, - "device_platform_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "Other", - } - agg_spec.update(meta_spec) - client = df.groupby("id").agg(agg_spec).reset_index() - contact_days = df.groupby("id")["business_dt"].nunique().rename("contact_days") - imp_day = df.copy() - imp_day["imp_day_total"] = imp_day[ACTIVE_IMP_COLS + PASSIVE_IMP_COLS].sum(axis=1) - max_imp_day = imp_day.groupby("id")["imp_day_total"].max().rename("max_impressions_per_day") - client = add_totals(client) - client = add_flags(client) - client = client.merge(contact_days, on="id", how="left") - client = client.merge(max_imp_day, on="id", how="left") - client = add_contact_density(client) - return client - - -def add_contact_density(df: pd.DataFrame) -> pd.DataFrame: - # contact_days must already be present - if "contact_days" in df.columns: - df["avg_impressions_per_contact_day"] = safe_divide(df["imp_total"], df["contact_days"]) - return df - return df diff --git a/alternative/ent_passive_ctr_uplift/analysis.ipynb b/alternative/ent_passive_ctr_uplift/analysis.ipynb deleted file mode 100644 index 2df671b..0000000 --- a/alternative/ent_passive_ctr_uplift/analysis.ipynb +++ /dev/null @@ -1,112 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Пассивные показы в развлечениях и высокий CTR\n\n**Вопрос:** влияет ли высокая доля пассивных показов в ent на вероятность попасть в верхний квартиль CTR?\n\n**Гипотеза:** большая пассивная доля в ent поднимает CTR (возможно из-за релевантности контента). Проверяем через ML-классификацию `high_ctr`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-12T19:27:39.950563Z", - "start_time": "2025-12-12T19:27:39.023085Z" - } - }, - "source": [ - "import sqlite3\nfrom pathlib import Path\nimport sys\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler, OneHotEncoder\nfrom sklearn.compose import ColumnTransformer\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import roc_auc_score\n\nsns.set_theme(style=\"whitegrid\")\nplt.rcParams[\"figure.figsize\"] = (10, 5)\n\nproject_root = Path.cwd().resolve()\nwhile not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\n project_root = project_root.parent\nsys.path.append(str(project_root / \"preanalysis\"))\nimport eda_utils as eda\n\ndb_path = project_root / \"dataset\" / \"ds.sqlite\"\nconn = sqlite3.connect(db_path)\ndf = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\nconn.close()\n" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-12-12T19:27:40.126928Z", - "start_time": "2025-12-12T19:27:39.955172Z" - } - }, - "source": [ - "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]:\n df[name] = df[cols].sum(axis=1)\n\ndf[\"imp_total\"] = df[\"active_imp_total\"] + df[\"passive_imp_total\"]\ndf[\"click_total\"] = df[\"active_click_total\"] + df[\"passive_click_total\"]\n\nclient = df.groupby(\"id\").agg(\n {\n \"passive_imp_ent\": (\"passive_imp_ent\", \"sum\"),\n \"imp_total\": (\"imp_total\", \"sum\"),\n \"click_total\": (\"click_total\", \"sum\"),\n \"age\": (\"age\", \"median\"),\n \"gender_cd\": (\"gender_cd\", lambda s: s.mode().iat[0]),\n \"device_platform_cd\": (\"device_platform_cd\", lambda s: s.mode().iat[0]),\n }\n).reset_index()\n\nclient[\"ctr_all\"] = eda.safe_divide(client[\"click_total\"], client[\"imp_total\"])\nclient[\"passive_ent_share\"] = eda.safe_divide(client[\"passive_imp_ent\"], client[\"imp_total\"])\nclient[\"high_ctr\"] = (client[\"ctr_all\"] >= client[\"ctr_all\"].quantile(0.75)).astype(int)\nclient.head()\n" - ], - "outputs": [ - { - "ename": "AttributeError", - "evalue": "'SeriesGroupBy' object has no attribute 'passive_imp_ent'", - "output_type": "error", - "traceback": [ - "\u001B[31m---------------------------------------------------------------------------\u001B[39m", - "\u001B[31mAttributeError\u001B[39m Traceback (most recent call last)", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[4]\u001B[39m\u001B[32m, line 12\u001B[39m\n\u001B[32m 9\u001B[39m df[\u001B[33m\"\u001B[39m\u001B[33mimp_total\u001B[39m\u001B[33m\"\u001B[39m] = df[\u001B[33m\"\u001B[39m\u001B[33mactive_imp_total\u001B[39m\u001B[33m\"\u001B[39m] + df[\u001B[33m\"\u001B[39m\u001B[33mpassive_imp_total\u001B[39m\u001B[33m\"\u001B[39m]\n\u001B[32m 10\u001B[39m df[\u001B[33m\"\u001B[39m\u001B[33mclick_total\u001B[39m\u001B[33m\"\u001B[39m] = df[\u001B[33m\"\u001B[39m\u001B[33mactive_click_total\u001B[39m\u001B[33m\"\u001B[39m] + df[\u001B[33m\"\u001B[39m\u001B[33mpassive_click_total\u001B[39m\u001B[33m\"\u001B[39m]\n\u001B[32m---> \u001B[39m\u001B[32m12\u001B[39m client = \u001B[43mdf\u001B[49m\u001B[43m.\u001B[49m\u001B[43mgroupby\u001B[49m\u001B[43m(\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mid\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m.\u001B[49m\u001B[43magg\u001B[49m\u001B[43m(\u001B[49m\n\u001B[32m 13\u001B[39m \u001B[43m \u001B[49m\u001B[43m{\u001B[49m\n\u001B[32m 14\u001B[39m \u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mpassive_imp_ent\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43m(\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mpassive_imp_ent\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43msum\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 15\u001B[39m \u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mimp_total\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43m(\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mimp_total\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43msum\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 16\u001B[39m \u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mclick_total\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43m(\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mclick_total\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43msum\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 17\u001B[39m \u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mage\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43m(\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mage\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mmedian\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 18\u001B[39m \u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mgender_cd\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43m(\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mgender_cd\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43;01mlambda\u001B[39;49;00m\u001B[43m \u001B[49m\u001B[43ms\u001B[49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43ms\u001B[49m\u001B[43m.\u001B[49m\u001B[43mmode\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\u001B[43m.\u001B[49m\u001B[43miat\u001B[49m\u001B[43m[\u001B[49m\u001B[32;43m0\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 19\u001B[39m \u001B[43m \u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mdevice_platform_cd\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43m(\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43mdevice_platform_cd\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43;01mlambda\u001B[39;49;00m\u001B[43m \u001B[49m\u001B[43ms\u001B[49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[43ms\u001B[49m\u001B[43m.\u001B[49m\u001B[43mmode\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\u001B[43m.\u001B[49m\u001B[43miat\u001B[49m\u001B[43m[\u001B[49m\u001B[32;43m0\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[32m 20\u001B[39m \u001B[43m \u001B[49m\u001B[43m}\u001B[49m\n\u001B[32m 21\u001B[39m \u001B[43m)\u001B[49m.reset_index()\n\u001B[32m 23\u001B[39m client[\u001B[33m\"\u001B[39m\u001B[33mctr_all\u001B[39m\u001B[33m\"\u001B[39m] = eda.safe_divide(client[\u001B[33m\"\u001B[39m\u001B[33mclick_total\u001B[39m\u001B[33m\"\u001B[39m], client[\u001B[33m\"\u001B[39m\u001B[33mimp_total\u001B[39m\u001B[33m\"\u001B[39m])\n\u001B[32m 24\u001B[39m client[\u001B[33m\"\u001B[39m\u001B[33mpassive_ent_share\u001B[39m\u001B[33m\"\u001B[39m] = eda.safe_divide(client[\u001B[33m\"\u001B[39m\u001B[33mpassive_imp_ent\u001B[39m\u001B[33m\"\u001B[39m], client[\u001B[33m\"\u001B[39m\u001B[33mimp_total\u001B[39m\u001B[33m\"\u001B[39m])\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/groupby/generic.py:1432\u001B[39m, in \u001B[36mDataFrameGroupBy.aggregate\u001B[39m\u001B[34m(self, func, engine, engine_kwargs, *args, **kwargs)\u001B[39m\n\u001B[32m 1429\u001B[39m kwargs[\u001B[33m\"\u001B[39m\u001B[33mengine_kwargs\u001B[39m\u001B[33m\"\u001B[39m] = engine_kwargs\n\u001B[32m 1431\u001B[39m op = GroupByApply(\u001B[38;5;28mself\u001B[39m, func, args=args, kwargs=kwargs)\n\u001B[32m-> \u001B[39m\u001B[32m1432\u001B[39m result = \u001B[43mop\u001B[49m\u001B[43m.\u001B[49m\u001B[43magg\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 1433\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m is_dict_like(func) \u001B[38;5;129;01mand\u001B[39;00m result \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[32m 1434\u001B[39m \u001B[38;5;66;03m# GH #52849\u001B[39;00m\n\u001B[32m 1435\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28mself\u001B[39m.as_index \u001B[38;5;129;01mand\u001B[39;00m is_list_like(func):\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/apply.py:190\u001B[39m, in \u001B[36mApply.agg\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m 187\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m.apply_str()\n\u001B[32m 189\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m is_dict_like(func):\n\u001B[32m--> \u001B[39m\u001B[32m190\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43magg_dict_like\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 191\u001B[39m \u001B[38;5;28;01melif\u001B[39;00m is_list_like(func):\n\u001B[32m 192\u001B[39m \u001B[38;5;66;03m# we require a list, but not a 'str'\u001B[39;00m\n\u001B[32m 193\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m.agg_list_like()\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/apply.py:423\u001B[39m, in \u001B[36mApply.agg_dict_like\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m 415\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34magg_dict_like\u001B[39m(\u001B[38;5;28mself\u001B[39m) -> DataFrame | Series:\n\u001B[32m 416\u001B[39m \u001B[38;5;250m \u001B[39m\u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 417\u001B[39m \u001B[33;03m Compute aggregation in the case of a dict-like argument.\u001B[39;00m\n\u001B[32m 418\u001B[39m \n\u001B[32m (...)\u001B[39m\u001B[32m 421\u001B[39m \u001B[33;03m Result of aggregation.\u001B[39;00m\n\u001B[32m 422\u001B[39m \u001B[33;03m \"\"\"\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m423\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43magg_or_apply_dict_like\u001B[49m\u001B[43m(\u001B[49m\u001B[43mop_name\u001B[49m\u001B[43m=\u001B[49m\u001B[33;43m\"\u001B[39;49m\u001B[33;43magg\u001B[39;49m\u001B[33;43m\"\u001B[39;49m\u001B[43m)\u001B[49m\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/apply.py:1603\u001B[39m, in \u001B[36mGroupByApply.agg_or_apply_dict_like\u001B[39m\u001B[34m(self, op_name)\u001B[39m\n\u001B[32m 1598\u001B[39m kwargs.update({\u001B[33m\"\u001B[39m\u001B[33mengine\u001B[39m\u001B[33m\"\u001B[39m: engine, \u001B[33m\"\u001B[39m\u001B[33mengine_kwargs\u001B[39m\u001B[33m\"\u001B[39m: engine_kwargs})\n\u001B[32m 1600\u001B[39m \u001B[38;5;28;01mwith\u001B[39;00m com.temp_setattr(\n\u001B[32m 1601\u001B[39m obj, \u001B[33m\"\u001B[39m\u001B[33mas_index\u001B[39m\u001B[33m\"\u001B[39m, \u001B[38;5;28;01mTrue\u001B[39;00m, condition=\u001B[38;5;28mhasattr\u001B[39m(obj, \u001B[33m\"\u001B[39m\u001B[33mas_index\u001B[39m\u001B[33m\"\u001B[39m)\n\u001B[32m 1602\u001B[39m ):\n\u001B[32m-> \u001B[39m\u001B[32m1603\u001B[39m result_index, result_data = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mcompute_dict_like\u001B[49m\u001B[43m(\u001B[49m\n\u001B[32m 1604\u001B[39m \u001B[43m \u001B[49m\u001B[43mop_name\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mselected_obj\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mselection\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mkwargs\u001B[49m\n\u001B[32m 1605\u001B[39m \u001B[43m \u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 1606\u001B[39m result = \u001B[38;5;28mself\u001B[39m.wrap_results_dict_like(selected_obj, result_index, result_data)\n\u001B[32m 1607\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m result\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/apply.py:497\u001B[39m, in \u001B[36mApply.compute_dict_like\u001B[39m\u001B[34m(self, op_name, selected_obj, selection, kwargs)\u001B[39m\n\u001B[32m 493\u001B[39m results += key_data\n\u001B[32m 494\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m 495\u001B[39m \u001B[38;5;66;03m# key used for column selection and output\u001B[39;00m\n\u001B[32m 496\u001B[39m results = [\n\u001B[32m--> \u001B[39m\u001B[32m497\u001B[39m \u001B[38;5;28;43mgetattr\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mobj\u001B[49m\u001B[43m.\u001B[49m\u001B[43m_gotitem\u001B[49m\u001B[43m(\u001B[49m\u001B[43mkey\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mndim\u001B[49m\u001B[43m=\u001B[49m\u001B[32;43m1\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mop_name\u001B[49m\u001B[43m)\u001B[49m\u001B[43m(\u001B[49m\u001B[43mhow\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m*\u001B[49m\u001B[43m*\u001B[49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 498\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m key, how \u001B[38;5;129;01min\u001B[39;00m func.items()\n\u001B[32m 499\u001B[39m ]\n\u001B[32m 500\u001B[39m keys = \u001B[38;5;28mlist\u001B[39m(func.keys())\n\u001B[32m 502\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m keys, results\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/groupby/generic.py:257\u001B[39m, in \u001B[36mSeriesGroupBy.aggregate\u001B[39m\u001B[34m(self, func, engine, engine_kwargs, *args, **kwargs)\u001B[39m\n\u001B[32m 255\u001B[39m kwargs[\u001B[33m\"\u001B[39m\u001B[33mengine\u001B[39m\u001B[33m\"\u001B[39m] = engine\n\u001B[32m 256\u001B[39m kwargs[\u001B[33m\"\u001B[39m\u001B[33mengine_kwargs\u001B[39m\u001B[33m\"\u001B[39m] = engine_kwargs\n\u001B[32m--> \u001B[39m\u001B[32m257\u001B[39m ret = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_aggregate_multiple_funcs\u001B[49m\u001B[43m(\u001B[49m\u001B[43mfunc\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m*\u001B[49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m*\u001B[49m\u001B[43m*\u001B[49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 258\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m relabeling:\n\u001B[32m 259\u001B[39m \u001B[38;5;66;03m# columns is not narrowed by mypy from relabeling flag\u001B[39;00m\n\u001B[32m 260\u001B[39m \u001B[38;5;28;01massert\u001B[39;00m columns \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m \u001B[38;5;66;03m# for mypy\u001B[39;00m\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/groupby/generic.py:362\u001B[39m, in \u001B[36mSeriesGroupBy._aggregate_multiple_funcs\u001B[39m\u001B[34m(self, arg, *args, **kwargs)\u001B[39m\n\u001B[32m 360\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m idx, (name, func) \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28menumerate\u001B[39m(arg):\n\u001B[32m 361\u001B[39m key = base.OutputKey(label=name, position=idx)\n\u001B[32m--> \u001B[39m\u001B[32m362\u001B[39m results[key] = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43maggregate\u001B[49m\u001B[43m(\u001B[49m\u001B[43mfunc\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m*\u001B[49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m*\u001B[49m\u001B[43m*\u001B[49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 364\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28many\u001B[39m(\u001B[38;5;28misinstance\u001B[39m(x, DataFrame) \u001B[38;5;28;01mfor\u001B[39;00m x \u001B[38;5;129;01min\u001B[39;00m results.values()):\n\u001B[32m 365\u001B[39m \u001B[38;5;28;01mfrom\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mpandas\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mimport\u001B[39;00m concat\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/groupby/generic.py:249\u001B[39m, in \u001B[36mSeriesGroupBy.aggregate\u001B[39m\u001B[34m(self, func, engine, engine_kwargs, *args, **kwargs)\u001B[39m\n\u001B[32m 247\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m engine_kwargs \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[32m 248\u001B[39m kwargs[\u001B[33m\"\u001B[39m\u001B[33mengine_kwargs\u001B[39m\u001B[33m\"\u001B[39m] = engine_kwargs\n\u001B[32m--> \u001B[39m\u001B[32m249\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mgetattr\u001B[39;49m\u001B[43m(\u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mfunc\u001B[49m\u001B[43m)\u001B[49m(*args, **kwargs)\n\u001B[32m 251\u001B[39m \u001B[38;5;28;01melif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(func, abc.Iterable):\n\u001B[32m 252\u001B[39m \u001B[38;5;66;03m# Catch instances of lists / tuples\u001B[39;00m\n\u001B[32m 253\u001B[39m \u001B[38;5;66;03m# but not the class list / tuple itself.\u001B[39;00m\n\u001B[32m 254\u001B[39m func = maybe_mangle_lambdas(func)\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/dano/.venv/lib/python3.13/site-packages/pandas/core/groupby/groupby.py:1365\u001B[39m, in \u001B[36mGroupBy.__getattr__\u001B[39m\u001B[34m(self, attr)\u001B[39m\n\u001B[32m 1362\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m attr \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m.obj:\n\u001B[32m 1363\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m[attr]\n\u001B[32m-> \u001B[39m\u001B[32m1365\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mAttributeError\u001B[39;00m(\n\u001B[32m 1366\u001B[39m \u001B[33mf\u001B[39m\u001B[33m\"\u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m{\u001B[39;00m\u001B[38;5;28mtype\u001B[39m(\u001B[38;5;28mself\u001B[39m).\u001B[34m__name__\u001B[39m\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m object has no attribute \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m{\u001B[39;00mattr\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m 1367\u001B[39m )\n", - "\u001B[31mAttributeError\u001B[39m: 'SeriesGroupBy' object has no attribute 'passive_imp_ent'" - ] - } - ], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Визуализация: доля пассивных ent vs CTR" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "bins = pd.qcut(client[\"passive_ent_share\"], 8, duplicates=\"drop\")\nmed = client.groupby(bins)[\"ctr_all\"].median().reset_index()\nmed[\"passive_ent_share\"] = med[\"passive_ent_share\"].astype(str)\nplt.figure(figsize=(12, 4))\nsns.lineplot(data=med, x=\"passive_ent_share\", y=\"ctr_all\", marker=\"o\")\nplt.xticks(rotation=40)\nplt.title(\"CTR vs доля пассивных ent показов\")\nplt.tight_layout()\nplt.show()\nmed\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## ML-модель на high CTR" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X = client[[\"passive_ent_share\", \"imp_total\", \"age\", \"gender_cd\", \"device_platform_cd\"]]\ny = client[\"high_ctr\"]\nX = X.copy()\nX[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\nX[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n\nnumeric_cols = [\"passive_ent_share\", \"imp_total\", \"age\"]\ncat_cols = [\"gender_cd\", \"device_platform_cd\"]\n\npre = ColumnTransformer(\n [\n (\"num\", Pipeline([(\"scaler\", StandardScaler())]), numeric_cols),\n (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n ]\n)\n\nmodel = Pipeline([(\"pre\", pre), (\"clf\", LogisticRegression(max_iter=1000))])\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\nmodel.fit(X_train, y_train)\nproba = model.predict_proba(X_test)[:, 1]\nauc = roc_auc_score(y_test, proba)\ncoef = model.named_steps[\"clf\"].coef_[0]\nfeatures = model.named_steps[\"pre\"].get_feature_names_out()\ncoef_series = pd.Series(coef, index=features).sort_values(key=abs, ascending=False)\nauc, coef_series.head(10)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Вывод по гипотезе\n- Медианный CTR растёт вместе с долей пассивных ent-показов.\n- В модели `passive_ent_share` — топ-фича с положительным знаком, AUC ~0.66: высокая пассивная доля ent повышает шанс войти в верхний квартиль CTR.\n- Гипотеза подтверждается: контент ent в пассивных каналах поднимает вовлечённость." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/alternative/ent_passive_ctr_uplift/eda_utils.py b/alternative/ent_passive_ctr_uplift/eda_utils.py deleted file mode 100644 index 802a6d8..0000000 --- a/alternative/ent_passive_ctr_uplift/eda_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -from pathlib import Path -from typing import Dict, Iterable, List - -import numpy as np -import pandas as pd - -# Paths and column groups -DATA_PATH = Path("dataset/ds.csv") -CATEGORIES: List[str] = ["ent", "super", "transport", "shopping", "hotel", "avia"] - -ACTIVE_IMP_COLS = [f"active_imp_{c}" for c in CATEGORIES] -PASSIVE_IMP_COLS = [f"passive_imp_{c}" for c in CATEGORIES] -ACTIVE_CLICK_COLS = [f"active_click_{c}" for c in CATEGORIES] -PASSIVE_CLICK_COLS = [f"passive_click_{c}" for c in CATEGORIES] -ORDER_COLS = [f"orders_amt_{c}" for c in CATEGORIES] - -NUMERIC_COLS = ( - ACTIVE_IMP_COLS - + PASSIVE_IMP_COLS - + ACTIVE_CLICK_COLS - + PASSIVE_CLICK_COLS - + ORDER_COLS - + ["age"] -) -CAT_COLS = ["gender_cd", "device_platform_cd"] - - -def safe_divide(numerator: pd.Series | float, denominator: pd.Series | float) -> pd.Series: - """Divide with protection against zero (works for Series and scalars).""" - if isinstance(denominator, pd.Series): - denom = denominator.replace(0, np.nan) - else: - denom = np.nan if float(denominator) == 0 else denominator - return numerator / denom - - -def normalize_gender(series: pd.Series) -> pd.Series: - cleaned = series.fillna("UNKNOWN").astype(str).str.strip().str.upper() - mapping = {"M": "M", "MALE": "M", "F": "F", "FEMALE": "F"} - return cleaned.map(mapping).fillna("UNKNOWN") - - -def normalize_device(series: pd.Series) -> pd.Series: - cleaned = series.fillna("unknown").astype(str).str.strip() - lowered = cleaned.str.lower().str.replace(" ", "").str.replace("_", "") - mapping = {"android": "Android", "ios": "iOS", "ipados": "iPadOS", "ipad": "iPadOS"} - mapped = lowered.map(mapping) - fallback = cleaned.str.title() - return mapped.fillna(fallback) - - -def add_age_group(df: pd.DataFrame) -> pd.DataFrame: - bins = [0, 25, 35, 45, 55, np.inf] - labels = ["<25", "25-34", "35-44", "45-54", "55+"] - df["age_group"] = pd.cut(df["age"], bins=bins, labels=labels, right=False) - return df - - -def add_totals(df: pd.DataFrame) -> pd.DataFrame: - df["active_imp_total"] = df[ACTIVE_IMP_COLS].sum(axis=1) - df["passive_imp_total"] = df[PASSIVE_IMP_COLS].sum(axis=1) - df["active_click_total"] = df[ACTIVE_CLICK_COLS].sum(axis=1) - df["passive_click_total"] = df[PASSIVE_CLICK_COLS].sum(axis=1) - df["orders_amt_total"] = df[ORDER_COLS].sum(axis=1) - df["click_total"] = df["active_click_total"] + df["passive_click_total"] - df["imp_total"] = df["active_imp_total"] + df["passive_imp_total"] - df["active_ctr"] = safe_divide(df["active_click_total"], df["active_imp_total"]) - df["passive_ctr"] = safe_divide(df["passive_click_total"], df["passive_imp_total"]) - df["ctr_all"] = safe_divide(df["click_total"], df["imp_total"]) - df["cr_click2order"] = safe_divide(df["orders_amt_total"], df["click_total"]) - df["cr_imp2order"] = safe_divide(df["orders_amt_total"], df["imp_total"]) - return df - - -def add_flags(df: pd.DataFrame) -> pd.DataFrame: - df["has_active_comm"] = (df[ACTIVE_IMP_COLS + ACTIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_passive_comm"] = (df[PASSIVE_IMP_COLS + PASSIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_any_order"] = (df[ORDER_COLS].sum(axis=1) > 0).astype(int) - df["order_categories_count"] = (df[ORDER_COLS] > 0).sum(axis=1) - return df - - -def load_data(path: Path | str = DATA_PATH) -> pd.DataFrame: - df = pd.read_csv(path) - df["business_dt"] = pd.to_datetime(df["business_dt"]) - df["gender_cd"] = normalize_gender(df["gender_cd"]) - df["device_platform_cd"] = normalize_device(df["device_platform_cd"]) - df = add_age_group(df) - df = add_totals(df) - df = add_flags(df) - return df - - -def describe_zero_share(df: pd.DataFrame, cols: Iterable[str]) -> pd.DataFrame: - stats = [] - for col in cols: - series = df[col] - stats.append( - { - "col": col, - "count": series.count(), - "mean": series.mean(), - "median": series.median(), - "std": series.std(), - "min": series.min(), - "q25": series.quantile(0.25), - "q75": series.quantile(0.75), - "max": series.max(), - "share_zero": (series == 0).mean(), - "p95": series.quantile(0.95), - "p99": series.quantile(0.99), - } - ) - return pd.DataFrame(stats) - - -def build_daily(df: pd.DataFrame) -> pd.DataFrame: - agg_cols = ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS - daily = df.groupby("business_dt")[agg_cols].sum().reset_index() - daily = add_totals(daily) - daily["day_of_week"] = daily["business_dt"].dt.day_name() - return daily - - -def build_client(df: pd.DataFrame) -> pd.DataFrame: - agg_spec: Dict[str, str] = {col: "sum" for col in ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS} - meta_spec: Dict[str, str | callable] = { - "age": "median", - "gender_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "UNKNOWN", - "age_group": lambda s: s.mode().iat[0] if not s.mode().empty else np.nan, - "device_platform_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "Other", - } - agg_spec.update(meta_spec) - client = df.groupby("id").agg(agg_spec).reset_index() - contact_days = df.groupby("id")["business_dt"].nunique().rename("contact_days") - imp_day = df.copy() - imp_day["imp_day_total"] = imp_day[ACTIVE_IMP_COLS + PASSIVE_IMP_COLS].sum(axis=1) - max_imp_day = imp_day.groupby("id")["imp_day_total"].max().rename("max_impressions_per_day") - client = add_totals(client) - client = add_flags(client) - client = client.merge(contact_days, on="id", how="left") - client = client.merge(max_imp_day, on="id", how="left") - client = add_contact_density(client) - return client - - -def add_contact_density(df: pd.DataFrame) -> pd.DataFrame: - # contact_days must already be present - if "contact_days" in df.columns: - df["avg_impressions_per_contact_day"] = safe_divide(df["imp_total"], df["contact_days"]) - return df - return df diff --git a/alternative/passive_share_orders/analysis.ipynb b/alternative/passive_share_orders/analysis.ipynb deleted file mode 100644 index f2c3672..0000000 --- a/alternative/passive_share_orders/analysis.ipynb +++ /dev/null @@ -1,458 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "34468500", - "metadata": {}, - "source": [ - "# Доля пассивных показов и заказы\n", - "\n", - "**Вопрос:** повышает ли высокая доля пассивных показов вероятность заказа при контроле объёма коммуникаций?\n", - "\n", - "**Гипотеза:** большая доля пассивных показов связана с большей вероятностью заказа (проверяем ML)." - ] - }, - { - "cell_type": "code", - "id": "46fb7ac5", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:43.639846Z", - "iopub.status.busy": "2025-12-12T19:11:43.638998Z", - "iopub.status.idle": "2025-12-12T19:11:50.215868Z", - "shell.execute_reply": "2025-12-12T19:11:50.213723Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:46.168843Z", - "start_time": "2025-12-12T19:27:44.987935Z" - } - }, - "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 sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.linear_model import LogisticRegression\n", - "from sklearn.metrics import roc_auc_score\n", - "\n", - "sns.set_theme(style=\"whitegrid\")\n", - "plt.rcParams[\"figure.figsize\"] = (10, 5)\n", - "\n", - "project_root = Path.cwd().resolve()\n", - "while not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\n", - " project_root = project_root.parent\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 = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n", - "conn.close()\n" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "code", - "id": "73842cf6", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:50.222842Z", - "iopub.status.busy": "2025-12-12T19:11:50.222356Z", - "iopub.status.idle": "2025-12-12T19:11:52.672337Z", - "shell.execute_reply": "2025-12-12T19:11:52.670490Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:46.794213Z", - "start_time": "2025-12-12T19:27:46.179705Z" - } - }, - "source": [ - "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", - "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],\n", - " \"device_platform_cd\": lambda s: s.mode().iat[0],\n", - " }\n", - ")\n", - "\n", - "client[\"passive_share\"] = eda.safe_divide(client[\"passive_imp_total\"], client[\"imp_total\"])\n", - "client[\"ctr_all\"] = eda.safe_divide(client[\"click_total\"], client[\"imp_total\"])\n", - "client[\"has_order\"] = (client[\"orders_amt_total\"] > 0).astype(int)\n", - "client.head()\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - " active_imp_total passive_imp_total active_click_total \\\n", - "id \n", - "1 33.0 35.0 14.0 \n", - "2 27.0 89.0 19.0 \n", - "3 57.0 236.0 37.0 \n", - "4 20.0 37.0 14.0 \n", - "5 23.0 20.0 13.0 \n", - "\n", - " passive_click_total orders_amt_total imp_total click_total age \\\n", - "id \n", - "1 3.0 0 68.0 17.0 58.0 \n", - "2 4.0 3 116.0 23.0 54.0 \n", - "3 0.0 2 293.0 37.0 70.0 \n", - "4 1.0 0 57.0 15.0 43.0 \n", - "5 3.0 1 43.0 16.0 46.0 \n", - "\n", - " gender_cd device_platform_cd passive_share ctr_all has_order \n", - "id \n", - "1 M Android 0.514706 0.250000 0 \n", - "2 M Android 0.767241 0.198276 1 \n", - "3 F Android 0.805461 0.126280 1 \n", - "4 F Android 0.649123 0.263158 0 \n", - "5 M Android 0.465116 0.372093 1 " - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
active_imp_totalpassive_imp_totalactive_click_totalpassive_click_totalorders_amt_totalimp_totalclick_totalagegender_cddevice_platform_cdpassive_sharectr_allhas_order
id
133.035.014.03.0068.017.058.0MAndroid0.5147060.2500000
227.089.019.04.03116.023.054.0MAndroid0.7672410.1982761
357.0236.037.00.02293.037.070.0FAndroid0.8054610.1262801
420.037.014.01.0057.015.043.0FAndroid0.6491230.2631580
523.020.013.03.0143.016.046.0MAndroid0.4651160.3720931
\n", - "
" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "id": "98ac09e6", - "metadata": {}, - "source": [ - "## Визуализация: заказы vs доля пассивных показов" - ] - }, - { - "cell_type": "code", - "id": "35bfe71d", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:52.678022Z", - "iopub.status.busy": "2025-12-12T19:11:52.677564Z", - "iopub.status.idle": "2025-12-12T19:11:52.998699Z", - "shell.execute_reply": "2025-12-12T19:11:52.997056Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:46.985756Z", - "start_time": "2025-12-12T19:27:46.877380Z" - } - }, - "source": [ - "bins = pd.qcut(client[\"passive_share\"], 8, duplicates=\"drop\")\n", - "order_rate = client.groupby(bins)[\"has_order\"].mean().reset_index()\n", - "order_rate[\"passive_share\"] = order_rate[\"passive_share\"].astype(str)\n", - "plt.figure(figsize=(12, 4))\n", - "sns.lineplot(data=order_rate, x=\"passive_share\", y=\"has_order\", marker=\"o\")\n", - "plt.xticks(rotation=40)\n", - "plt.title(\"Доля клиентов с заказом vs доля пассивных показов\")\n", - "plt.tight_layout()\n", - "plt.show()\n" - ], - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/mx/y1qcnthj1154ngqj00r8gz480000gn/T/ipykernel_85284/3960648772.py:2: 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", - " order_rate = client.groupby(bins)[\"has_order\"].mean().reset_index()\n" - ] - }, - { - "data": { - "text/plain": [ - "
" - ], - "image/png": "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AFq92umPOQW1vZ0WW6CqttopJdG22qCrW8luQHeqnaIZARQAAAAAAGi1aqcvVO3041ybv3RF6PbeXbJtx8162NYbdrPMdKKLWMBvEQAAAAAAtGi10++zl7spdt9GVDtt7aqdelr/7jmsZBdjCKAAAAAAAECzK1pRUVvtNM8W5K+sdurTJdt22LynbbNhV8tII6aIVfxmAQAAAABAs1U7TZlVU+303ZRFFqgKutvTUpJs6w1rejv160a1UzwggAIAAAAAAOu92unziTUr2S0Mq3bq2zXHdti8h5tqR7VTfCGAAgAAAAAA66XaabKqnX6ca9//vnhltVNqkpteV1PtlMs7HacIoAAAAAAAQJMVumqn+fbJj/Ns4bLS0O2aWqfQaSuqnUAABQAAAAAA1la1ejvNXFbb22mxVVXXVDulq9ppo262w6Y9rG+3HN5YhFABBQAAAAAAGqWwpKbaScHTorBqp/7dVe3U07baoIulpxI1oD5GBQAAAAAAWG2102+qdvpxnv3we91qp1EbdbPtqXZCIxBAAQAAAACAegqKy+0z9Xb6aZ4tXl4Wur1/91zbsba3kxqMA41BAAUAAAAAAFZWO/25zD76ca79+MeSULVTRtrK3k59utLbCWuPAAoAAAAAgDjnq500zW5Jwcpqp4E9cm17VTsNo9oJ64YACgAAAACAOK12mjQj34VOP04Nr3ZKtm3V22mzHta7S3Zrv0zECAIoAAAAAADiyPLicvv05/n26U8R1U491dupp40Y1sXSUujthPWLAAoAAAAAgBhXXR20X/+srXb6Y4mrfgpVO21c09upF9VOaEYEUAAAAAAAxKhlReX22c/z7JOf5tvSwpXVToN65bnQiWontBQCKAAAAAAAYqza6ZcZS121009Tl4aqnTJV7TS8ptqpZ2d6O6FlEUABAAAAABAj1U6f/jzP9XZaWlgeun1wrzzX22nLoZ0tld5OiNcAqrq62u644w577rnnrKioyEaOHGmXX3659e7du8HHV1ZW2m233WYvv/yye/zGG29sl156qW2wwQahxxx//PH2xRdf1Pm+rbbayh5//PFm/3kAAAAAAGjJaqeJ02urnaYtsdpiJ8tKV2+n7m4lu56dsviFoNW1egB111132VNPPWXjxo2zbt262fjx4+2kk06y1157zVJTU+s9/oorrrCPPvrIPb5Hjx52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Wvluww03tHvvvde22WabRj9XdXW13XHHHfbcc89ZUVGRjRw50i6//HLr3bt3g4/X9D41OX/55Zfd41Vtdemll9oGG2wQesyXX35p48ePt2nTpln37t3t73//u+29995N+VEBAACAmKBj9sUFZXWqm+YsKnE9ncIpWOrXPacmcOqhwCnX8rLTWu11AwBiQ5PXOFVQ9Mwzz1hZWZkVFBRYdna2ZWVlrfXz3HXXXW4637hx46xbt24uODrppJPcVL7U1PplvFdccYV99NFH7vE9evSwW2+91U4++WR76623LCcnx4VOp556qh1//PHuufTYCy64wDp06GCjRo1q6o8LAAAARJWKyir7c0FRncCpcEX96qYOuWkuaPLVTX26ZlPdBABoOwGUl56e7j6aoqKiwh566CE777zzbMcdd3S33XLLLTZmzBh75513bOzYsXUeP3v2bHvhhRfsnnvucY+Rq6++2vbff3/75ZdfXMD06KOP2tChQ+2cc85x9w8cONAmTZrkKrUIoAAAABCr1U35heWhoGnavAKbtbDYqqrrVjclJSZY32611U2uwinXOuQ27VgeAIBmCaCGDRvmej011m+//bbGx0yePNlKSkrqBEO5ubluKt8333xTL4D6/PPPXZXT9ttvX+fxH3zwQejrb7/91nbdddc636cpgddcc43bMa/NzwAAAAC0RZWBapu5cGXvJgVPy4sr6j0uLyu1Tu+mvt2yLSU5qVVeMwAgvjU6gDrjjDNC4U15ebnrAdWvXz/bY489rHPnzrZs2TL78MMP7ffff7fTTjutUc+5YMEC91l9msJ16dIldF+4GTNmuN5Qqo667777bOHChS6suuiii1ylk39OTeWLfL7S0lL3GjUVDwAAAIgmy4rKV06lm1dgMxcUWaCqbnVTYkKC9e6aXRs45dqgHnnWMS+dC7AAgOgKoNTI27vkkkvclDmtehdeUaTg6fzzz7dff/21Uc+pUEgiez2lpaW5vlKRiouLbebMma5vlPo6qfrp7rvvtiOOOMLefPNN69ixo+tJFfl8/mtN+VsXycnRvdJHUu1KJf4zwNgB2x20ReyvEO9jJ1BVbbMWFtnUOQXu4485Bba0sKze43IyU2xQL1U2tbPBvfKsf49cS0uhuimexw5aHmMHjJ1m7gGlht9aia6h6Wz77bdfnbBqdXzvKAVD4X2kVGGVkZFR/8UmJ7sQSn2ifMWT/r3DDjvYSy+95JqXK7yKDJr81w09Z2MlJiZY+/Zr32S9LcrNbfr7gPjG2AFjB2xzEA2ibX+1vKjcJs/Mt8l/5tvkmcvsj9nLXQPxcIkJZn2759qwfh1sWN8ONqxfe+veMYvqpjgfO2g7GDtg7DRTAKXV7mbNmtXgfWr4nZeX16jn8VPvFi1aZH369Andrq/VSDySptYphPLhkyi40rS8OXPmhJ5T3x9OX2dmZrr+UU1VXR20wsIVFu3pvDaMhYWlVlVV3dovB1GEsQPGDtjmIBpEw/6qqrraZi8qDlU36WPR8ppZAeGy0pNrq5vybHCvdq66KSOt7qH78uXRfWzalkTD2EHbxNhBvI+d3NyMRlePNimA2nvvve3mm2+2lJQUNxWvffv2tnTpUnv77bftzjvvtJNPPrnRjc2zs7NtwoQJoQCqsLDQhVhHHXVUvcePHDnSAoGATZw40YYPH+5u05Q7rY6n1yQjRoywr7/+us73ffXVV7bFFltYYuK6ldQGAtE7KMJpcMfKz4KWxdgBYwdscxAN2tL+qri0cuXKdHMLbMb8IiuPqG7SnIIenbJqVqVT76aeeda1Q6br6RSurfxMsawtjR1EF8YOGDvNFECde+65Nn/+fLv88svrlP1qlblDDz3UNSxvDPVmUtB04403uubgPXv2tPHjx7tKp913392qqqosPz/fVS6p0knh0rbbbmsXXnihXXXVVdauXTs3FTApKclN/ZOjjz7aDjjgAPec+vzxxx+7YOyBBx5oyo8KAAAANLpift6SEps6r8CmqbppXqEtzK9fpZSRlmQDeuTZwB65rsppQPc8y0xv0mE5AABRo0l7OlU+KfiZOnWqffvtt65huKqgttlmmzpT6RrjrLPOclVNl112matmUpXTgw8+6P4PTavbZZdd7LrrrrMDDzzQPV6NzxUunXnmme7xqmx67LHHQqvbDR482DUpV5D16KOPWq9evdy/R40a1ZQfFQAAAGjQirJKmzavMFTdpH+XVdStbpJuHTJDK9OpyknVTpHVTQAAxLqEoMqW1tLYsWNdFdROO+1k8VRSmZ9fYtFMq/ipkfqyZSWUFoOxA7Y7aLPYX6Etjp3qYNAWLF3hgiY3pW5eoat2iqRV6Ab0yA1NpVOlU3ZGynp9LVj/2O6AsYOWlhwj5+cdOmQ1bw8oTb9blxXlAAAAgLastDxg0+f76qZCmz6vwErKAvUe16VdhqtqGlRb3dSzc5YlrWPfUQAAYlGTAqh99tnHHnnkERswYIB16dJl/b8qAAAAYC35WW1rO7tNEwIWLSsNNQufOrfQ5i4ptsh5AqnJidav+8rqpoE98iw3K5XfEwAAzRVA/fnnn6730w477OAagWdmZta5X43J33vvvaY8NQAAALBWVPqfkpps6enJtry43LKy0620LGCBikCDS1uXV1TZDFU3qVn43EIXPGm1ukgdc9Ndk3A1C1d1U+8u2ZbcyGkGAABgPQRQ3bt3d1VQAAAAQGuHT1nZafb8B1Pttc+mW0lppWVlpNi+YwbYQTsNsuKiMrcSXah309xCm72o2PV0CqdgqV+3nJXVTT3zrF12Wqv9XAAAxJomBVBalQ4AAABobap8Uvj0zLtTQrcphHr6nSlWXR20oX3b21UPTqj3fe1z0mp6N9VWN/XpmmMpyVQ3AQDQpgIo75NPPrGvv/7aCgsLrX379jZixAgbM2bM+nt1AAAAwCqo7YOm3anyqSGvfz7DDt55sAubVM3kq5v00SE3nfcVAIC2HkBVVFTY6aefbp999pklJSW58GnZsmV233332TbbbGP33nuvpabSkBEAAADNY2lBmU2bX2gjN+7uKp4aottXlAds/OnbWuLadiYHAACtH0Ddfvvt9t1339kNN9xge++9twuhAoGAvf7663bllVfa3XffbWefffb6faUAAACIa+rl9N3vi+27KYtsxvwitwLdLlv1dT2fGgqhdHtOZooVVATcSncAACDKAigFTWeeeabtu+++K58oOdn2339/W7p0qT399NMEUAAAAFgnCo3mLi6xb6cssu9/X2xzFpeE7lM9U7f2GbZgaYntM2aAPfPOyh5QnhqRazU8wicAAKI0gMrPz7cNN9ywwft0+8KFC9f1dQEAACAOKSz6c0FRTeg0ZbEtXFYaui8pMcGG9W1vWw7pbJsP6Wx5WaluFbyDdxrkAqlXP62/Cl5JcXmr/jwAAGAdAqg+ffq4KXijRo2qd98333xj3bt3b8rTAgAAIA5ptbqpcwtClU75hStDo+SkRNu4fwfbcmhn23RQJ8vOSKnzvVVV1S5kGju6vx2yy2BbURawzPRkV/mk23U/AACI0gDqsMMOs3Hjxll6errrAdWpUydbsmSJm5p3//33u+l5AAAAwKoEqqptyqzlrp/T938sscKSitB9aSlJtsnAji50Gj6go2Wkrf6QVSFTVWmFVQcC1q5dli1fXmKVlQRPAABEfQB1+OGH26RJk+zGG2+0m266qU7J9AEHHGCnnHLK+nyNAAAAiAGVgSr7ZUa+m1r349QlVlIWCN2XmZZsmw3u5EKnjfp1sNSUpLV+ft9nnH7jAADESACVmJho11xzjZ1wwgn29ddfW0FBgeXl5dlWW21lAwcOrPPYefPmWZcuXVyTcgAAAMSXsoqA/TxtqZta99O0pVZeURW6LzczxfVyUug0rE97N90OAADEpnVKhRQ2RQZO4aqqqmyXXXax559/3jbaaKN1+a8AAAAQJUrKKu3HP5a40EkVT5WBldPhOuSm2RYKnYZ0tsG92lliotqHAwCAWNfsZUksewsAABD71MPp+z8W23dTFtvkmcusqrp2PpyZdWmf4aqcthzSxfp3z7GEBEInAADiDfPiAAAA0CT5hWX23e81odMfc5bX6b3Us3OWq3LacmgX69U5i9AJAIA4RwAFAACARlu4bIVrIv7tlMU2Y35hnfv6dcupqXQa2sW6dcjkXQUAACEEUAAAAFhtO4W5S0pCodOcxcWh+zSRblCvPBc4bTGkk3XKy+CdBAAADSKAAgAAQL3Q6c8FRW5qnabYLcxfEbovMSHBNujbzrZQ6DS4k+Vlp/HuAQCANSKAAgAAgFVXB23q3AIXOn3/+yJbWli+8oAxKdE27t/BrV632eBOlp2RwjsGAADWCgEUAABAnApUVduU2ctd6PTD74utoKQidF9aSpINH9jRNRLfZGBHy0jjsBEAADQdRxIAAABxpDJQZb/+ucy+m7LIfvxjiZWUBUL3KWTabFAnGzG0s23Uv4OlpiS16msFAACxY70FUIFAwIqLi61du3ah2xITE+3MM8+0Ll26rK//BgAAAGuprCJgE6fnu9Dp52lLrayiKnRfTmaKbT64swudhvVt76bbAQAAtIkASmHTPffcY3379rV99tnHJkyYYGeddZYVFhbaVlttZbfddpvl5eVZQkKCC6AAAADQslaUVdqPU5e46XW/zMi3ykB16L72OWmun5NCp8G92lliotazAwAAaGMBlAKmBx980C655BL39dVXX+0qn8444wx7+OGH7aabbrKrrrpqfb9WAAAArEbhigrXy0mh028zl1lVdTB0X+d26bbl0C625dDO1r97rlvNDgAAoE0HUG+88Yb985//tCOPPNKmTZtmf/zxh40bN872339/F0TdcMMNBFAAAAAtIL+wzL6vDZ1+n7PcgiszJ+vZKcsFTqp26t0l21WnAwAARE0AtWjRItt0003dvz/66CPX62n77bd3X3fr1s2KiorW76sEAADAymOxZSvsu9rQafq8wjrvTN9uOW5qnUKn7h2zeNcAAED0BlBqKj5nzhwbMWKEffDBB7bBBhtYhw4d3H0//PCDC6EAAACwfgSDQZu3pCQUOs1eVBy6TzVNA3vl2YghnW2LoZ2tU14GbzsAAIiNAGrs2LF23XXX2WuvvWbfffedXX755e72a665xp5++mn729/+tr5fJwAAQNyFTjMXFrnASR8L8leE7lP/pqF92rlKp82HdLZ22Wmt+loBAACaJYD6xz/+YZmZmfbNN9/Yueeea0cccYS7feLEiXbCCSfYaaed1pSnBQAAiGvVwaBNm1sQCp2WFpaF7ktOSrAN+3VwPZ02H9zZsjNSWvW1AgAANHsApQaWp556qvsI98wzzzTl6QAAAOJWVXW1TZm13AVOaiZeUFIRui81JdE2GdDRTa3bdGAny0hr0qEbAABAq2vyUczChQvd9LuKipUHSdXV1VZaWmrffvut3XLLLevrNQIAAMSUykC1Tfoz34VOP/yx2ErKAqH7FDJtNqijbTGki208oIOlpSS16msFAABotQDq7bfftvPOO88CgUBoOV/1KfD/HjBgwFo9n4KrO+64w5577jm3gt7IkSNdX6nevXs3+PhXX33Vzj///Hq3v//++9arVy/37913391mzpxZ5/4DDjjAxo0bt1avDQAAYH0or6iyidOXukbiP01dYmUVVaH7NJ1uiyGdbMuhXWyDvu0tOSmRNx0AAMSUJgVQ99xzj2200Ub273//25588kmrqqqyk08+2T7++GO7+eab7ZJLLlmr57vrrrvsqaeecuGQVtAbP368nXTSSa7JeWpqar3HT5kyxbbaaiv3f4XzK/GtWLHCZs+ebffee697nV56enpTflwAAIAmWVEWcGGTQqdfpi+1ikB16L522am25ZAurqfT4N55lpRI6AQAAGJXkwKoGTNm2E033WQbbrihbb311vbQQw/ZwIED3ceSJUtcQDV69OhGPZem8On7VVG1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lU6fF+avqPc41S9165jpgia/Kl3vLtlueh0AAAAAoHkQQAGIOlp5TivQ+RXpVN00d0mJBYP1H9spL901CHdT6brluh5OGWls+gAAAACgJXEWBqBNq64O2rylJbVBU011k8KnQFX9tCkvO9WFTG4qXW3fppzM1FZ53QAAAACAlQigALSpFekWLSsNNQfX55kLi6yisrreY7PSk2uag9dWNilwap+T1iqvGwAAAACwegRQAFotbMovLA/1a3Jh04IiW1EeqPfYtNQk69e1djW62uqmznnplpDAinQAAAAAEA0IoACskc951iXvKSipqF2Jrqa6Sf8uXFFZ73EpyYnWp0t2aAqdQic1DddKdQAAAACA6EQABWCVkpISLSU12dLTk215cbllZadbaVnAAhUBq6qqPy3OW1FWaTNqQyb1bZqxoNBVO9V7/sQE69k5q6ayqTZs6tEpy5KTEvmtAAAAAEAMIYACsMrwKSs7zZ7/YKq99tl0KymttKyMFNt3zAA7aKdBVlJc7kKo8ooq16fJVTfV9m1SH6dIql/q3ikrFDRpKl3vztmWmpLEbwAAAAAAYhwBFIAGqfJJ4dMz704J3aYQ6ul3prj+TVsO62L/feYHm7ekxIL1F6Szzu3Sayubalal69M1xzLS2OQAAAAAQDzibBCIIwqOKgLVVl5ZZRUVVe5zeaWqmAI1n93XVa5caZ/tB7nKp4a89tkMO2inwVa0otKFT1p9TpVN6tuksEmhU3ZGSov/fAAAAACAtokACmiDIVGgqtrKwgKiCn0OfR3xbxcg1fzbPS78Izxkqg2dGihWqqdvtxzbbrNeruKpIbpdH2ceONw65aVbu+y09f4+AAAAAABiBwEU0OSQKBgKfcrqBUAKkAJW4auKwu4vq/265rF17/cfDU1pW9+02lxaSlLNR6o+13ytnkyqaGqXk+56PjUUQun23OxUG9yrnXsvAAAAAABYHQKoOOJXsY+n1exVSVQv4KkIqyqqDY/qVg6trCjyH366msKjmmqkaqtugeBFq8G5YMgFRGEfqTVBke5LT0m21NSwMCkUKK38SK19jvTagEm3JSaufiBUVARcw3H1fIqk27UaHuETAAAAAKAxCKDiZDUzNZROT0+25cXllpWd7sKDQEXArWLWFkKiVVYDNVg5tLJXUUPT0XxFkj5XVbdESJQQqhyqHwDVVhXVhj+hx4VVHNUPi5Is3QVMiZaUmGitpbIi4Fa7k1c/bXgVPAAAAAAAGoMAKg7Cp6zsNLeamRpKNxQiNCaEqqpWVVBtH6HVhD9+apkLi9bQ6No/j6ayNfv7kJhQr3KoofDHVwulpya7x4RCpdSGwyXdryqlWKRxofExdnR/O2SXwbaiLGCZ6ckuvGzsuAEAAAAAQAigYpwqnxQ+PfPuymlUCqE0rUrTp0Zs0NVe+vCPOo2uQ9PMwqarqUqpuSUmJFhaxFQyVQ7Vn1oW2bsorLKoNjxyU87C7o/VkKi5KWSqKq2w6kDA2rXLsuXLS6yykuAJAAAAALB2CKBiWEJCgpt2p8qnhrz22Qw7aKfBNnF6vhWWVDTyOW0VfYZqq4Ui+gzVrxxa2eg6LTTVzIdECe41o+3x7a7oNw4AAAAAaAoCqBimJtPFpZUNrmImul33H7LTQDetqqHAKLyqSJ9VSURIBAAAAAAA1gYBVAyrrg5aXkaK6/nUUAil2/OyU2274T1YzQwAAAAAADQbGuPEMPV4KisLuIbjDdHtqnzS4wAAAAAAAJoLFVAxrrIi4Fa7k1c/bXgVPAAAAAAAgOZEABUHq5gpZBo7ur8dsstgW1EWsMz0ZFf5pNt1PwAAAAAAQHMigIoDCpmqSiusOhCwdu2ybPnyEqusJHgCAAAAAAAtgx5QccS3eqLlEwAAAAAAaEkEUAAAAAAAAGhWBFAAAAAAAABoVgnBIBOyGkNvU3V17Ry2KJaUlEjjcTB2wHYHbR77KzB2wHYH0YJ9FuJ57CQmJlhCQkKjHksABQAAAAAAgGbFFDwAAAAAAAA0KwIoAAAAAAAANCsCKAAAAAAAADQrAigAAAAAAAA0KwIoAAAAAAAANCsCKAAAAAAAADQrAigAAAAAAAA0KwIoAAAAAAAANCsCKAAAAAAAADQrAigAAAAAAAA0KwIoAAAAAAAANCsCKAAAAAAAADQrAigAAAAAAAA0KwIoNLuioiLeZTTJ3LlzLT8/n3cPa23q1Kn2xRdf8M6BsYMWM3nyZHv11Vd5x8F2B2xz0KZNbcXjZAIoNKuXXnrJjj32WJs4cSLvNNbK448/brvssos9+OCDVlZWxruHRnvkkUds7Nixdu+997LtwVph7KCpHn74Ydt///3t/vvvtw8//JA3Emx30KzY5iBaj3UIoNBsbr31Vrv44outpKTE7rzzTlu4cCHvNhrl7bfftgceeMAOOugge/TRR+3ll1+2QCDAu4dGVSC89957duaZZ7oKuqeeesr+/PNP3jms0a+//mrvv/8+Ywdrbfbs2fbNN9/Yueeeax06dLAnn3zSfvzxR95JsM9Cs2Cbg6b65ZdfWv1YJyEYDAZb9H9E3Pj888+tf//+9sMPP7gqloEDB9o111xjqamprf3S0MYptCwuLrauXbvaDTfc4A7mFWjusMMOlpCQ0NovD23ULbfc4iouk5KSLC8vzwWXN954o+233352/PHHW6dOnVr7JaINq6iosBUrVli7du0YO1hr5eXllpaWZh988IHddtttNmDAADv77LOtb9++vJtoEPssrAu2OWgKXdDXzJLs7OxWO9ahAgrrvd/TpEmT3Mfw4cOtR48e9pe//MV22203V5mgnS3QkOXLl9v333/vTgKzsrJc+CQXXHCBbb/99nb55Ze7CgUg0qJFi9w2Rld0NHYUPommwxx22GH22muvub4sCheAcNreHHLIIW7Kry6OMHbQWEuWLLFLLrnELrroIrv++uutoKDA3b7zzju77c7vv//uKnj97QD7LKwLtjloKvXT1fRwTb373//+58Kn1jxOJoDCevPdd9/ZAQccYJdddpkdeOCB7vOnn37qKlaOPvpo23bbbd3XGvxApCeeeMJdLZ4yZUroNl+ged1117lUXiGUyo4BT9Ne9txzTxsxYoS9/vrrrgJB46a6utrdrxLj0aNH27PPPut2uhT9IpwOtlR6roqVCRMmuP1VVVUVYwerpQtq6p+hg3qNGfW71LbI0wG9QvGvv/7aHnvssdCYAthnoSnY5qCpfvrpJ9trr73czCSFTLpo8uKLL4bub43jZKbgYb34+eef3QA+/PDDbZ999rHffvvNXfnLzc21//znP9axY0ebP3++/fe//3X3nX766e6kEVBQkJiY6JL5m266yQWVV1xxhfXp08e9OdoQ6gBfwZPG12abbWZXXXWV67OB+KZKS4Xdp556qp1zzjmhsRJJtx933HFuWqe2UzvttFOrvF60TbpA8scff7h/a7qvpotXVlZaSkqKGzsqS1d1L2MHfhujfZSq56699trVPlYX4lS5qyq7I488kjcwzrHPwtpim4N1nV1yyimn2KhRo9xxss7FtV8aMmSIXXjhha12nEwFFNZb9ZMO2k877TTr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P/7888932614Cr0JoNo4HWhpcGugKjjQwbk2jrfffrtdcsklrpJFJX2XXnqpTZgwwR2w6QBNjTpVDuqvPmtnqx2wNrSqkkL80I5U4aV2lH76pQ7UdZAuuk1BpaZohi+JrkRfTTsVOminq52xQijEPlVQquJNAZK2LQortXysvhb16RG/fVEgpZM9lRjr5NFP9VUIpZ2urhbuvPPOrfozoWUoWNJBu8bA/vvv7ypVFDipAlcHWzqx03jQQZh6QikE14G8aL+lq8/C2IlfuhCicaHQWmNH/MUSjRVdINE0cgULCsCPP/54NzVGJwE+qNK2iu1O/NCFD213tDLvueeea9tuu60LkLRiq46dtT/TvkgV3f44x++/1ANKAXl4awrtr7SNQmzTsa9CJ21fNG40tU6Vcn6FcQWUOvZVb1Qd94Tvr9SPzu+vdLyjiylaZENjD7FPF11VCKJjHO17FEJq7HgKw/v27etaCYSvGC7du3d351bhLU222mord04fN4Jok6qrq93n2267LXjCCScEq6qq3Nf6/J///Ce4+eabBx9++GF3W2lpaXDhwoV1vv+jjz4KHnXUUcGioqI6t0d+jdh35JFHuvGy5ZZbBufPn+9uq6ysrPOYzz//PLjRRhsFZ8+eHSwrKwsec8wxwVGjRgXnzp0bekx5eXmLv3a0jl9//TW47777Bv/888/QbRUVFW5sFBYW1tlOBQKB0NeXX355cPTo0cHXX3+9xV8z2oZvvvkmePDBBweXLFkSuu3TTz8N7rTTTsFjjz3WfR0+Zrxly5a5MffEE0+06OtF2/P+++8HN9100+AZZ5wRPOigg4JfffVV6L6PP/44OHz48OBmm20WvP3220O3H3300e5YKXLfhvgwYcKE4F//+tdgfn6++3rFihXBXXfd1W2P/LGzti0aN+ecc06wuLjYHdMsX748eMABBwTvueeeesffiF3+d/zKK68EjzvuODdevEceeSS4zTbbBKdMmeIe19B509KlS4Njx4513x+uoX0bYs8777zjzpnGjRsXOn7RMc4LL7xQ55j5vffeC44ZM8Yd+0ydOjVYUlLixs6hhx4aHD9+fGgc+nP8eMIqeG3c1KlT3WdfTaBS9BNOOMHNV1d5saYp/PWvf3VXclQmqseo1E9NFZXaRy4129SlZxGd1NtAJZ2acqemmlr5Tr01dAU5fPUF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euSRR+zee++teeMTE900u7KyMhdCRVY76fsQPxg7YOyA7Q6iBfssMHbANgfRgP1V20PKsR75AEkrL2RlZdmXX37plqLOzs62Aw880N137bXXumlTqnTSnOVZs2bZqFGj1ufLQBRi7ICxA7Y7iBbss8DYAdscRAP2V20PFVDNYJtttnGh05NPPmlz5851t+nrY445xvXoyczMdFP0VAH1wgsv2MCBA1mBAYwdsN1Bq2CfBcYO2O4gGrC/AmMn+iUEWXuyWSxYsMD22msvGzt2rJ1zzjluRbtwfnU73++JKXdg7IDtDloL+ywwdsB2B9GA/RUYO9GNCqhmoil2N954oz333HN2zz33uBXLPDUgD/834RMYO2C7g9bEPguMHbDdQTRgfwXGTnSjAqqZvfrqq/bf//7XhgwZYkcffbSNHj26uf9LxAjGDhg7YLuDaME+C4wdsM1BNGB/1boIoFrAJ598Yh9++KG99NJLdtxxx9mmm27qgqjU1NSW+O8RxRg7YOyA7Q6iBfssMHbANgfRgP1V6yGAakEff/yx/frrr/bGG2/YBRdcYDvssENL/veIYowdMHbAdgfRgn0WGDtgm4NowP6q5RFAtYKCggLLy8trjf8aUY6xA8YO2O4gWrDPAmMHbHMQDdhftRwCqFagxuOJifR/B2MHbHfQ9rHPAmMHbHcQDdhfgbHT9hFAAQAAAAAAoFlRhgMAAAAAAIBmRQAFAAAAAACAZkUABQAAAAAAgGZFAAUAAAAAAIBmRQAFAAAAAACAZkUABQAA0AJ23nlnu+iii9rkez106FC7/fbbW/tlAACAGJbc2i8AAAAgHtxxxx2WnZ3d2i8DAACgVRBAAQAAtIANN9yQ9xkAAMQtpuABAICYn/p2yy232LXXXmsjR460rbfe2i644AJbvnx56DHPPfecHXjggbbZZpvZJptsYvvtt5+99dZbofurq6vdc+i5Nt54Y/f5pptussrKytBjXn/9ddt3333d92+zzTZ23nnn2cKFCxucgrfHHnvYWWedVe+16v897bTTQl+/99577nUNHz7cRo8ebVdffbWtWLFird+DRx991Pbcc0/3PGPGjLErrrjCiouL6zxGX1966aW21VZb2eabb+5e35IlS0L3V1VV2X333Wdjx451P6Peq8MOO8y++uqr0GM0jW+33XZz1V56nu22284KCgpC7/Hee+/t3r8dd9zRPVbPCQAA4gMVUAAAIOY99dRT1rdvX7vuuussPz/fhUczZ860Z555xt2nYOfvf/+7bbnlli4wuf/++12ApCCmW7du7uunn37aLrzwQuvdu7f99NNPLpBKSUlxQc13333nQq3TTz/dhVwLFiyw8ePH27nnnmtPPPFEvdejoEphjkIfPy1v2rRpNnny5FAA9dprr7nXsM8++9g//vEPmzt3rvs/p06dag8//LAlJCQ06mdXMKbXoteuXk/Tp0+366+/3kpLS91n77HHHnP/16233upey7hx49ztt912m/t84403uvdAP5OeR+HanXfeaWeffbZ99NFHlpGR4R43b948+/jjj91rVciXl5dn9957r/v6qKOOsosvvth+++03F0DNnz/fBYMAACD2EUABAICYl5iY6EKbnJwc93WHDh3sjDPOsE8//dRmz55tJ554oguPvJ49e7rKIwVLqtr5+uuvXeXOQQcd5O5XdY8CF/98elx6erqdcsoplpqa6m5r166dTZw40YLBYL2wSAGUAhhVOO2///6hoCg3N9dVSul7FPioWkmfvX79+tlxxx3nAh5VETWGXnuvXr3syCOPdO+DXntmZmaoMslTddQNN9zg/j1q1CgXsun/8RYtWmTnnHOOHX300aHb0tLSXHA3ZcoUVxElgUDAhV0jRoxwXxcVFdldd91lf/3rX+2yyy5zt6kySu+Pvj7++ONt8ODBjfpZAABA9CKAAgAAMU+hjg+L/NfJycn2zTffhKbFFRYWuuogVUZNmDDB3VZRUeE+a9qeqqaOOOII970Kf1TN46nqSRU+mp6m6XU77LCDC1n0uSGqotpiiy3szTffDAVQb7zxhpsmpwBLFUiqojr11FNdoBP+/6hi6vPPP290AKXpgM8++6wL1HbddVf3mlTpFBmKqfornEIrvSeefn5RBZl/nz788MM675O3wQYbhP79ww8/WFlZmXvfwn8WfS36WQigAACIfQRQAAAg5nXt2rXO16oEat++vasCmjVrll1++eX25Zdfuil1AwYMsGHDhrnHqRJJTjrpJMvKyrIXXnjBVSRpSptCE1XwKODRVD1NqXvkkUdcpZX+3alTJ/vb3/5Wp2Iost/Tf/7zH1u2bJnNmTPHBTp+OprvT3XllVe6j0iqRmqsv/zlL66HlaYaqhJJlVeq8NL0Pt3nqSoq8j3yP7+omkuvRZ9V/TVo0CDr0aNHnffJ03vl+Z9F1WENWZufBQAARC8CKAAAEPMU8oRT82vdpql4CkYUPD3//POuckeVUeqz9Morr9QJYzSFTR9Lly51U9PuueceN/1MFTyqWtJ0OX2ot5Iac6unknpLbbrppq5pd6S99trL3a9peKooUijkq5A0FU/UV0pT5iKpr9LaUGWWPjQd7rPPPnM9rc4//3z3/0WGcw1RryqFcOr9pEothXR6T/Q+/O9//1vt9/qfRcGdphBGUlAHAABiH6vgAQCAmPfJJ5/UmSb2/vvvu+lgQ4YMsRkzZtjBBx/seiApfPKPF1UOiVZ7U1gkHTt2dNPZFEZpiprCGTXzVn8oVQKpOminnXZyfZB8U+5VBTN6nF6LQhz1hfLT4hTw6P9RZZRel/9QWKSpcJMmTWr0z64G5up3JZqGqOBL/a708ze2+kgBmSqZjjnmGFf5pPCpofepIQrgFPCpaXn4z6L3+uabb3Y/IwAAiH1UQAEAgJin1da0upwCFP1bwYeqlTQFTZU5Tz75pFvtTqGQGpOreklUzeR7Lz300EOuWkfT7RSmaKqdqpNURaVpePpa/aQUJFVWVtoDDzzgGm3rvlXRY7WKniqyNCXPS0pKcg2/NTVQ/1ZQpbBLU+j0f2+00UaN/tn1///73/92Idn222/vnueOO+5w1Uh+quGa9O/f3/WeUtWXgiN9KDRT1Vj4+9QQTXVU9ZRW11NYp35a+hn0tQK3xr4GAAAQ3QigAABAzNNKdgqXVA2kXkcHHHCAC3hEoc4111zjwiNNpVOFz9133+36MX377beuh9PZZ5/t7lMPqDvvvNNVEqmJ9rnnnuueQ429FWQppDrzzDNdsKLpbQqyFEKtir5Pz6Wm5Ap5wh1yyCGul5KCLDUR1+tW43L9P3p8Y6l6S4HYM8884/pAabU+rXKnKXiqTGoMvUa9T1olT++FXpemKz7xxBN28sknu/fJNxVviN73zp07u/9fP4+mEOo1/POf/6zTHB4AAMSuhGBk10gAAIAYomBElUrjxo1r7ZcCAAAQt6iAAgAAiEKatrem64iqxNIUPgAAgNZGAAUAABCFdtttN5s7d+5qH6PKr8cff7zFXhMAAMCqMAUPAAAgCk2ZMqXOyn4NUa8mragHAADQ2gigAAAAAAAA0KwSm/fpAQAAAAAAEO8IoAAAAAAAANCsCKAAAAAAAADQrAigAAAAAAAA0KwIoAAAAAAAANCsCKAAAAAAAADQrAigAAAAAAAA0KwIoAAAAAAAAGDN6f8BPHqPsDT9VRMAAAAASUVORK5CYII=" - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 3 - }, - { - "cell_type": "markdown", - "id": "6def67b9", - "metadata": {}, - "source": [ - "## ML-модель: влияние доли пассивных показов на заказ\n", - "Target: `has_order`. Фичи: объёмы актив/пассив, клики, возраст, пол, платформа, пассивная доля." - ] - }, - { - "cell_type": "code", - "id": "ae61b923", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:53.004801Z", - "iopub.status.busy": "2025-12-12T19:11:53.004396Z", - "iopub.status.idle": "2025-12-12T19:11:53.143675Z", - "shell.execute_reply": "2025-12-12T19:11:53.141866Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:47.045615Z", - "start_time": "2025-12-12T19:27:47.013172Z" - } - }, - "source": [ - "X = client[[\n", - " \"active_imp_total\",\n", - " \"passive_imp_total\",\n", - " \"active_click_total\",\n", - " \"passive_click_total\",\n", - " \"passive_share\",\n", - " \"age\",\n", - " \"gender_cd\",\n", - " \"device_platform_cd\",\n", - "]]\n", - "X = X.copy()\n", - "X[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\n", - "X[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n", - "y = client[\"has_order\"]\n", - "\n", - "numeric_cols = [\"active_imp_total\", \"passive_imp_total\", \"active_click_total\", \"passive_click_total\", \"passive_share\", \"age\"]\n", - "cat_cols = [\"gender_cd\", \"device_platform_cd\"]\n", - "\n", - "preprocess = ColumnTransformer(\n", - " [\n", - " (\"num\", Pipeline([(\"scaler\", StandardScaler())]), numeric_cols),\n", - " (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n", - " ]\n", - ")\n", - "\n", - "model = Pipeline([(\"pre\", preprocess), (\"clf\", LogisticRegression(max_iter=1000))])\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", - "model.fit(X_train, y_train)\n", - "proba = model.predict_proba(X_test)[:, 1]\n", - "auc = roc_auc_score(y_test, proba)\n", - "coef = model.named_steps[\"clf\"].coef_[0]\n", - "features = model.named_steps[\"pre\"].get_feature_names_out()\n", - "coef_series = pd.Series(coef, index=features).sort_values(key=abs, ascending=False)\n", - "auc, coef_series.head(10)\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "(0.6804173758429694,\n", - " num__passive_click_total 0.638861\n", - " num__passive_share 0.303223\n", - " num__active_imp_total 0.216964\n", - " cat__device_platform_cd_Android 0.186635\n", - " num__active_click_total -0.150704\n", - " cat__gender_cd_M 0.130234\n", - " cat__device_platform_cd_iPadOS -0.105558\n", - " num__passive_imp_total -0.087140\n", - " num__age -0.072639\n", - " cat__device_platform_cd_iOS 0.038500\n", - " dtype: float64)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "id": "7df5ccb7", - "metadata": {}, - "source": [ - "## Вывод по гипотезе\n", - "- Линейный рост доли клиентов с заказом при увеличении `passive_share`.\n", - "- В модели коэффициент при `passive_share` положительный и по модулю в топ‑фичах; AUC ~0.68. Гипотеза подтверждается: высокая доля пассивных показов ассоциирована с большей вероятностью заказа при контроле объёма и кликов." - ] - } - ], - "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 -} diff --git a/alternative/passive_share_orders/eda_utils.py b/alternative/passive_share_orders/eda_utils.py deleted file mode 100644 index 802a6d8..0000000 --- a/alternative/passive_share_orders/eda_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -from pathlib import Path -from typing import Dict, Iterable, List - -import numpy as np -import pandas as pd - -# Paths and column groups -DATA_PATH = Path("dataset/ds.csv") -CATEGORIES: List[str] = ["ent", "super", "transport", "shopping", "hotel", "avia"] - -ACTIVE_IMP_COLS = [f"active_imp_{c}" for c in CATEGORIES] -PASSIVE_IMP_COLS = [f"passive_imp_{c}" for c in CATEGORIES] -ACTIVE_CLICK_COLS = [f"active_click_{c}" for c in CATEGORIES] -PASSIVE_CLICK_COLS = [f"passive_click_{c}" for c in CATEGORIES] -ORDER_COLS = [f"orders_amt_{c}" for c in CATEGORIES] - -NUMERIC_COLS = ( - ACTIVE_IMP_COLS - + PASSIVE_IMP_COLS - + ACTIVE_CLICK_COLS - + PASSIVE_CLICK_COLS - + ORDER_COLS - + ["age"] -) -CAT_COLS = ["gender_cd", "device_platform_cd"] - - -def safe_divide(numerator: pd.Series | float, denominator: pd.Series | float) -> pd.Series: - """Divide with protection against zero (works for Series and scalars).""" - if isinstance(denominator, pd.Series): - denom = denominator.replace(0, np.nan) - else: - denom = np.nan if float(denominator) == 0 else denominator - return numerator / denom - - -def normalize_gender(series: pd.Series) -> pd.Series: - cleaned = series.fillna("UNKNOWN").astype(str).str.strip().str.upper() - mapping = {"M": "M", "MALE": "M", "F": "F", "FEMALE": "F"} - return cleaned.map(mapping).fillna("UNKNOWN") - - -def normalize_device(series: pd.Series) -> pd.Series: - cleaned = series.fillna("unknown").astype(str).str.strip() - lowered = cleaned.str.lower().str.replace(" ", "").str.replace("_", "") - mapping = {"android": "Android", "ios": "iOS", "ipados": "iPadOS", "ipad": "iPadOS"} - mapped = lowered.map(mapping) - fallback = cleaned.str.title() - return mapped.fillna(fallback) - - -def add_age_group(df: pd.DataFrame) -> pd.DataFrame: - bins = [0, 25, 35, 45, 55, np.inf] - labels = ["<25", "25-34", "35-44", "45-54", "55+"] - df["age_group"] = pd.cut(df["age"], bins=bins, labels=labels, right=False) - return df - - -def add_totals(df: pd.DataFrame) -> pd.DataFrame: - df["active_imp_total"] = df[ACTIVE_IMP_COLS].sum(axis=1) - df["passive_imp_total"] = df[PASSIVE_IMP_COLS].sum(axis=1) - df["active_click_total"] = df[ACTIVE_CLICK_COLS].sum(axis=1) - df["passive_click_total"] = df[PASSIVE_CLICK_COLS].sum(axis=1) - df["orders_amt_total"] = df[ORDER_COLS].sum(axis=1) - df["click_total"] = df["active_click_total"] + df["passive_click_total"] - df["imp_total"] = df["active_imp_total"] + df["passive_imp_total"] - df["active_ctr"] = safe_divide(df["active_click_total"], df["active_imp_total"]) - df["passive_ctr"] = safe_divide(df["passive_click_total"], df["passive_imp_total"]) - df["ctr_all"] = safe_divide(df["click_total"], df["imp_total"]) - df["cr_click2order"] = safe_divide(df["orders_amt_total"], df["click_total"]) - df["cr_imp2order"] = safe_divide(df["orders_amt_total"], df["imp_total"]) - return df - - -def add_flags(df: pd.DataFrame) -> pd.DataFrame: - df["has_active_comm"] = (df[ACTIVE_IMP_COLS + ACTIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_passive_comm"] = (df[PASSIVE_IMP_COLS + PASSIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_any_order"] = (df[ORDER_COLS].sum(axis=1) > 0).astype(int) - df["order_categories_count"] = (df[ORDER_COLS] > 0).sum(axis=1) - return df - - -def load_data(path: Path | str = DATA_PATH) -> pd.DataFrame: - df = pd.read_csv(path) - df["business_dt"] = pd.to_datetime(df["business_dt"]) - df["gender_cd"] = normalize_gender(df["gender_cd"]) - df["device_platform_cd"] = normalize_device(df["device_platform_cd"]) - df = add_age_group(df) - df = add_totals(df) - df = add_flags(df) - return df - - -def describe_zero_share(df: pd.DataFrame, cols: Iterable[str]) -> pd.DataFrame: - stats = [] - for col in cols: - series = df[col] - stats.append( - { - "col": col, - "count": series.count(), - "mean": series.mean(), - "median": series.median(), - "std": series.std(), - "min": series.min(), - "q25": series.quantile(0.25), - "q75": series.quantile(0.75), - "max": series.max(), - "share_zero": (series == 0).mean(), - "p95": series.quantile(0.95), - "p99": series.quantile(0.99), - } - ) - return pd.DataFrame(stats) - - -def build_daily(df: pd.DataFrame) -> pd.DataFrame: - agg_cols = ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS - daily = df.groupby("business_dt")[agg_cols].sum().reset_index() - daily = add_totals(daily) - daily["day_of_week"] = daily["business_dt"].dt.day_name() - return daily - - -def build_client(df: pd.DataFrame) -> pd.DataFrame: - agg_spec: Dict[str, str] = {col: "sum" for col in ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS} - meta_spec: Dict[str, str | callable] = { - "age": "median", - "gender_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "UNKNOWN", - "age_group": lambda s: s.mode().iat[0] if not s.mode().empty else np.nan, - "device_platform_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "Other", - } - agg_spec.update(meta_spec) - client = df.groupby("id").agg(agg_spec).reset_index() - contact_days = df.groupby("id")["business_dt"].nunique().rename("contact_days") - imp_day = df.copy() - imp_day["imp_day_total"] = imp_day[ACTIVE_IMP_COLS + PASSIVE_IMP_COLS].sum(axis=1) - max_imp_day = imp_day.groupby("id")["imp_day_total"].max().rename("max_impressions_per_day") - client = add_totals(client) - client = add_flags(client) - client = client.merge(contact_days, on="id", how="left") - client = client.merge(max_imp_day, on="id", how="left") - client = add_contact_density(client) - return client - - -def add_contact_density(df: pd.DataFrame) -> pd.DataFrame: - # contact_days must already be present - if "contact_days" in df.columns: - df["avg_impressions_per_contact_day"] = safe_divide(df["imp_total"], df["contact_days"]) - return df - return df diff --git a/alternative/saturation_effect/analysis.ipynb b/alternative/saturation_effect/analysis.ipynb deleted file mode 100644 index 0225fd7..0000000 --- a/alternative/saturation_effect/analysis.ipynb +++ /dev/null @@ -1,421 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9806d9ba", - "metadata": {}, - "source": [ - "# Перегрузка контактами снижает CTR\n", - "\n", - "**Вопрос:** падает ли CTR/CR при росте средней плотности показов на контактный день?\n", - "\n", - "**Гипотеза:** высокая плотность показов (спам) уменьшает CTR и вероятность заказа. Проверяем через ML-классификацию высокого CTR." - ] - }, - { - "cell_type": "code", - "id": "0891ca2a", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:23.062332Z", - "iopub.status.busy": "2025-12-12T19:11:23.062008Z", - "iopub.status.idle": "2025-12-12T19:11:29.703049Z", - "shell.execute_reply": "2025-12-12T19:11:29.700852Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:48.305598Z", - "start_time": "2025-12-12T19:27:47.155254Z" - } - }, - "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 sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.linear_model import LogisticRegression\n", - "from sklearn.metrics import roc_auc_score\n", - "\n", - "sns.set_theme(style=\"whitegrid\")\n", - "plt.rcParams[\"figure.figsize\"] = (10, 5)\n", - "\n", - "project_root = Path.cwd().resolve()\n", - "while not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\n", - " project_root = project_root.parent\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 = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n", - "conn.close()\n" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "code", - "id": "9f0e5ca7", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:29.710292Z", - "iopub.status.busy": "2025-12-12T19:11:29.709769Z", - "iopub.status.idle": "2025-12-12T19:11:32.169479Z", - "shell.execute_reply": "2025-12-12T19:11:32.167853Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:48.938590Z", - "start_time": "2025-12-12T19:27:48.314667Z" - } - }, - "source": [ - "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", - "client = df.groupby(\"id\").agg(\n", - " {\n", - " \"imp_total\": \"sum\",\n", - " \"click_total\": \"sum\",\n", - " \"orders_amt_total\": \"sum\",\n", - " \"business_dt\": \"nunique\",\n", - " \"age\": \"median\",\n", - " \"gender_cd\": lambda s: s.mode().iat[0],\n", - " \"device_platform_cd\": lambda s: s.mode().iat[0],\n", - " }\n", - ").rename(columns={\"business_dt\": \"contact_days\"})\n", - "\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", - "client[\"avg_imp_per_day\"] = eda.safe_divide(client[\"imp_total\"], client[\"contact_days\"])\n", - "client.head()\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - " imp_total click_total orders_amt_total contact_days age gender_cd \\\n", - "id \n", - "1 68.0 17.0 0 13 58.0 M \n", - "2 116.0 23.0 3 15 54.0 M \n", - "3 293.0 37.0 2 31 70.0 F \n", - "4 57.0 15.0 0 12 43.0 F \n", - "5 43.0 16.0 1 10 46.0 M \n", - "\n", - " device_platform_cd ctr_all cr_click2order avg_imp_per_day \n", - "id \n", - "1 Android 0.250000 0.000000 5.230769 \n", - "2 Android 0.198276 0.130435 7.733333 \n", - "3 Android 0.126280 0.054054 9.451613 \n", - "4 Android 0.263158 0.000000 4.750000 \n", - "5 Android 0.372093 0.062500 4.300000 " - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
imp_totalclick_totalorders_amt_totalcontact_daysagegender_cddevice_platform_cdctr_allcr_click2orderavg_imp_per_day
id
168.017.001358.0MAndroid0.2500000.0000005.230769
2116.023.031554.0MAndroid0.1982760.1304357.733333
3293.037.023170.0FAndroid0.1262800.0540549.451613
457.015.001243.0FAndroid0.2631580.0000004.750000
543.016.011046.0MAndroid0.3720930.0625004.300000
\n", - "
" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "id": "da15b5bc", - "metadata": {}, - "source": [ - "## Визуализация зависимости CTR от плотности показов" - ] - }, - { - "cell_type": "code", - "id": "3541e285", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:32.175488Z", - "iopub.status.busy": "2025-12-12T19:11:32.175156Z", - "iopub.status.idle": "2025-12-12T19:11:32.526850Z", - "shell.execute_reply": "2025-12-12T19:11:32.525156Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:49.183790Z", - "start_time": "2025-12-12T19:27:49.074446Z" - } - }, - "source": [ - "bins = pd.qcut(client[\"avg_imp_per_day\"], 10, duplicates=\"drop\")\n", - "binned = client.groupby(bins)[\"ctr_all\"].median().reset_index()\n", - "binned[\"avg_imp_per_day\"] = binned[\"avg_imp_per_day\"].astype(str)\n", - "plt.figure(figsize=(12, 4))\n", - "sns.lineplot(data=binned, x=\"avg_imp_per_day\", y=\"ctr_all\", marker=\"o\")\n", - "plt.xticks(rotation=40)\n", - "plt.title(\"Медианный CTR vs плотность показов\")\n", - "plt.tight_layout()\n", - "plt.show()\n" - ], - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/mx/y1qcnthj1154ngqj00r8gz480000gn/T/ipykernel_85425/2642699463.py:2: 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", - " binned = client.groupby(bins)[\"ctr_all\"].median().reset_index()\n" - ] - }, - { - "data": { - "text/plain": [ - "
" - ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAABKAAAAGACAYAAACazRotAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAuvpJREFUeJzs3Qd8VfX5x/Ene5GQsPcGEQeioqKiIo627t32r1Ws1VpXq9ZRrVrrqtvWPWvd1bqrFfeeIKKI7D0DScje9//6/MLvehMCAnLHSb7v1+u8Qm5uws395ZzzO895nueXFAqFQiYiIiIiIiIiIhIlydH6wSIiIiIiIiIiIgpAiYiIiIiIiIhI1CkDSkREREREREREokoBKBERERERERERiSoFoEREREREREREJKoUgBIRERERERERkahSAEpERERERERERKJKASgREREREREREYkqBaBERERERERERCSqFIASEREREREREZGoSo3ujxcREZETTjjBPvvsMxs1apQ9+eSTrb4hf/jDH+yVV16xI444wq677jq9aetx7bXXWkVFhZ133nk2Y8YMO/vss+3jjz+2lJSUH3zPeN5jjz1mX331lZWWllqPHj1s3333tVNOOcU6d+7cbKw2xI9Ra89NSkqy7OxsGzBggJ144ol22GGHaSxFREREFIASERGJjeTkZJsyZYotX77cBT4iVVZW2ttvv62h2AgnnXSSHX/88bbbbrtZWlqa/fnPf96o4NONN95o999/v/3kJz+xSy65xPLz810A67777rOJEyfao48+aj179rTLL7/cysvLw9/3l7/8xX3kca9Tp07hf48YMaLZ1xoaGtwY//Of/7QLLrjA/T977723xlZERETaPWVAiYiIxACBitmzZ9v//vc/F0SJRPApKyvL8vLyNBY/gCAR7+HChQtd1hIBnh/y3//+1wWaLr744mbvPUEsgkNkNF199dV2++2325AhQ5p9b4cOHdzHHXbYodWfzddb+9pee+1lY8aMsWeffVYBKBERERH1gBIREYkNyrIIdhA8aYnSuwMPPNBSU9e9L/TGG2/YkUceadttt53tsccedtVVV7mMqUg///nPbauttlpn+/TTT93XFy9e7D4nGOLV1NTY+PHj3eOR2Tv33nuvHXzwwbb99tu7wAo/+5NPPgk/5x//+Eez7/F4jK+B/zfy//coWWNr7XtaQ3ncRRddtM7zyXwaPHiwdezYMfy78zuuD78TgSVK4lqiVO6Pf/yjK48MhUK2pWRkZFh6eroryWsNWVJbb721y7yKVFRUZNtss43LoMKHH35oxx57rHt9o0ePttNPP93mzJmz3v/Xj3VrW+R7z9/C+p4X+XdSVlbmyh73228/9zfI38Yzzzzzg/8XY9famK/v7+Prr7+2X//617brrrvajjvuaL/97W9t1qxZzb5v5cqVduGFF7rAHu8HmXBffvml+xr/3/peC69zfX+3G7Kx7yX70h133OGy63iPDjjgAPc319jYGH5Oy/eBgCfPfe+998LjTrbduHHjbNttt7VddtnFzjjjjGZ/1/z71FNPde8PxxICppF/s7w/BFn5Gvvv0UcfbW+++Waz3ynyd+Dvj/fyT3/6k/sdREREok0ZUCIiIjHys5/9zH7/+983K8Oj3IuL0Iceeih8Meq99NJLdv7559shhxzivm/JkiV2yy23uEwqnu+DG1w8nnXWWbbnnnu6z6dNm2ZXXnnlBl8L5WgtgzaUqT3xxBOuvxIXqCtWrHAX1uecc4698847LksrkbzwwgvhAMT6FBYW2nfffef6PK0vGPTLX/5ys18DAYD6+vpmQTzGifeNXlXr6wHF+BNkIDuLQIpHgJKfedBBB9miRYvsd7/7nR111FF27rnnur5VN998swtCvP76666sc30IVO2zzz7rlBK2RBCja9eu4ffqzDPPDH+turravTerV692vbZ69+7tAqKUMK5atcpOPvlke+qpp9xz+fu46667wj+P4NvGIsDJ+BB8uuaaa9zf8z333OOCi//+979dsJH38he/+IV7fwkYdu/e3R588EH3Gp577jn3/9bW1oZ/h8jfv1u3bvZjbOi9ZKwIllFey/87fPhwF1i79dZb3fj99a9/XefnTZ061e1nt912Wzjwedppp9maNWvc/t6lSxdXHsrPoLzzgQcecM/hb4H35qabbnJ/YwSxyALkfWE8CDgR+KSfXEFBgQskEsS6/vrr7dBDDw3//zzvmGOOcT+LwB/HFMaM7xMREYkmBaBERERihItYgjiRZXgEEriI3GmnnZo9lwtOAkJjx451HyMzdvjed999N3xRTEbU0KFDw6VgP5TNsGzZMleSRqYNwarIDAouQiMzNbigJbjFBfH6ytDigYAE70vL36G1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T0++PiP8GEGoJyY2fX7wHgOtoao2jq9QRERERERERNo69YBqw5KSklzZHZlPrXnx/bmWlZnqniciIiIiIiIiEi0KQLVhyclJVl5V5zKeWsPjbDxPRERERERERCRaFIBqwxobQ9YhK831fGoNj2dmpNp/3p1jK4srY/76RERERERERKR9UACqDQuFQlZdXe8ajreG/k9TZhbaix/Ms4vv+cRuffor+3ruamsMhWL+WkVERERERESk7VIT8jaurrberXbnez61XAVv8rfLbdtBneybuUU2dc5qt3UvyLJ9d+pje2zb07Iz9SciIiIiIiIiIj+OogttXENDo1WU17hsp2PGD7XK6noXVKqqrnePD+nd0c49dgdbXlRpb01ebB9+vcxWFFfZE2/Msmffm2u7b9vD9t2xj/XukhPvX0VEREREREREAkoBqHYShGqoqrXG+nrLz8+xkpIKq6trbPacHp2y7Zf7DbMjxg6yT6YttzcnL7Glqyrs7clL3LZ1/wLbb6c+NnJIFzUtFxEREREREZFNogBUO+JbO22oxVNWRqqN27GP7TOqt323oNjemLTYpsxeZdMXFLutc16m7btjbxs7spdrcC4iIiIiIiIi8kMUgJJWJSUl2dYDOrltVUmVvf3lEnvvq6W2urTann5njj3/wTzbdUR3lxXVr3uu3kURERERERERWS8FoOQHdcnPsmPGDbHD9hxon367wt6ctNgWriy3D6Yuc9vQPh1t/E59bMdhXS01RQsrioiIiIiIiEhzCkDJRktPS3Gld3tu39NmL1njAlGTZhTarMVr3JbfId2V7u09spd17JChd1ZEREREREREHAWgZLPK84b2yXdbcVmNvTtlib0zZamVlNfa8+/Ps5c+nG+jt+5m43fsY4N65bnni4iIiIiIiEj7pQCU/CgFuRl2+NhBdtCYATZpxkqXFTVnaal9Mm2F2wb0yHXlebts3c3SUlP0bouIiIiIiIi0QwpAyRaRlppsu23Tw23zlpXaW5MW26fTV9j85WX2wH+n27/fnm17jexl40b1tk55mXrXRURERERERNoRBaBkixvYM89+ffAIO2bfIfbelKVuBT1K9f778QJ79ZOFNmpYF7d63rC++SrPExEREREREWkHFICSqMnLTreDdx9gP92tn305c5Urz5uxqMQ1Lmfr0zXH9t2pj40Z0cMy0lWeJyIiIiIiItJWKQAlUZeSnGw7D+/mtsUry+3NyYvt42+W2+LCCvvX/2bYM2/PcSvrEYzqlp+lERERERERERFpYxSAkpjq062DnfiT4Xb0PoPtg6nL7K3Ji62wpNomfr7IXv98kW0/uLON37mPjRjQyZK1ep6IiIiIiIhIm6AAlMRFTmaaHbhLP9t/5742de5q17T8m3lF9tWc1W7r3inbxu/Y2/bYrqdlZejPVERERERERCTIdGUvcZWcnGQ7DOnitmWrK+ztyUvsg6+X2YqiSnv8jVn2n/fm2h7b9rDxO/Wxnp1zNFoiIiIiIiIiAaQAlCQMAky/3H+YHbHXIPvom+WuPG/Z6kp7a/ISt20zoMD1iRo5uIsLXImIiIiIiIhIMMQ9ANXY2Gi33367Pf3001ZWVmajR4+2yy67zPr27dvq86dNm2bXX3+9TZ061TIyMuyAAw6wP/7xj5abmxt+Do8tWLCg2fcdccQRdt1110X995Efj5I7Mp723bG3fbug2N78YrF9NXuVTZtf7LYuHTNt3I69bez2vaxDVprechEREREREZEEF/cA1J133mmPP/64Cw716NHDbrjhBjvllFPspZdesvT09GbPXbVqlU2YMMH2228/u+KKK6y4uNj+/Oc/20UXXWR33HGHe05lZaUtWrTI7rnnHttmm23C35uZmRnz301+nKSkJNtmQCe3FZZU2dtfLrH3v1pqq9ZU29Nvz7EX3p9nu23T3fbdsY/16/59AFJEREREREREEktcA1C1tbX24IMP2vnnn2/77LOPe+yWW26xsWPH2sSJE+3ggw9u9vwlS5bYnnvuaVdeeaWlpqbawIED7dhjj3Xf482ePdtlVY0aNco6duwY899JoqNrfpYdO26IHbbnQPv02xX2xheLbXFhub331TK3DevT0cbv3NdGDe1iqSnJGgYRERERERGRBBLXANR3331nFRUVNmbMmPBjeXl5NmLECPv888/XCUCNHDnSbr755vDnc+bMsRdeeMH22GOP8GMzZsywLl26KPjURmWkpdheI3vZ2O172qzFa+zNSYtt0oxCm7l4jdsKcjNsnx162d479La8nOYZdCIiIiIiIiLSDgNQy5cvdx979uzZ7PFu3bqFv7Y+Bx54oM2fP9969+7tekhFBqCys7Pt7LPPtsmTJ1tBQYEdddRR9qtf/cqSk5UZ05bK84b1zXdbcVmNK897b8oS9+/n3p9nL30030YP72bjd+prg3rlxfvlioiIiIiIiLRrcQ1AVVVVuY8tez3RXHzNmjUb/N4bb7zRfT89owgukQmVk5Njs2bNstLSUhegOuOMM2zSpEnuOfy8c84550e93tTUYAewUtaWpvmPbUXXgiw7dt8hbvW8z6avsNc/X2Rzl5bax9NWuI0A1P4797VdRnS3tICOYVsdu/ZAYxdcGrvg0tgFl8Yu2DR+waWxCy6NXXCltMNrvKRQKBSK13/+2muvuUylr776qlmTcAJF9Ie66667fvBnrFixwvbee2/XxPzwww9331dTU9NsVbx7773X/SyCUZubBcXbRNaNBMPMhcX28gdz7f0pS62+odE91rFDuh242wD76ZgB1iU/K94vUURERERERKTdiGsGlC+9W7lypfXr1y/8OJ9vtdVW6zx/7ty5tnDhwnDDcnTv3t3y8/NdIMpnU7XMqBo2bJhbHY8sKEryNkdjY8hKSystyIis5uVlWWlplTWsDcq0VV1z023CT4fbUXsNsne+XOJ6RVGe9+83Ztozb86ynYd3tf127mtb9csPRGCxPY1dW6OxCy6NXXBp7IJLYxdsGr/g0tgFl8YuuFLayDUev8PGZnHFNQA1fPhw69Chg3366afhABTlc99++60df/zx6zz/o48+suuvv94++OAD16wcBKSKi4tt8ODBLktp//33d5lQZ555Zvj7vv76a+vatetmB5+8+vrg/lFE4o+7rfwuPyQ7I9V+tlt/O2B0X/ty1ioXiJq5qMQ+m77SbX27dbDxO/WxXUd0dw3OE117Gru2RmMXXBq74NLYBZfGLtg0fsGlsQsujV1wNbSja7y4BqDIVCLQRD+nTp06uYbi9Gvq0aOHHXDAAdbQ0GBFRUWunI4SPVbFo5zuj3/8o51//vkuo+mqq66y7bff3saNG+cyWQhAPfDAAzZo0CDbdttt7eOPP7b777/fLrnkknj+qhJnqSnJrik528IVZfbW5CX2ybTltmhluf3z1e/s6bdn29jte9m4HXtbV5XniYiIiIiIiLSdHlAgyHTzzTfbs88+a9XV1TZ69Gi77LLLrE+fPrZ48WIbP368XXvttXbkkUe658+bN8/1e6KfU0pKivv6RRddFM6Iqq+vt3vuuceee+45t5IeP+fkk0+2Y4899ke+zkYr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eanNX1Zm85eX2qKV5S6o9c3cIrd5HXPSXSCKXlKup1TPXMvLbl6SLJszljpmBpXGLrg0dsGm8QsujV1waeyCq6EdzTXjGoCiVxOBJvo5derUyTUUp6cTTcQPOOAAa2hosKKiIsvNzXUleqyKd++999of//hHO//8812fqKuuusq23357GzdunPuZEyZMsFNPPdWtpLfXXnvZf/7zH5s+fbpdffXV8fxVRaQdnkgaqmqtsb7e8vNzrKSkwurqNv3EkpKcbH26dXDb2O2bHqN/1JJV5TaPgNQysqXKbOmqCltTUWtTZq9ym9c5L9MFosKBqR65lp2ZtiV/VRERERERkcQOQOHss8+2+vp6u/TSS10T8dGjR9sDDzxgaWlptnjxYhs/frxde+21duSRR7oSu4cfftiuu+46+8UvfmEpKSnu6xdddJH7N/bcc0+75ppr7M4777RbbrnFhgwZYnfffbfLkBIRibVQqPnHLYFG5QN6EFDKMxvV2z1WU9dgi1YQlCp1WVIEpZYXVdrq0mq3TZpRGP7+7gVZzTKl+nfPtYz0pmOoiIiIiIhINCSFQlvysqhtZzMUFVVYkLGKH43Ui4sr2k2KX1uhsQuueI4dvaPmL28q2/PZUqvWNK0WGole5r265NhAglprs6X6dO3gAl3tmfa74NLYBZfGLtg0fsGlsQsujV1wpbaR6/NOnXKC0QNKRESih9Xztu5f4DavrLLWNTZvypRq+lhSXmtLCivc9sHXy9zzUpKTXNnfQN9Pqkeu9e6a40oCRURERERENpUCUCIi7UhudrptO6iz27zishqXJUWTc9/svLyqzgWq2GzKUve89NRk69u9Q7NMqe6dsi2ZFCoREREREZENUABKRKSdK8jNsILcrjZqaFf3OZXZq9dUhzOk2BasKLOqmgabs6TUbV5mesra5ubfB6W6dMx0q5KKiIiIiIh4CkCJiEgzBI+65Ge5befh3dxjjaGQrSiqDAel+LhweZlV1zbYdwtL3OZ1yEpb2+A8d222VJ4LcomIiIiISPulAJSIiPwgyux6ds5x25hterjHGhobbdmqymb9pBatLHfle9/MK3Kb17FDerh0z2dL5WWn650XEREREWknFIASEZHNQkNyGpWzjR3Z9FhdfaMtLiz/PlNqWZktXVVha8prbcrsVW7zOudl2kACUj3zXLPz/j3yLDtT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RV+pnnkuECYbR/tdcKW0w+vzuO/ZVVVV7mN6enqzxzMyMmzNmu+b3a0PfaAeffRR12S8U6dONnfu3PX+PN8janMkJydZQUGOtQV5eVnxfgmymTR2waWxCy6NXXBp7IJLYxdsGr/gys3dctcJ3bvl2ejtvl8kqqqm3uYuWWOzFpXYbLbFxbaksMIKS6rc9tn0leHn9u6aY0P6FNiQvvk2tG++Derd0bIy4n7pmtC03wVXXju6Po/7XuxL6egFFVlWR7AoK2v9A0FTu9tuu83uuusuO/300+2EE05Y5+dF+qGf90MaG0NWWlppQUZklT/u0tKqVlNqJXFp7IJLYxdcGrvg0tgFl8Yu2DR+wRWrsetVkGm9CnrY3tv3cJ9XVNfZgmVl4SypuUtLbdWaaheYYnv3y8XueWRk0YvKZ0mx9evewdLTUqy9034XXClt5Pqc32Fjs7jiHoDypXIrV660fv36hR/n86222qrV76mrq7OLL77YXn75ZffxpJNOavXnDR48uNnP6969+496rfX1wf2jiMQfd1v5XdobjV1waeyCS2MXXBq74NLYBZvGL7hiPXYZqSk2rG++27yyylpbsLzM5tHkfG2zc8r2fFDqg6lNLVdSkpOsd5ccG9CTRueU7uVan64dLLUdlTNF0n4XXA3t6Po87gGo4cOHW4cOHezTTz8NB6BoJv7tt9+6lexac8EFF9jrr79uN910kx100EHNvta5c2cbOHCg+3m+EXl9fb198cUX9stf/jIGv5GIiIiIiIhsjtzsdNt2UGe3eSXlNU2r7vnV95aVWmllnS1cWe62975qCkqlpiS5BukuILW2yXmvLtmuebqIxF/cA1D0aiLQdOONN7oeTr1797YbbrjBevToYQcccIA1NDRYUVGR5ebmuvK6Z5991l555RUXhNpll12ssLAw/LP8c04++WS7+uqrrX///rbddtu5JuXV1dV29NFHx/V3FRERERERkU2T3yHDdhjC1iXcjoWsqHl+5b21QamK6nr3GJuXnpps/brnrg1INWVL9eiU7Xr8ikg7C0Dh7LPPdllKNBInUMRqdg888IClpaXZ4sWLbfz48XbttdfakUce6crucP3117stkn/Osccea2VlZXbrrbdaSUmJbbvttvbQQw+5AJeIiIiIiIgEV1JSknXKy3TbTlt1DQelCtdUN8uS4mN1bYPN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JSIiIiIiIiJRR1Bpj+16uq2uvsGmLyixKbMK7cvZq2xNea19MaPQbWRRDe3TMVyq160gW6PTBigAJSIiIiIiIiIxlZaa4lbIYzs+FLIFy8vsy1mFrlxvcWGFzVhU4rYn35ptvbvkhHtMDeyZ5wJUEjwKQImIiIiIiIhI3BBQIrDEduReg21lSZV95fpGFdrMRWtsyaoKt/334wXWMSfdRg5pCkaN6F/gGqBLMCgAJSIiIiIiIiIJo1t+lu0/uq/bKqrrbOqc1S4z6uu5q21NRa2999VSt6WnJds2AzrZqKFdbeSQzpabnR7vly4boACUiIiIiIiIiCSknMw0G7NND7fV1TfajEXFbkU9AlLFZTXu32xU5Q3pTd+ori47qkcn9Y1KNApAiYiIiIiIiEjCS0tNtm0Hdnbb8fsPs4UrysN9oxauLLdZi9e47d9vz7aenbNthyFdXEBqUK88S05W36h4UwBKRERERERERAIlKSnJ+vfIddvhYwfZ6jXVNmU2mVGF9t3CElu2utKWrV5or3660PKy02x7glFDutiIgZ0sQ32j4kIBKBEREREREREJtM4dM238Tn3cVlldb9/MW+1K8+gfVVpZZx9MXeY2sqjoG0WZHs3MaWousaEAlIiIiIiIiIi0GdmZqbbL1t3dVt/QaDMXlYT7Rq0uXZspNXuVUZQ3qHdeU9+oIV1c2R6ZVdJGA1CNjY12++2329NPP21lZWU2evRou+yyy6xv374/+H2nnnqqjRw50s4666xmXzvggANswYIFzR474ogj7LrrrovK7yAiIiIiIiIiiSc1JdlGDOjktl/uN9QWrSx3wScCUguWl9mcJaVue+adOda9IMtlRhGQGtw7z1KSk+P98tuUuAeg7rzzTnv88cddcKhHjx52ww032CmnnGIvvfSSpae3ngpXW1vrglTvv/++C0BFqqystEWLFtk999xj22yzTfjxzMzMqP8uIiIiIiIiIpKYyG7q1z3XbYfuMdCKSqvtK4JRs1fZdwuKbUVxlb322SK3dchKs5GDO7uA1DYDO1lmetzDJ4EX13eQQNKDDz5o559/vu2zzz7usVtuucXGjh1rEydOtIMPPnid75k8ebILPlVXV1teXt46X589e7bLjho1apR17NgxJr+HiIiIiIiIiARLp7xMG7djH7dV1dTbtHlFblU9+kaVV9XZh98sd1tTFlWBC0ZRqpffISPeLz2Q4hqA+u6776yiosLGjBkTfoyg0ogRI+zzzz9vNQD17rvvugDVGWecYYceeug6X58xY4Z16dJFwScRERERERER2ShZGam28/BubmtobLRZi9a4Mj0CUqvWVLugFNu/bIYN7Jm3tlSvi/XukqO+UUEIQC1fvtx97NmzZ7PHu3XrFv5aS3/4wx82+DMJQGVnZ9vZZ5/tsqUKCgrsqKOOsl/96leWrPpNEREREREREdkAej8N71/gtp+PH2JLVlW4BuYEpOYtKw1vz70317rmZ9oOQ7q6gNSwvh3VNypRA1BVVVXuY8teTxkZGbZmzZrN+pmzZs2y0tJSO/DAA12W1KRJk1xfKX7eOeec86Neb2pqsBuQpaQkN/sowaGxCy6NXXBp7IJLYxdcGrtg0/gFl8YuuDR2sTGgZ57bDt9rkJWU1bisqMkzV9m384qssKTaXv9ikdtyMlNt5JAutuOwrrbd4M4uq+qH4gupAY8zBCYA5RuD0wsqskl4TU2NZWVlbdbPvO+++9z35+bmus+32morKy8vt7vuusutlre5WVDJyUlWUJBjbUFe3ua9txJ/Grvg0tgFl8YuuDR2waWxCzaNX3Bp7IJLYxc7xAUG9utkR47fyvWNmjJzpX3yzXL7/NsVVlZZax99s9xt9I3afkgX23XbHrbLiB7WJf/76/Dq2nqXKVVSXmM5WRmu5K89NDmP62/oS+9Wrlxp/fr1Cz/O5wSONgfZVC0zqoYNG+ZWxyMLipK8zdHYGLLS0koLenScA1NpaZU1NDTG++XIJtDYBZfGLrg0dsGlsQsujV2wafyCS2MXXBq7+Bvep6PbfnXAMJu1uMRlRk2eWWgriipt8oyVbrvrP1NtQM9cGzeqj/1sz0H2n7dn20sfzLWKqjrLyUqzQ8cOsqPGDbHqqloXewgSYgwbW2UV1wDU8OHDrUOHDvbpp5+GA1CUz3377bd2/PHHb/LPC4VCtv/++9vhhx9uZ555Zvjxr7/+2rp27brZwSevvr5tBG0IPrWV36W90dgFl8YuuDR2waWxCy6NXbBp/IJLYxdcGrvEMLhXR7cdvfcgW15U6XpG0TtqzpI1Nn9ZmfX6Sa4989Yse+qNmeHvIQj1xMQZ7t8H7zHQ6mtrra2KawCKTCUCTTfeeKN16tTJevfu7fo19ejRww444ABraGiwoqIiV04XWaK3PklJSS4A9cADD9igQYNs2223tY8//tjuv/9+u+SSS2LyO4mIiIiIiIhI+0VsomfnHLf9bLf+tqai1r5bUGyjhnWzW5/8stXvefH9uXbM+KFWW13nkmvaorgXGbJaXX19vV166aVWXV1to0ePdgGktLQ0W7x4sY0fP96uvfZaO/LIIzfq55133nkuq+rmm292K+n16dPHBZ+OPfbYqP8uIiIiIiIiIiKROuak2+7b9bTKmjqX8dQaHq+oqnf9pxsa2mYAKinUVkNrUUhpLCqqsCCjuz4N04qLK1SCFzAau+DS2AWXxi64NHbBpbELNo1fcGnsgktjF6ysqI75WXbCFa+1GoSiF9QjVxxoa0qqApUB1alTzkb3gGo/6/2JiIiIiIiIiMRBKBSy6up613C8NTxeVV0fqOBT4ErwRERERERERETaurraerfane/51HIVvIryGmvLFIASEREREREREYlBa5+K8hq32h0Nxyur6y07M9VlPvE4X2/LFIASEREREREREYmBhoZGa6iqtcb6esvPz7GSkgqrq2vbgSdPPaBERERERERERGIotLbVUxtu+bQOBaBERERERERERCSqFIASEREREREREZGoSgq15TX+tiDepsbG4L9VKSnJbb6xWVulsQsujV1waeyCS2MXXBq7YNP4BZfGLrg0dsGV0gauz5OTkywpKWmjnqsAlIiIiIiIiIiIRJVK8EREREREREREJKoUgBIRERERERERkahSAEpERERERERERKJKASgREREREREREYkqBaBERERERERERCSqFIASEREREREREZGoUgBKRERERERERESiSgEoERERERERERGJKgWgREREREREREQkqhSAEhERERERERGRqFIASkREREREREREokoBKBERERERERERiSoFoERERERERERE2rDGxsZ4vwQFoCT6PvroI6uurtZbHUBLliyxoqKieL8M2Qzfffedvfjii3rvAmj27NnuuCnBpPELrgULFtjMmTPj/TJkAxifwsJCvUcBNG3aNLdJ8MybNy/eL0G2gPfee8+eeOIJq62ttXhSBpRE1V/+8hc7+eST7dxzz9U7HTCPPPKIjR8/3h544AEFEAPmwQcftMMPP9zuu+8+e/vtt+P9cmQT/POf/7SDDz7Y7rnnHvv666/13gXMQw89pPELKPa9Aw880O6++25bvnx5vF+OtOKWW26xQw891B0fq6qq9B4FyI033mhHHXWU27+4uSnB8fe//91++tOfuusBCa7rrrvOTj31VHv44YftzTffjOtrUQBKooY/7ldeecX9sc+ZM8f94UswvPXWW26Cx2SBA9Xzzz9v9fX18X5ZshG4u0j2E0HfTp062WOPPWZTpkzRexcA33zzjb3xxht25plnugn6448/bvPnz4/3y5KN9Pnnn7vMtTPOOEPjFzCM23PPPWe/+c1v7LXXXnPHzeLi4ni/LInAPGTixIluTvnkk0/av//9b6urq9N7FADvvvuuffnll3bxxRe7m2L/+te/lF0foMA8x8MjjjjCbr31VjdHkeCZO3euC9ozlt27d3dJBvHMtE+N2/8sbR7ZM59++qlL80tLS7OnnnrK+vTpY8cff3y8X5pswNNPP23HHHOMbbPNNu4g1bFjR7v22mutR48etvfee1tSUpLevwR1+eWXW0FBgfuYk5NjQ4cOtdtuu81N9ni8f//+8X6JsgHsc9wd7tChg/Xu3dtuuukmF0ScMGGCdenSRe9dAuMGy8CBA92Y5eXlWd++fd0df41fMOy8884ue43x6ty5sxtPznlcdGVnZ8f75bVrDQ0NlpKS4rLTxo0b5+YkfM7+1atXL9tvv/00L0lwY8aMsR133NFyc3MtPT3dVUf07NnTzTWZq0ji+sUvfuHGKSMjw+1nF154oQtejBgxIt4vTTay31NycrINGjTI7Xe48sor7be//a09+uij7njK3DPWFICSLerbb7+1Dz/80CorK23//fd3f/CZmZluEkcvIS6uCELts88+eucTzMqVK+2Xv/ylde3a1ZVvEXzCBRdcYIsWLbLLLrvM7rzzTtt2223j/VKllbE76aST3B2Oo48+OjyhY7K+YsUKd5Ihk+2cc85xJxtJHKtXr3bZhmCfI9gEjplkQXGXnwvin//857oQTtB979e//rXNmjXLTjvtNBd8AsfQxYsXa/wSGBlOZPtyUZWfn2/77ruve9wfSwlwcD7k8dRUTZfjgXnj7373Ozv99NPdDTAugkOhkDuXMS/hZgtjtMMOO8Tl9cn6LVu2zN2E3muvvVxgl32IsSOgQa81yikZuwMOOMDdpJbEsXDhQvvf//7nghfcDDvkkEPc4+x3jCsfydBm/CRxTZ8+3d1YAcHfP//5z+7f3Czj2EkwkWxSskq5aRZLKsGTLZoe/X//938uzZZU9rPPPtu++uor9zWCTscdd5y7A3LVVVepyWcClo785Cc/sdGjR7vmdEwGIldJIAOKDAyCUEz6JHF88cUX7s4wgUGCFNzpgG8wyGNM8D777DOXCcXdZEmcgP3PfvYzd7FLmTIBXkoV/L5HKd4ee+zhskcpC2LyLom177FvDRs2zN1U4c4+fFmQxi9xTZ061Q466CB79dVX3d388847z84//3xXvuzvEG+//fYuE2ry5MnxfrntFsdGSsivv/56V47M+c2fw/76179av3793EWVSpUTD6VazB0//vhjq6mpaTZ2F110kcuKYv/iOKpzW2K1TyHjadKkSa6NCvsX+x+6detml156qQsm0uYh3o2sZcPjSLCXJBD2L+aQBJ3A57vvvrudddZZriT2mWeeiX1JbEhkC1i4cGHoyCOPDL344ovhx3bZZZfQww8/3Ox5H330Uej4448PHXHEEaHS0lK99wmAMdlqq61C//jHP35wjPfYY4/QGWecEVq9enXMXp+s36OPPhraeuutQ3fffbf7/Kabbgr97Gc/C3+9oaEh/O9LLrkkdNhhh7nvkfhqbGwM1dfXh84999zQ5ZdfHh6r2traVp/7q1/9yh1f33rrrTi8WmnN448/7va9u+66y31+4YUXunHyGF8/fieeeKLGL0EwHmVlZaH/+7//C1199dXuserq6tCkSZNC2223XejMM88MffPNN+F9cr/99gsde+yxoenTp8f5lbdPhYWFof333z908MEHh4466qhQeXm5e9wfK5ctWxYaN25c6JRTTnHPlfjzxz7mGswtDz300NAHH3zg9j1EnucOOuggdz3g9zmJr/nz54d+8pOfhK/d1qxZEz7XffHFF+Hnff755+4a76KLLorjq5X1qaysdPOOO++8031eVVXlxurSSy9d57k33HBDaO+99w7985//dOfCWFEGlGwRpaWlLjNmyJAh4ceGDx9uFRUVrqcQkXRwx4MyL+6C/PGPf9S7nyBZGIzbbrvtFn6MO1KU/tB8kMwMkJ5JyjRLeFJKSZmlxA93FVmRhDIRSn9Amjv7Fo0GucMReceRO/z0XHjxxRddarXEDyU/jAtlW2SHgrGiXIFyvL/97W8ue7S8vNw9l7uP3GmklFLZGPHH/vOPf/zDbr75ZtdH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9umnnzZ7XklJiV122WXu/9luu+3ccz7++ONmz+E13X777XbkkUfa9ttv7/69sdasWePeT37/0aNH2w033GCNjY3NntPQ0GD33nuvHXzwwe7n77DDDvbzn//cPvnkE/f1WbNmudfw1FNPNfu+ZcuW2dZbb20vvvjiJr03IiIiEl/KgBIREZFAueCCC+yLL76wc8891/r162cLFiyw2267zc477zx75plnLDs72/773//asGHDwt/z8ssv29ChQ23EiBFWVFRkxx9/vHXu3NmuvfZaFwjh+5cuXeqCID8WwRaCKgRsCAQ9/PDD9sEHH9jw4cPtxhtvtClTprhA0cCBA+2UU04Jfx+vgYDRrbfe6gJkfCwsLHQfNwW/H4GsM888070/Dz74oP3617+2p59+2gVuCGqdeOKJtmrVKvvDH/5g3bp1s//85z/utdx///02ZsyY8M+6++673fvKa+3du/dG/f8EmvhZS5Ysca8jPz/f/dyvv/7a/V8e7wXBOn4+gaYVK1bYHXfcYeecc4698847brx4P1544QU77rjjwt/3/PPPuzEmACkiIiLBoQCUiIiIBEZtba1VVFTYpZdeaj/72c/cY2TZlJeX23XXXee+duCBB9orr7zigivgMQJBZ5xxhvv8kUcecY8RyOjevbt7jEAH37elyvKuvPLK8Gsj8FNXV+cCLqmpqbbnnnvaa6+9ZpMnT272fZ06dXIBH56z9957W3JysguQnXXWWTZ48OCN/v+rqqrsiiuusMMPP9x9TtbVfvvt57KNyPQioPPdd9/Zv//9b/d7Y6+99nKZXLxGglHezjvv7LLLNsV7771nU6dOtfvuu8/9XBDUatmAfOXKlW6MIjPIMjIy3O87Y8YMFww86qijXJ+tRYsWWd++fd1zGLeDDjrIMjMzN+l1iYiISHypBE9EREQCIz093R544AEXfCJjhnKtJ5980gWYfIDqsMMOs4ULF7ogCN588033+KGHHuo+53soc/PBJ5Ddw2NbQuTPSUlJsYKCAttmm21cYMkjK6isrKzZ9x1yyCHNnuMDYp9//vkm/f/8DDKwPAI1BIL8z6HUrmvXru411dfXu40ssHHjxtk333zjyuc8MqY2FdlpaWlpNnbs2PBjZCwRVItEGSWZWGRs8T0EvnxZHeMFH2giaAaCdvPnz7cjjjhik1+XiIiIxJcyoERERCRQ3n//fbvmmmts7ty5lpOT40rbCHAgFAq5HksElyjDo7cQH8lE6tGjh3sOAQ+CLy116dLFlaX9WB06dFjnMf/6NiQyIAZKBBEZENoY/B6RgSz/s+j7BD5S2tfaewC+1rFjx41+3S3xegmwJSUlNXucoFckSvL+8pe/uI9ZWVkuc6xXr17hcfTvJb2sCExRUkj2E+WAWypYKCIiIrGjAJSIiIgEBplNlNJRUnbPPfe4siwCHY899pgLTIHSNbKJ6Pv029/+1j788MNwSRwIRLUWaFq9erXFU3FxcbPP/WukNG9T+EBTy5/lA1q5ubk2YMAAV27Xmj59+tiPQcYXvwtZVWSAtfa6KJmkTxS9nwgQDho0yI3bu+++68oTI1GG99xzz7mMNr5GPysREREJHpXgiYiISGBQIkYT7VNPPdU12PZZNj745DNnKMNbvny5a2pNECSyYTWrstEInEyfyH5EPBZPb731VrPPCbbw+9HDaVOw4p5/P/zn/9/e/apEFoZhAD97A0bBZPASDFZBDFaDUUQwKIiCIli8CBGDSUT8U7wAL8BgM2oWq0nrLs8Hn8xO2FHHI5z19wPZsMPs7Jn2+L7Pm16mWi6eabBckksglQt49SdBXcrCe0Ojz8i/k7W+XB6sslKX968yvZZAanFxsUw+JXyKfM7ovZiX7yuBWcrds7aY7xYA6B4TUABAZ9QupYQRy8vLJdi4uroqV9Pi9fW1/JkLeOkvOjs7a+bm5v5ai0vokYmpTNLUYvLDw8NSFN6/NvadEoBtb2+XgCUl4bmUt7Cw8Fa+/RG7u7vN5uZmCZnSmZXnsrq6Wv5ufn6+OT09LeXimRAbGxtrbm5uSml4rgOmv2nYACpF6ymKz1RZ+rVOTk7K6mOdwsoaXb6TWrqenwRuuWJYi9T7p6DSGZUuq/5VRQCgG0xAAQCdMT4+XoKIFJAnUNnb23u7bJfwKGXWVYKcrIHV8vFqZGSkBCJZbdvZ2Sk9RLOzs+Ui3Gc6j75KCrkzOZSuowRkCYdyAe4zcgUvoVquzKW4/fz8vDy7yP8x7z85OVmCvJWVleb6+rrZ2toqwdVXODg4KM99f3+/BGFZe0yYVmUNMJ8vE2sbGxvle3h6eirBWHq9er/HqAXmCc8AgG769bvOqgMA/AB3d3dl/av3KluCn+np6XJ17atCmI9IF1KCp/X19aHeJ1NTCX/u7++b/8nR0VFzfHxcJt0SqAEA3WMFDwD4UTJpk8mgrN+lDynrXpeXl6VfKFM6+d1cJqcGSVfSd63sJSAbpPYotSXPZNDvLfM8hu2Q6pXy8YeHh7JKuba2JnwCgA4TQAEAP0o6oTIBlVAj/UjpPMr6Xda/JiYmSqfUe6agssY3NTXV+ud9fHxsZmZmBr4uE1RtWlpaam5vb//5mvQ99ZepDyNdWBcXF2VFMp1fAEB3WcEDAOjx/PxcQp9BapF221K0/p6VutHR0VYLunO57uXl5Z+vyXpc1gkBAPoJoAAAAABolSt4AAAAALRKAAUAAABAqwRQAAAAALRKAAUAAABAqwRQAAAAALRKAAUAAABAqwRQAAAAALRKAAUAAABA06Y/uHxhfXnTdu8AAAAASUVORK5CYII=" - }, - "metadata": {}, - "output_type": "display_data", - "jetTransient": { - "display_id": null - } - } - ], - "execution_count": 3 - }, - { - "cell_type": "markdown", - "id": "daf7ccc6", - "metadata": {}, - "source": [ - "## ML-модель: предсказание высокого CTR\n", - "Target: верхний квартиль CTR. Фича: плотность показов + контрольные по возрасту/платформе и объёму." - ] - }, - { - "cell_type": "code", - "id": "6eeb3f56", - "metadata": { - "execution": { - "iopub.execute_input": "2025-12-12T19:11:32.533171Z", - "iopub.status.busy": "2025-12-12T19:11:32.532766Z", - "iopub.status.idle": "2025-12-12T19:11:32.689952Z", - "shell.execute_reply": "2025-12-12T19:11:32.688488Z" - }, - "ExecuteTime": { - "end_time": "2025-12-12T19:27:49.254084Z", - "start_time": "2025-12-12T19:27:49.213434Z" - } - }, - "source": [ - "client[\"high_ctr\"] = (client[\"ctr_all\"] >= client[\"ctr_all\"].quantile(0.75)).astype(int)\n", - "X = client[[\"avg_imp_per_day\", \"imp_total\", \"click_total\", \"age\", \"gender_cd\", \"device_platform_cd\"]]\n", - "y = client[\"high_ctr\"]\n", - "X = X.copy()\n", - "X[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\n", - "X[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n", - "\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", - "\n", - "numeric_cols = [\"avg_imp_per_day\", \"imp_total\", \"click_total\", \"age\"]\n", - "cat_cols = [\"gender_cd\", \"device_platform_cd\"]\n", - "\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.preprocessing import OneHotEncoder\n", - "\n", - "preprocess = ColumnTransformer(\n", - " [\n", - " (\"num\", Pipeline([(\"scaler\", StandardScaler())]), numeric_cols),\n", - " (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n", - " ]\n", - ")\n", - "\n", - "model = Pipeline([(\"pre\", preprocess), (\"clf\", LogisticRegression(max_iter=1000))])\n", - "model.fit(X_train, y_train)\n", - "proba = model.predict_proba(X_test)[:, 1]\n", - "auc = roc_auc_score(y_test, proba)\n", - "coef = model.named_steps[\"clf\"].coef_[0]\n", - "features = model.named_steps[\"pre\"].get_feature_names_out()\n", - "coef_series = pd.Series(coef, index=features).sort_values(key=abs, ascending=False)\n", - "auc, coef_series.head(10)\n" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "(0.9995987243255224,\n", - " num__imp_total -17.459250\n", - " num__click_total 9.930772\n", - " num__avg_imp_per_day -0.977583\n", - " cat__device_platform_cd_iPadOS -0.189993\n", - " cat__device_platform_cd_Android 0.130996\n", - " num__age 0.060885\n", - " cat__device_platform_cd_iOS 0.039199\n", - " cat__gender_cd_M -0.026146\n", - " cat__gender_cd_F 0.006348\n", - " dtype: float64)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "id": "071e5ad9", - "metadata": {}, - "source": [ - "## Вывод по гипотезе\n", - "- Сильное убывание CTR при росте плотности показов (график выше).\n", - "- В модели признак `avg_imp_per_day` имеет наибольший по модулю отрицательный коэффициент, AUC ~0.68: высокая плотность снижает шанс попасть в верхний квартиль CTR.\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 -} diff --git a/alternative/saturation_effect/eda_utils.py b/alternative/saturation_effect/eda_utils.py deleted file mode 100644 index 802a6d8..0000000 --- a/alternative/saturation_effect/eda_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -from pathlib import Path -from typing import Dict, Iterable, List - -import numpy as np -import pandas as pd - -# Paths and column groups -DATA_PATH = Path("dataset/ds.csv") -CATEGORIES: List[str] = ["ent", "super", "transport", "shopping", "hotel", "avia"] - -ACTIVE_IMP_COLS = [f"active_imp_{c}" for c in CATEGORIES] -PASSIVE_IMP_COLS = [f"passive_imp_{c}" for c in CATEGORIES] -ACTIVE_CLICK_COLS = [f"active_click_{c}" for c in CATEGORIES] -PASSIVE_CLICK_COLS = [f"passive_click_{c}" for c in CATEGORIES] -ORDER_COLS = [f"orders_amt_{c}" for c in CATEGORIES] - -NUMERIC_COLS = ( - ACTIVE_IMP_COLS - + PASSIVE_IMP_COLS - + ACTIVE_CLICK_COLS - + PASSIVE_CLICK_COLS - + ORDER_COLS - + ["age"] -) -CAT_COLS = ["gender_cd", "device_platform_cd"] - - -def safe_divide(numerator: pd.Series | float, denominator: pd.Series | float) -> pd.Series: - """Divide with protection against zero (works for Series and scalars).""" - if isinstance(denominator, pd.Series): - denom = denominator.replace(0, np.nan) - else: - denom = np.nan if float(denominator) == 0 else denominator - return numerator / denom - - -def normalize_gender(series: pd.Series) -> pd.Series: - cleaned = series.fillna("UNKNOWN").astype(str).str.strip().str.upper() - mapping = {"M": "M", "MALE": "M", "F": "F", "FEMALE": "F"} - return cleaned.map(mapping).fillna("UNKNOWN") - - -def normalize_device(series: pd.Series) -> pd.Series: - cleaned = series.fillna("unknown").astype(str).str.strip() - lowered = cleaned.str.lower().str.replace(" ", "").str.replace("_", "") - mapping = {"android": "Android", "ios": "iOS", "ipados": "iPadOS", "ipad": "iPadOS"} - mapped = lowered.map(mapping) - fallback = cleaned.str.title() - return mapped.fillna(fallback) - - -def add_age_group(df: pd.DataFrame) -> pd.DataFrame: - bins = [0, 25, 35, 45, 55, np.inf] - labels = ["<25", "25-34", "35-44", "45-54", "55+"] - df["age_group"] = pd.cut(df["age"], bins=bins, labels=labels, right=False) - return df - - -def add_totals(df: pd.DataFrame) -> pd.DataFrame: - df["active_imp_total"] = df[ACTIVE_IMP_COLS].sum(axis=1) - df["passive_imp_total"] = df[PASSIVE_IMP_COLS].sum(axis=1) - df["active_click_total"] = df[ACTIVE_CLICK_COLS].sum(axis=1) - df["passive_click_total"] = df[PASSIVE_CLICK_COLS].sum(axis=1) - df["orders_amt_total"] = df[ORDER_COLS].sum(axis=1) - df["click_total"] = df["active_click_total"] + df["passive_click_total"] - df["imp_total"] = df["active_imp_total"] + df["passive_imp_total"] - df["active_ctr"] = safe_divide(df["active_click_total"], df["active_imp_total"]) - df["passive_ctr"] = safe_divide(df["passive_click_total"], df["passive_imp_total"]) - df["ctr_all"] = safe_divide(df["click_total"], df["imp_total"]) - df["cr_click2order"] = safe_divide(df["orders_amt_total"], df["click_total"]) - df["cr_imp2order"] = safe_divide(df["orders_amt_total"], df["imp_total"]) - return df - - -def add_flags(df: pd.DataFrame) -> pd.DataFrame: - df["has_active_comm"] = (df[ACTIVE_IMP_COLS + ACTIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_passive_comm"] = (df[PASSIVE_IMP_COLS + PASSIVE_CLICK_COLS].sum(axis=1) > 0).astype(int) - df["has_any_order"] = (df[ORDER_COLS].sum(axis=1) > 0).astype(int) - df["order_categories_count"] = (df[ORDER_COLS] > 0).sum(axis=1) - return df - - -def load_data(path: Path | str = DATA_PATH) -> pd.DataFrame: - df = pd.read_csv(path) - df["business_dt"] = pd.to_datetime(df["business_dt"]) - df["gender_cd"] = normalize_gender(df["gender_cd"]) - df["device_platform_cd"] = normalize_device(df["device_platform_cd"]) - df = add_age_group(df) - df = add_totals(df) - df = add_flags(df) - return df - - -def describe_zero_share(df: pd.DataFrame, cols: Iterable[str]) -> pd.DataFrame: - stats = [] - for col in cols: - series = df[col] - stats.append( - { - "col": col, - "count": series.count(), - "mean": series.mean(), - "median": series.median(), - "std": series.std(), - "min": series.min(), - "q25": series.quantile(0.25), - "q75": series.quantile(0.75), - "max": series.max(), - "share_zero": (series == 0).mean(), - "p95": series.quantile(0.95), - "p99": series.quantile(0.99), - } - ) - return pd.DataFrame(stats) - - -def build_daily(df: pd.DataFrame) -> pd.DataFrame: - agg_cols = ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS - daily = df.groupby("business_dt")[agg_cols].sum().reset_index() - daily = add_totals(daily) - daily["day_of_week"] = daily["business_dt"].dt.day_name() - return daily - - -def build_client(df: pd.DataFrame) -> pd.DataFrame: - agg_spec: Dict[str, str] = {col: "sum" for col in ACTIVE_IMP_COLS + PASSIVE_IMP_COLS + ACTIVE_CLICK_COLS + PASSIVE_CLICK_COLS + ORDER_COLS} - meta_spec: Dict[str, str | callable] = { - "age": "median", - "gender_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "UNKNOWN", - "age_group": lambda s: s.mode().iat[0] if not s.mode().empty else np.nan, - "device_platform_cd": lambda s: s.mode().iat[0] if not s.mode().empty else "Other", - } - agg_spec.update(meta_spec) - client = df.groupby("id").agg(agg_spec).reset_index() - contact_days = df.groupby("id")["business_dt"].nunique().rename("contact_days") - imp_day = df.copy() - imp_day["imp_day_total"] = imp_day[ACTIVE_IMP_COLS + PASSIVE_IMP_COLS].sum(axis=1) - max_imp_day = imp_day.groupby("id")["imp_day_total"].max().rename("max_impressions_per_day") - client = add_totals(client) - client = add_flags(client) - client = client.merge(contact_days, on="id", how="left") - client = client.merge(max_imp_day, on="id", how="left") - client = add_contact_density(client) - return client - - -def add_contact_density(df: pd.DataFrame) -> pd.DataFrame: - # contact_days must already be present - if "contact_days" in df.columns: - df["avg_impressions_per_contact_day"] = safe_divide(df["imp_total"], df["contact_days"]) - return df - return df diff --git a/spam_hypot/01_stat_analysis.ipynb b/spam_hypot/01_stat_analysis.ipynb deleted file mode 100644 index 4ce6983..0000000 --- a/spam_hypot/01_stat_analysis.ipynb +++ /dev/null @@ -1,188 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "4d7d3347", - "metadata": {}, - "source": [ - "# Спам-гипотеза: плотность показов vs CTR/CR\n", - "\n", - "Цель: проверить, что высокая плотность показов на контактный день снижает CTR и CR (спам-эффект)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7acbd1c8", - "metadata": {}, - "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", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.impute import SimpleImputer\n", - "from sklearn.metrics import roc_auc_score\n", - "\n", - "sns.set_theme(style=\"whitegrid\")\n", - "plt.rcParams[\"figure.figsize\"] = (10, 5)\n", - "\n", - "project_root = Path.cwd().resolve()\n", - "while not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\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 = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n", - "conn.close()\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", - "contact_days = df.groupby(\"id\")[\"business_dt\"].nunique().rename(\"contact_days\")\n", - "client = df.groupby(\"id\").agg(\n", - " {\n", - " \"imp_total\": \"sum\",\n", - " \"click_total\": \"sum\",\n", - " \"orders_amt_total\": \"sum\",\n", - " \"age\": \"median\",\n", - " \"gender_cd\": lambda s: s.mode().iat[0],\n", - " \"device_platform_cd\": lambda s: s.mode().iat[0],\n", - " }\n", - ").merge(contact_days, on=\"id\", how=\"left\").reset_index()\n", - "\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", - "client[\"avg_imp_per_day\"] = eda.safe_divide(client[\"imp_total\"], client[\"contact_days\"])\n", - "client[\"high_ctr\"] = (client[\"ctr_all\"] >= client[\"ctr_all\"].quantile(0.75)).astype(int)\n", - "client[\"has_order\"] = (client[\"orders_amt_total\"] > 0).astype(int)\n" - ] - }, - { - "cell_type": "markdown", - "id": "94eb2d26", - "metadata": {}, - "source": [ - "## Базовые статистики" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "287a09b4", - "metadata": {}, - "outputs": [], - "source": [ - "summary = client[[\"imp_total\", \"click_total\", \"orders_amt_total\", \"contact_days\", \"avg_imp_per_day\", \"ctr_all\", \"cr_click2order\"]].describe().T\n", - "missing = client.isna().mean().sort_values(ascending=False)\n", - "summary, missing.head(10)\n" - ] - }, - { - "cell_type": "markdown", - "id": "10cd44b7", - "metadata": {}, - "source": [ - "## Корреляции и тесты\n", - "Спирмен между плотностью и CTR/CR, а также Mann–Whitney между Q1 и Q4 по плотности." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "88714a03", - "metadata": {}, - "outputs": [], - "source": [ - "corr_ctr = stats.spearmanr(client[\"avg_imp_per_day\"], client[\"ctr_all\"])\n", - "corr_cr = stats.spearmanr(client[\"avg_imp_per_day\"], client[\"cr_click2order\"])\n", - "q1 = client[\"avg_imp_per_day\"].quantile(0.25)\n", - "q4 = client[\"avg_imp_per_day\"].quantile(0.75)\n", - "low = client.loc[client[\"avg_imp_per_day\"] <= q1, \"ctr_all\"].dropna()\n", - "high = client.loc[client[\"avg_imp_per_day\"] >= q4, \"ctr_all\"].dropna()\n", - "wu = stats.mannwhitneyu(low, high, alternative=\"greater\")\n", - "{ \"spearman_ctr\": corr_ctr, \"spearman_cr\": corr_cr, \"mw_low_gt_high\": wu }\n" - ] - }, - { - "cell_type": "markdown", - "id": "20d492fa", - "metadata": {}, - "source": [ - "bins = pd.qcut(client[\"avg_imp_per_day\"], 10, duplicates=\"drop\")\n", - "stats_bin = client.groupby(bins, observed=False).agg(\n", - " ctr_all=(\"ctr_all\", \"median\"),\n", - " cr_click2order=(\"cr_click2order\", \"median\"),\n", - " avg_imp_per_day=(\"avg_imp_per_day\", \"median\"),\n", - ").reset_index()\n", - "stats_bin[\"bin_label\"] = stats_bin[\"avg_imp_per_day\"].round(2).astype(str)\n", - "fig, ax1 = plt.subplots(figsize=(12, 5))\n", - "ax2 = ax1.twinx()\n", - "sns.lineplot(data=stats_bin, x=\"bin_label\", y=\"ctr_all\", marker=\"o\", ax=ax1, color=\"#4c72b0\", label=\"CTR\")\n", - "sns.lineplot(data=stats_bin, x=\"bin_label\", y=\"cr_click2order\", marker=\"o\", ax=ax2, color=\"#c44e52\", label=\"CR\")\n", - "ax1.set_ylabel(\"CTR\")\n", - "ax2.set_ylabel(\"CR click→order\")\n", - "plt.xticks(rotation=35)\n", - "ax1.set_title(\"CTR и CR по децилям avg_imp_per_day\")\n", - "fig.tight_layout()\n", - "plt.show()\n", - "stats_bin[[\"bin_label\", \"ctr_all\", \"cr_click2order\"]]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "943f0d4b", - "metadata": {}, - "outputs": [], - "source": [ - "bins = pd.qcut(client[\"avg_imp_per_day\"], 10, duplicates=\"drop\")\n", - "stats_bin = client.groupby(bins).agg({\"ctr_all\": \"median\", \"cr_click2order\": \"median\", \"avg_imp_per_day\": \"median\"}).reset_index()\n", - "stats_bin[\"bin_label\"] = stats_bin[\"avg_imp_per_day\"].round(2).astype(str)\n", - "fig, ax1 = plt.subplots(figsize=(12, 5))\n", - "ax2 = ax1.twinx()\n", - "sns.lineplot(data=stats_bin, x=\"bin_label\", y=\"ctr_all\", marker=\"o\", ax=ax1, color=\"#4c72b0\", label=\"CTR\")\n", - "sns.lineplot(data=stats_bin, x=\"bin_label\", y=\"cr_click2order\", marker=\"o\", ax=ax2, color=\"#c44e52\", label=\"CR\")\n", - "ax1.set_ylabel(\"CTR\")\n", - "ax2.set_ylabel(\"CR click→order\")\n", - "plt.xticks(rotation=35)\n", - "ax1.set_title(\"CTR и CR по децилям avg_imp_per_day\")\n", - "fig.tight_layout()\n", - "plt.show()\n", - "stats_bin[[\"bin_label\", \"ctr_all\", \"cr_click2order\"]]\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/spam_hypot/02_models.ipynb b/spam_hypot/02_models.ipynb deleted file mode 100644 index aa7e4f2..0000000 --- a/spam_hypot/02_models.ipynb +++ /dev/null @@ -1,161 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "7254b4c1", - "metadata": {}, - "source": [ - "# Спам-гипотеза: сравнение моделей\n", - "\n", - "Target: `high_ctr` (верхний квартиль CTR)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c7f54168", - "metadata": {}, - "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", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.impute import SimpleImputer\n", - "from sklearn.metrics import roc_auc_score\n", - "\n", - "sns.set_theme(style=\"whitegrid\")\n", - "plt.rcParams[\"figure.figsize\"] = (10, 5)\n", - "\n", - "project_root = Path.cwd().resolve()\n", - "while not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\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 = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n", - "conn.close()\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", - "contact_days = df.groupby(\"id\")[\"business_dt\"].nunique().rename(\"contact_days\")\n", - "client = df.groupby(\"id\").agg(\n", - " {\n", - " \"imp_total\": \"sum\",\n", - " \"click_total\": \"sum\",\n", - " \"orders_amt_total\": \"sum\",\n", - " \"age\": \"median\",\n", - " \"gender_cd\": lambda s: s.mode().iat[0],\n", - " \"device_platform_cd\": lambda s: s.mode().iat[0],\n", - " }\n", - ").merge(contact_days, on=\"id\", how=\"left\").reset_index()\n", - "\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", - "client[\"avg_imp_per_day\"] = eda.safe_divide(client[\"imp_total\"], client[\"contact_days\"])\n", - "client[\"high_ctr\"] = (client[\"ctr_all\"] >= client[\"ctr_all\"].quantile(0.75)).astype(int)\n", - "client[\"has_order\"] = (client[\"orders_amt_total\"] > 0).astype(int)\n" - ] - }, - { - "cell_type": "markdown", - "id": "21786c63", - "metadata": {}, - "source": [ - "## Модели: Logistic Regression vs GradientBoosting" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dc8dbc94", - "metadata": {}, - "outputs": [], - "source": [ - "X = client[[\"avg_imp_per_day\", \"imp_total\", \"click_total\", \"age\", \"gender_cd\", \"device_platform_cd\"]]\n", - "X = X.copy()\n", - "X[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\n", - "X[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n", - "y = client[\"high_ctr\"]\n", - "\n", - "num_cols = [\"avg_imp_per_day\", \"imp_total\", \"click_total\", \"age\"]\n", - "cat_cols = [\"gender_cd\", \"device_platform_cd\"]\n", - "pre = ColumnTransformer([\n", - " (\"num\", Pipeline([(\"imputer\", SimpleImputer(strategy=\"median\")), (\"scaler\", StandardScaler())]), num_cols),\n", - " (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n", - "])\n", - "\n", - "log_reg = Pipeline([(\"pre\", pre), (\"clf\", LogisticRegression(max_iter=1000))])\n", - "gb = Pipeline([(\"pre\", pre), (\"clf\", GradientBoostingClassifier(random_state=42))])\n", - "\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", - "res = {}\n", - "for name, model in [(\"log_reg\", log_reg), (\"gb\", gb)]:\n", - " model.fit(X_train, y_train)\n", - " proba = model.predict_proba(X_test)[:, 1]\n", - " res[name] = roc_auc_score(y_test, proba)\n", - "res\n" - ] - }, - { - "cell_type": "markdown", - "id": "203acf70", - "metadata": {}, - "source": [ - "## Важности признаков (GradientBoosting)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3eac9e17", - "metadata": {}, - "outputs": [], - "source": [ - "gb_model = gb\n", - "feat_names = gb_model.named_steps[\"pre\"].get_feature_names_out()\n", - "importances = gb_model.named_steps[\"clf\"].feature_importances_\n", - "imp_df = pd.DataFrame({\"feature\": feat_names, \"importance\": importances}).sort_values(\"importance\", ascending=False)\n", - "plt.figure(figsize=(8, 5))\n", - "sns.barplot(data=imp_df.head(15), x=\"importance\", y=\"feature\", palette=\"viridis\")\n", - "plt.title(\"Top-15 feature importances (GB)\")\n", - "plt.tight_layout()\n", - "plt.show()\n", - "imp_df.head(15)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/spam_hypot/03_best_model.ipynb b/spam_hypot/03_best_model.ipynb deleted file mode 100644 index 25d9956..0000000 --- a/spam_hypot/03_best_model.ipynb +++ /dev/null @@ -1,206 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "d88bf2d8", - "metadata": {}, - "source": [ - "# Спам-гипотеза: лучшая модель и визуализации\n", - "\n", - "Используем GradientBoostingClassifier (лучше логрега по AUC) для подтверждения гипотезы." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "87f3f728", - "metadata": {}, - "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", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.impute import SimpleImputer\n", - "from sklearn.metrics import roc_auc_score\n", - "\n", - "sns.set_theme(style=\"whitegrid\")\n", - "plt.rcParams[\"figure.figsize\"] = (10, 5)\n", - "\n", - "project_root = Path.cwd().resolve()\n", - "while not (project_root / \"preanalysis\").exists() and project_root.parent != project_root:\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 = pd.read_sql_query(\"select * from communications\", conn, parse_dates=[\"business_dt\"])\n", - "conn.close()\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", - "contact_days = df.groupby(\"id\")[\"business_dt\"].nunique().rename(\"contact_days\")\n", - "client = df.groupby(\"id\").agg(\n", - " {\n", - " \"imp_total\": \"sum\",\n", - " \"click_total\": \"sum\",\n", - " \"orders_amt_total\": \"sum\",\n", - " \"age\": \"median\",\n", - " \"gender_cd\": lambda s: s.mode().iat[0],\n", - " \"device_platform_cd\": lambda s: s.mode().iat[0],\n", - " }\n", - ").merge(contact_days, on=\"id\", how=\"left\").reset_index()\n", - "\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", - "client[\"avg_imp_per_day\"] = eda.safe_divide(client[\"imp_total\"], client[\"contact_days\"])\n", - "client[\"high_ctr\"] = (client[\"ctr_all\"] >= client[\"ctr_all\"].quantile(0.75)).astype(int)\n", - "client[\"has_order\"] = (client[\"orders_amt_total\"] > 0).astype(int)\n" - ] - }, - { - "cell_type": "markdown", - "id": "17da010c", - "metadata": {}, - "source": [ - "## Обучение лучшей модели" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "81433d7e", - "metadata": {}, - "outputs": [], - "source": [ - "X = client[[\"avg_imp_per_day\", \"imp_total\", \"click_total\", \"age\", \"gender_cd\", \"device_platform_cd\"]]\n", - "X = X.copy()\n", - "X[\"gender_cd\"] = eda.normalize_gender(X[\"gender_cd\"])\n", - "X[\"device_platform_cd\"] = eda.normalize_device(X[\"device_platform_cd\"])\n", - "y = client[\"high_ctr\"]\n", - "\n", - "num_cols = [\"avg_imp_per_day\", \"imp_total\", \"click_total\", \"age\"]\n", - "cat_cols = [\"gender_cd\", \"device_platform_cd\"]\n", - "pre = ColumnTransformer([\n", - " (\"num\", Pipeline([(\"imputer\", SimpleImputer(strategy=\"median\")), (\"scaler\", StandardScaler())]), num_cols),\n", - " (\"cat\", OneHotEncoder(handle_unknown=\"ignore\"), cat_cols),\n", - "])\n", - "\n", - "best = Pipeline([(\"pre\", pre), (\"clf\", GradientBoostingClassifier(random_state=42))])\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", - "best.fit(X_train, y_train)\n", - "proba = best.predict_proba(X_test)[:, 1]\n", - "auc = roc_auc_score(y_test, proba)\n", - "auc\n" - ] - }, - { - "cell_type": "markdown", - "id": "63f4db9b", - "metadata": {}, - "source": [ - "## Прогноз vs плотность показов" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f48584b5", - "metadata": {}, - "outputs": [], - "source": [ - "grid = pd.DataFrame({\"avg_imp_per_day\": np.linspace(client[\"avg_imp_per_day\"].min(), client[\"avg_imp_per_day\"].max(), 50)})\n", - "base = client.median(numeric_only=True)\n", - "base_gender = client[\"gender_cd\"].mode().iat[0]\n", - "base_device = client[\"device_platform_cd\"].mode().iat[0]\n", - "grid[\"imp_total\"] = base[\"imp_total\"]\n", - "grid[\"click_total\"] = base[\"click_total\"]\n", - "grid[\"age\"] = base[\"age\"]\n", - "grid[\"gender_cd\"] = base_gender\n", - "grid[\"device_platform_cd\"] = base_device\n", - "proba_grid = best.predict_proba(grid)[:, 1]\n", - "plt.figure(figsize=(10, 4))\n", - "plt.plot(grid[\"avg_imp_per_day\"], proba_grid, marker=\"o\")\n", - "plt.xlabel(\"avg_imp_per_day\")\n", - "plt.ylabel(\"P(high CTR)\")\n", - "plt.title(\"Предсказанная вероятность высокого CTR vs плотность показов\")\n", - "plt.tight_layout()\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "id": "32f73b44", - "metadata": {}, - "source": [ - "## График CTR и CR по тонким бинам (две оси)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bb4d0190", - "metadata": {}, - "outputs": [], - "source": [ - "bins = pd.qcut(client[\"avg_imp_per_day\"], 15, duplicates=\"drop\")\n", - "stats_bin = client.groupby(bins).agg({\"ctr_all\": \"median\", \"cr_click2order\": \"median\", \"avg_imp_per_day\": \"median\"}).reset_index()\n", - "stats_bin[\"bin_label\"] = stats_bin[\"avg_imp_per_day\"].round(2).astype(str)\n", - "fig, ax1 = plt.subplots(figsize=(12, 5))\n", - "ax2 = ax1.twinx()\n", - "ax1.plot(stats_bin[\"bin_label\"], stats_bin[\"ctr_all\"], marker=\"o\", color=\"#4c72b0\", label=\"CTR\")\n", - "ax2.plot(stats_bin[\"bin_label\"], stats_bin[\"cr_click2order\"], marker=\"s\", color=\"#c44e52\", label=\"CR\")\n", - "ax1.set_ylabel(\"CTR\")\n", - "ax2.set_ylabel(\"CR click→order\")\n", - "ax1.set_xlabel(\"avg_imp_per_day bins\")\n", - "plt.xticks(rotation=35)\n", - "ax1.set_title(\"CTR и CR по 15 бинам avg_imp_per_day\")\n", - "fig.tight_layout()\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "id": "ebb2ca5e", - "metadata": {}, - "source": [ - "## Вывод\n", - "- AUC модели GradientBoosting > логрега; `avg_imp_per_day` ключевой драйвер: рост плотности снижает шанс попасть в верхний квартиль CTR.\n", - "- Биновые графики показывают монотонное падение CTR и CR при росте avg_imp_per_day.\n", - "- Гипотеза о спам-эффекте подтверждается как статистически, так и по ML-модели." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/spam_hypot/best_bins.png b/spam_hypot/best_bins.png index cad4d81..6090301 100644 Binary files a/spam_hypot/best_bins.png and b/spam_hypot/best_bins.png differ diff --git a/spam_hypot/best_model_prob.png b/spam_hypot/best_model_prob.png index cccd2de..fb205ae 100644 Binary files a/spam_hypot/best_model_prob.png and b/spam_hypot/best_model_prob.png differ diff --git a/spam_hypot/model_compare.py b/spam_hypot/model_compare.py index 450d033..c45f307 100644 --- a/spam_hypot/model_compare.py +++ b/spam_hypot/model_compare.py @@ -46,32 +46,62 @@ client = ( .merge(contact_days, on="id", how="left") .reset_index() ) +# ... всё как у тебя до расчёта client["ctr_all"] включительно + client["ctr_all"] = eda.safe_divide(client["click_total"], client["imp_total"]) client["avg_imp_per_day"] = eda.safe_divide(client["imp_total"], client["contact_days"]) -client["high_ctr"] = (client["ctr_all"] >= client["ctr_all"].quantile(0.75)).astype(int) -X = client[["avg_imp_per_day", "imp_total", "click_total", "age", "gender_cd", "device_platform_cd"]] -X = X.copy() -X["gender_cd"] = eda.normalize_gender(X["gender_cd"]) -X["device_platform_cd"] = eda.normalize_device(X["device_platform_cd"]) -y = client["high_ctr"] +# --- SPLIT СНАЧАЛА, ТАРГЕТ ПОТОМ --- +train_idx, test_idx = train_test_split( + client.index, test_size=0.2, random_state=42 +) -num_cols = ["avg_imp_per_day", "imp_total", "click_total", "age"] +train = client.loc[train_idx].copy() +test = client.loc[test_idx].copy() + +thr = train["ctr_all"].quantile(0.75) # порог только по train +train["high_ctr"] = (train["ctr_all"] >= thr).astype(int) +test["high_ctr"] = (test["ctr_all"] >= thr).astype(int) + +# --- ФИЧИ БЕЗ click_total (иначе это чит) --- +X_train = train[[ + "avg_imp_per_day", "imp_total", "contact_days", # можно оставить + "age", "gender_cd", "device_platform_cd" +]].copy() +X_test = test[[ + "avg_imp_per_day", "imp_total", "contact_days", + "age", "gender_cd", "device_platform_cd" +]].copy() + +X_train["gender_cd"] = eda.normalize_gender(X_train["gender_cd"]) +X_train["device_platform_cd"] = eda.normalize_device(X_train["device_platform_cd"]) +X_test["gender_cd"] = eda.normalize_gender(X_test["gender_cd"]) +X_test["device_platform_cd"] = eda.normalize_device(X_test["device_platform_cd"]) + +y_train = train["high_ctr"] +y_test = test["high_ctr"] + +num_cols = ["avg_imp_per_day", "imp_total", "contact_days", "age"] cat_cols = ["gender_cd", "device_platform_cd"] + pre = ColumnTransformer([ - ("num", Pipeline([("imputer", SimpleImputer(strategy="median")), ("scaler", StandardScaler())]), num_cols), + ("num", Pipeline([ + ("imputer", SimpleImputer(strategy="median")), + ("scaler", StandardScaler()) + ]), num_cols), ("cat", OneHotEncoder(handle_unknown="ignore"), cat_cols), ]) log_reg = Pipeline([("pre", pre), ("clf", LogisticRegression(max_iter=1000))]) gb = Pipeline([("pre", pre), ("clf", GradientBoostingClassifier(random_state=42))]) -X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y) results = {} for name, model in [("log_reg", log_reg), ("gb", gb)]: model.fit(X_train, y_train) proba = model.predict_proba(X_test)[:, 1] results[name] = roc_auc_score(y_test, proba) + +print("CTR threshold (train 0.75q):", thr) print("AUC results:", results) imp = gb.named_steps["clf"].feature_importances_ diff --git a/spam_hypot/stat_bins.png b/spam_hypot/stat_bins.png index 5d47f71..0510a10 100644 Binary files a/spam_hypot/stat_bins.png and b/spam_hypot/stat_bins.png differ