From a3d17db28a2fb97afe098782f92243a01fa51f40 Mon Sep 17 00:00:00 2001 From: Anna Eremina <127204320+annaeremina96@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:41:01 +0300 Subject: [PATCH] Add files via upload --- product_analytics_rfm_analysis.ipynb | 1015 ++++++++++++++++++++++++++ 1 file changed, 1015 insertions(+) create mode 100644 product_analytics_rfm_analysis.ipynb diff --git a/product_analytics_rfm_analysis.ipynb b/product_analytics_rfm_analysis.ipynb new file mode 100644 index 0000000..b9bdfb4 --- /dev/null +++ b/product_analytics_rfm_analysis.ipynb @@ -0,0 +1,1015 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Продуктовая аналитика: Методы сегментации клиентов и целевой аудитории\n", + "\n", + "Обсудим, зачем необходимо сегментировать целевую аудиторию. Поговорим об особенностях сегментации в B2B и B2C продуктах. Познакомимся с популярными критериями выделения сегментов и методами сегментации: описательными (модель 5W, Khramatrix и др.) и аналитическими (RFM, когорты, k-means и др.)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Проект. RFM анализ\n", + "\n", + "**Скачайте датасет и проведите RFM анализ. В каждом подсегменте поделите пользователей на 4 класса. Отсчитывайте количество дней, прошедших с момента последней покупки, с максимальной даты покупки в датасете.**\n", + "\n", + "- Какое максимальное кол-во покупок было совершено одним пользователем?\n", + "- Какая верхняя граница у суммы покупок у пользователей с классом 4 в подсегменте М? (Другими словами: пользователи, у которых сумма покупок от 0 до Х попадают в 4 класс в подсегменте М)\n", + "- Какая нижняя граница у количества покупок у пользователей с классом 1 в подсегменте F?\n", + "- Какая верхняя граница у количества покупок у пользователей с классом 2 в подсегменте R?\n", + "- Сколько пользователей попало в сегмент 111?\n", + "- Сколько пользователей попало в сегмент 311?\n", + "- В каком RFM-сегменте самое большое кол-во пользователей?\n", + "- В каком RFM-сегменте самое маленькое кол-во пользователей?\n", + "- Какое количество пользователей попало в самый малочисленный сегмент?" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import numpy as np\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/tljh/user/lib/python3.7/site-packages/IPython/core/interactiveshell.py:3063: DtypeWarning: Columns (1) have mixed types.Specify dtype option on import or set low_memory=False.\n", + " interactivity=interactivity, compiler=compiler, result=result)\n" + ] + } + ], + "source": [ + "project = pd.read_csv('/mnt/HC_Volume_18315164/home-jupyter/jupyter-a-eremina/product_analytics/RFM_ht_data.csv', sep = ',')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": true + }, + "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", + "
InvoiceNoCustomerCodeInvoiceDateAmount
0C0011810010001190672902020-09-011716.00
1C0011810010017132339332020-09-011489.74
2C0011810010020990579682020-09-01151.47
3C0011810010021800072762020-09-01146.72
4C0011810010024131640762020-09-01104.00
\n", + "
" + ], + "text/plain": [ + " InvoiceNo CustomerCode InvoiceDate Amount\n", + "0 C0011810010001 19067290 2020-09-01 1716.00\n", + "1 C0011810010017 13233933 2020-09-01 1489.74\n", + "2 C0011810010020 99057968 2020-09-01 151.47\n", + "3 C0011810010021 80007276 2020-09-01 146.72\n", + "4 C0011810010024 13164076 2020-09-01 104.00" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(332730, 4)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Приводим данные в нужный формат:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "project['InvoiceDate']=pd.to_datetime(project['InvoiceDate'])\n", + "project['CustomerCode']=project['CustomerCode'].astype(str)\n", + "project['InvoiceNo']=project['InvoiceNo'].astype(str)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "last_date=project['InvoiceDate'].max()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "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", + "
CustomerCodesize
8938819057820204
4459413215452113
1034713032521106
970771908088099
1199519900306190
.........
58910132728611
58911132728711
58913132728751
58914132728781
61866140007781
\n", + "

123733 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " CustomerCode size\n", + "89388 19057820 204\n", + "44594 13215452 113\n", + "10347 13032521 106\n", + "97077 19080880 99\n", + "119951 99003061 90\n", + "... ... ...\n", + "58910 13272861 1\n", + "58911 13272871 1\n", + "58913 13272875 1\n", + "58914 13272878 1\n", + "61866 14000778 1\n", + "\n", + "[123733 rows x 2 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.groupby('CustomerCode', as_index=False).size().sort_values('size', ascending=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "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", + "
CustomerCoderecencyfrequencymonetary_value
0022130191911609.20
1022130422239685.48
202213071291415.00
302213088231305.00
4022130922511412.88
...............
12372899099927101961.10
12372999099936011521.78
12373099099959821444.56
123731990999631913018.91
12373299099972024577.37
\n", + "

