Spaces:
Runtime error
Runtime error
HardWorkingStation
commited on
Commit
•
fccbfb8
1
Parent(s):
3fd6b1d
Initial commit
Browse files- src/tools.py +120 -16
- src/web_app.py +63 -8
src/tools.py
CHANGED
@@ -2,29 +2,28 @@ from typing import Any
|
|
2 |
|
3 |
import pandas as pd
|
4 |
from sklearn.model_selection import train_test_split
|
5 |
-
from sklift.datasets import
|
6 |
from catboost import CatBoostClassifier
|
7 |
import sklearn
|
8 |
import streamlit as st
|
|
|
|
|
9 |
|
10 |
|
11 |
@st.experimental_memo
|
12 |
-
def get_data() ->
|
13 |
-
|
14 |
-
treat_dict = {
|
15 |
-
'test': 1,
|
16 |
-
'control': 0
|
17 |
-
}
|
18 |
# получаем датасет
|
19 |
-
dataset =
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
28 |
|
29 |
|
30 |
@st.experimental_memo
|
@@ -41,3 +40,108 @@ def data_split(data, treatment, target) -> tuple[Any, Any, Any, Any, Any, Any]:
|
|
41 |
random_state=42
|
42 |
)
|
43 |
return X_train, X_val, trmnt_train, trmnt_val, y_train, y_val
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
import pandas as pd
|
4 |
from sklearn.model_selection import train_test_split
|
5 |
+
from sklift.datasets import fetch_hillstrom
|
6 |
from catboost import CatBoostClassifier
|
7 |
import sklearn
|
8 |
import streamlit as st
|
9 |
+
import plotly.express as px
|
10 |
+
import plotly.graph_objects as go
|
11 |
|
12 |
|
13 |
@st.experimental_memo
|
14 |
+
def get_data() -> tuple[Any, Any, Any]:
|
|
|
|
|
|
|
|
|
|
|
15 |
# получаем датасет
|
16 |
+
dataset = fetch_hillstrom(target_col='visit')
|
17 |
+
dataset, target, treatment = dataset['data'], dataset['target'], dataset['treatment']
|
18 |
+
# выбираем два сегмента
|
19 |
+
dataset = dataset[treatment != 'Mens E-Mail']
|
20 |
+
target = target[treatment != 'Mens E-Mail']
|
21 |
+
treatment = treatment[treatment != 'Mens E-Mail'].map({
|
22 |
+
'Womens E-Mail': 1,
|
23 |
+
'No E-Mail': 0
|
24 |
+
})
|
25 |
+
|
26 |
+
return dataset, target, treatment
|
27 |
|
28 |
|
29 |
@st.experimental_memo
|
|
|
40 |
random_state=42
|
41 |
)
|
42 |
return X_train, X_val, trmnt_train, trmnt_val, y_train, y_val
|
43 |
+
|
44 |
+
|
45 |
+
def get_newbie_plot(data):
|
46 |
+
fig = px.histogram(
|
47 |
+
data['newbie'],
|
48 |
+
color=data['newbie'],
|
49 |
+
title='Распределение клиентов по флагу Newbie'
|
50 |
+
)
|
51 |
+
|
52 |
+
fig.update_xaxes(
|
53 |
+
title='',
|
54 |
+
ticktext=['"Старые" клиенты', 'Новые клиенты'],
|
55 |
+
tickvals=[0, 1]
|
56 |
+
)
|
57 |
+
|
58 |
+
fig.update_yaxes(
|
59 |
+
title='Количество'
|
60 |
+
)
|
61 |
+
|
62 |
+
fig.update_layout(
|
63 |
+
showlegend=False,
|
64 |
+
bargap=0.3
|
65 |
+
)
|
66 |
+
|
67 |
+
fig.update_traces(hovertemplate="Количество клиентов: %{y}")
|
68 |
+
|
69 |
+
return fig
|
70 |
+
|
71 |
+
|
72 |
+
def get_zipcode_plot(data):
|
73 |
+
fig = px.histogram(
|
74 |
+
data['zip_code'],
|
75 |
+
color=data['zip_code'],
|
76 |
+
title='Распределение клиентов по флагу zip_code'
|
77 |
+
)
|
78 |
+
|
79 |
+
fig.update_xaxes(
|
80 |
+
title='',
|
81 |
+
categoryorder='total descending'
|
82 |
+
)
|
83 |
+
|
84 |
+
fig.update_yaxes(
|
85 |
+
title='Количество'
|
86 |
+
)
|
87 |
+
|
88 |
+
fig.update_layout(
|
89 |
+
showlegend=False,
|
90 |
+
bargap=0.3
|
91 |
+
)
|
92 |
+
|
93 |
+
fig.update_traces(hovertemplate="Количество клиентов: %{y}")
|
94 |
+
|
95 |
+
return fig
|
96 |
+
|
97 |
+
|
98 |
+
def get_channel_plot(data):
|
99 |
+
fig = px.histogram(
|
100 |
+
data['channel'],
|
101 |
+
color=data['channel'],
|
102 |
+
title='Распределение клиентов по флагу zip_code'
|
103 |
+
)
|
104 |
+
|
105 |
+
fig.update_xaxes(
|
106 |
+
title='',
|
107 |
+
categoryorder='total descending'
|
108 |
+
)
|
109 |
+
|
110 |
+
fig.update_yaxes(
|
111 |
+
title='Количество'
|
112 |
+
)
|
113 |
+
|
114 |
+
fig.update_layout(
|
115 |
+
showlegend=False,
|
116 |
+
bargap=0.3
|
117 |
+
)
|
118 |
+
|
119 |
+
fig.update_traces(hovertemplate="Количество клиентов: %{y}")
|
120 |
+
|
121 |
+
return fig
|
122 |
+
|
123 |
+
|
124 |
+
def get_history_segment_plot(data):
|
125 |
+
fig = px.histogram(
|
126 |
+
data['history_segment'],
|
127 |
+
color=data['history_segment'],
|
128 |
+
title='Распределение клиентов по флагу history_segment'
|
129 |
+
)
|
130 |
+
|
131 |
+
fig.update_xaxes(
|
132 |
+
title='',
|
133 |
+
categoryorder='total descending'
|
134 |
+
)
|
135 |
+
|
136 |
+
fig.update_yaxes(
|
137 |
+
title='Количество'
|
138 |
+
)
|
139 |
+
|
140 |
+
fig.update_layout(
|
141 |
+
showlegend=False,
|
142 |
+
bargap=0.3
|
143 |
+
)
|
144 |
+
|
145 |
+
fig.update_traces(hovertemplate="Количество клиентов: %{y}")
|
146 |
+
|
147 |
+
return fig
|
src/web_app.py
CHANGED
@@ -1,15 +1,70 @@
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
|
3 |
import tools
|
4 |
-
from time import sleep
|
5 |
|
6 |
-
|
7 |
-
dataset = tools.get_data()
|
8 |
|
9 |
st.title('Uplift lab')
|
10 |
|
11 |
-
st.
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
|
3 |
import streamlit as st
|
4 |
|
5 |
import tools
|
|
|
6 |
|
7 |
+
|
8 |
+
dataset, target, treatment = tools.get_data()
|
9 |
|
10 |
st.title('Uplift lab')
|
11 |
|
12 |
+
st.markdown(
|
13 |
+
"""
|
14 |
+
#### Рассмотрим пример применения одного из подходов прогнозирования _uplift_.
|
15 |
+
|
16 |
+
Данные для примера взяты из [_The MineThatData E-Mail Analytics And Data Mining Challenge_](https://blog.minethatdata.com/2008/03/minethatdata-e-mail-analytics-and-data.html)
|
17 |
+
|
18 |
+
Этот набор данных содержит 42 693 строк с данными клиентов, которые в последний раз совершали покупки в течение двенадцати месяцев.
|
19 |
+
|
20 |
+
Среди клиентов была проведена рекламная кампания с помощью _email_ рассылки:
|
21 |
+
- 1/3 клиентов были выбраны случайным образом для получения электронного письма, рекламирующего мужскую продукцию;
|
22 |
+
- 1/3 клиентов были выбраны случайным образом для получения электронного письма, рекламирующего женскую продукцию;
|
23 |
+
- С оставшейся 1/3 коммуникацию не проводили.
|
24 |
+
|
25 |
+
Для каждого клиента из выборки замерили факт перехода по ссылке в письме, факт совершения покупки и сумму трат за
|
26 |
+
две недели, следующими после получения письма.
|
27 |
+
|
28 |
+
Пример данных приведен ниже.
|
29 |
+
"""
|
30 |
+
)
|
31 |
+
refresh = st.button('Обновить выборку')
|
32 |
+
title_subsample = dataset.sample(7)
|
33 |
+
if refresh:
|
34 |
+
title_subsample = dataset.sample(7)
|
35 |
+
st.dataframe(title_subsample, width=700)
|
36 |
+
st.write( f"Всего записей: {dataset.shape[0]}")
|
37 |
+
|
38 |
+
st.write('Описание данных')
|
39 |
+
st.markdown(
|
40 |
+
"""
|
41 |
+
| Колонка | Обозначение |
|
42 |
+
|-------------------|------------------------------------------------------------------------|
|
43 |
+
| _recency_ | Месяцев с момента последней покупки |
|
44 |
+
| _history_Segment_ | Классификация долларов, потраченных в прошлом году |
|
45 |
+
| _history_ | Фактическая стоимость в долларах, потраченная в прошлом году |
|
46 |
+
| _mens_ | Флаг 1/0, 1 = клиент приобрел мужские товары в прошлом году |
|
47 |
+
| _womens_ | Флаг 1/0, 1 = клиент приобрел женские товары в прошлом году |
|
48 |
+
| _zip_code_ | Классифицирует почтовый индекс как городской, пригородный или сельский |
|
49 |
+
| _newbie_ | Флаг 1/0, 1 = Новый клиент за последние двенадцать месяцев |
|
50 |
+
| _channel_ | Описывает каналы, которые клиент приобрел в прошлом году |
|
51 |
+
|
52 |
+
---
|
53 |
+
"""
|
54 |
+
)
|
55 |
+
st.write("Для того, чтобы лучше понять на какую аудиторию лучше запустить рекламную кампанию, проведем небольшой \
|
56 |
+
анализ данных")
|
57 |
+
|
58 |
+
with st.expander('Развернуть блок анализа данных'):
|
59 |
+
|
60 |
+
st.plotly_chart(tools.get_newbie_plot(dataset))
|
61 |
+
st.write(f'В данных примерно одинаковое количество новых и "старых клиентов". '
|
62 |
+
f'Отношение новых клиентов к старым: {(dataset["newbie"] == 1).sum() / (dataset["newbie"] == 0).sum():.2f}')
|
63 |
+
|
64 |
+
st.plotly_chart(tools.get_zipcode_plot(dataset))
|
65 |
+
st.write(f'Большинство клиентов из пригорода: {(dataset["zip_code"] == "Surburban").sum()}')
|
66 |
+
|
67 |
+
st.plotly_chart(tools.get_channel_plot(dataset))
|
68 |
+
|
69 |
+
st.plotly_chart(tools.get_history_segment_plot(dataset))
|
70 |
+
|