123733 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " CustomerCode recency frequency monetary_value\n", + "0 02213019 19 1 1609.20\n", + "1 02213042 22 3 9685.48\n", + "2 02213071 29 1 415.00\n", + "3 02213088 23 1 305.00\n", + "4 02213092 25 1 1412.88\n", + "... ... ... ... ...\n", + "123728 99099927 10 1 961.10\n", + "123729 99099936 0 1 1521.78\n", + "123730 99099959 8 2 1444.56\n", + "123731 99099963 19 1 3018.91\n", + "123732 99099972 0 2 4577.37\n", + "\n", + "[123733 rows x 4 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Создаём RFM-таблицу\n", + "\n", + "rfm_table=project.groupby('CustomerCode',as_index=False).agg({'InvoiceDate':lambda x: (last_date-x.max()).days,\n", + " 'InvoiceNo':lambda x:len(x),\n", + " 'Amount':lambda x:x.sum()})\n", + "\n", + "\n", + "rfm_table['InvoiceDate'] = rfm_table['InvoiceDate'].astype(int)\n", + "\n", + "\n", + "rfm_table=rfm_table.rename(columns={'InvoiceDate':'recency',\n", + " 'InvoiceNo':'frequency',\n", + " 'Amount':'monetary_value'})\n", + "\n", + "rfm_table" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "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", + "
recencyfrequencymonetary_value
0.252.01.0765.00
0.508.02.01834.48
0.7516.03.04008.84
\n", + "
" + ], + "text/plain": [ + " recency frequency monetary_value\n", + "0.25 2.0 1.0 765.00\n", + "0.50 8.0 2.0 1834.48\n", + "0.75 16.0 3.0 4008.84" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Рассчитаем квантили\n", + "\n", + "quantiles=rfm_table.quantile(q=(0.25,0.5,0.75))\n", + "quantiles" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# Разобьём пользователей на классы\n", + "\n", + "def Rclass(value, parameter_name, quantiles_table):\n", + " if value <= quantiles_table[parameter_name][0.25]:\n", + " return 1\n", + " elif value <= quantiles_table[parameter_name][0.5]:\n", + " return 2\n", + " elif value <= quantiles_table[parameter_name][0.75]:\n", + " return 3\n", + " else:\n", + " return 4\n", + " \n", + "def FMclass(value, parameter_name, quantiles_table):\n", + " if value <= quantiles_table[parameter_name][0.25]:\n", + " return 4\n", + " elif value <= quantiles_table[parameter_name][0.5]:\n", + " return 3\n", + " elif value <= quantiles_table[parameter_name][0.75]:\n", + " return 2\n", + " else:\n", + " return 1" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "rfm_segmentation=rfm_table" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "rfm_segmentation['R_quantile']=rfm_segmentation['recency'].apply(Rclass,args=('recency', quantiles))\n", + "rfm_segmentation['F_quantile']=rfm_segmentation['frequency'].apply(FMclass,args=('frequency', quantiles))\n", + "rfm_segmentation['M_quantile']=rfm_segmentation['monetary_value'].apply(FMclass,args=('monetary_value', quantiles))\n", + "rfm_segmentation['RFM_class']=rfm_segmentation['R_quantile'].map(str)\\\n", + " +rfm_segmentation['F_quantile'].map(str)\\\n", + " +rfm_segmentation['M_quantile'].map(str)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "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", + "
CustomerCoderecencyfrequencymonetary_valueR_quantileF_quantileM_quantileRFM_class
0022130191911609.20443443
1022130422239685.48421421
202213071291415.00444444
302213088231305.00444444
4022130922511412.88443443
\n", + "
" + ], + "text/plain": [ + " CustomerCode recency frequency monetary_value R_quantile F_quantile \\\n", + "0 02213019 19 1 1609.20 4 4 \n", + "1 02213042 22 3 9685.48 4 2 \n", + "2 02213071 29 1 415.00 4 4 \n", + "3 02213088 23 1 305.00 4 4 \n", + "4 02213092 25 1 1412.88 4 4 \n", + "\n", + " M_quantile RFM_class \n", + "0 3 443 \n", + "1 1 421 \n", + "2 4 444 \n", + "3 4 444 \n", + "4 3 443 " + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Какое максимальное кол-во покупок было совершено одним пользователем?" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "204" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.frequency.max()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Какая верхняя граница у суммы покупок у пользователей с классом 4 в подсегменте М? (Другими словами: пользователи, у которых сумма покупок от 0 до Х попадают в 4 класс в подсегменте М)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "765.0" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.query('M_quantile == 4').monetary_value.max()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Какая нижняя граница у количества покупок у пользователей с классом 1 в подсегменте F?" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.query('F_quantile == 1').frequency.min()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Какое максимальное количество дней может пройти с момента последней покупки для того, чтобы пользователь попал в класс 2 в подсегменте R?" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.query('R_quantile == 2').recency.max()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Сколько пользователей попало в сегмент 111?" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "9705" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.query('RFM_class == \"111\"').shape[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Сколько пользователей попало в сегмент 311?" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1609" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.query('RFM_class == \"311\"').shape[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В каком RFM-сегменте самое большое кол-во пользователей?" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'444'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.groupby('RFM_class').size().idxmax()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "В каком RFM-сегменте самое маленькое кол-во пользователей?" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'414'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.groupby('RFM_class').size().idxmin()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Какое количество пользователей попало в самый малочисленный сегмент?" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rfm_segmentation.groupby('RFM_class').size().min()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# heatmap\n", + "\n", + "rfm_viz = rfm_segmentation.pivot_table(\n", + " index='R_quantile', \n", + " columns='F_quantile', \n", + " values='monetary_value', \n", + " aggfunc=np.median).applymap(int)\n", + "sns.heatmap(rfm_viz, cmap=\"YlGnBu\", annot=True, fmt=\".0f\", linewidths=4.15, annot_kws={\"size\": 10},yticklabels=4);" + ] + } + ], + "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.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}