Untitled
unknown
plain_text
3 years ago
4.9 kB
42
Indexable
import pandas as pd
from datetime import datetime, timedelta
import seaborn as sns
from matplotlib import pyplot as plt
def get_conversion(
profiles,
purchases,
observation_date,
horizon_days,
dimensions=[],
ignore_horizon=False,
):
# исключаем пользователей, не «доживших» до горизонта анализа
last_suitable_acquisition_date = observation_date
if not ignore_horizon:
last_suitable_acquisition_date = observation_date - timedelta(
days=horizon_days - 1
)
result_raw = profiles.query('dt <= @last_suitable_acquisition_date')
# определяем дату и время первой покупки для каждого пользователя
first_purchases = (
purchases.sort_values(by=['user_id', 'event_dt'])
.groupby('user_id')
.agg({'event_dt': 'first'})
.reset_index()
)
# добавляем данные о покупках в профили
result_raw = result_raw.merge(
first_purchases[['user_id', 'event_dt']], on='user_id', how='left'
)
# рассчитываем лайфтайм для каждой покупки
result_raw['lifetime'] = (
result_raw['event_dt'] - result_raw['first_ts']
).dt.days
# группируем по cohort, если в dimensions ничего нет
if len(dimensions) == 0:
result_raw['cohort'] = 'All users'
dimensions = dimensions + ['cohort']
# функция для группировки таблицы по желаемым признакам
def group_by_dimensions(df, dims, horizon_days):
result = df.pivot_table(
index=dims, columns='lifetime', values='user_id', aggfunc='nunique'
)
result = result.fillna(0).cumsum(axis=1)
cohort_sizes = (
df.groupby(dims)
.agg({'user_id': 'nunique'})
.rename(columns={'user_id': 'cohort_size'})
)
result = cohort_sizes.merge(result, on=dims, how='left').fillna(0)
# делим каждую «ячейку» в строке на размер когорты
# и получаем conversion rate
result = result.div(result['cohort_size'], axis=0)
result = result[['cohort_size'] + list(range(horizon_days))]
result['cohort_size'] = cohort_sizes
return result
# получаем таблицу конверсии
result_grouped = group_by_dimensions(result_raw, dimensions, horizon_days)
# для таблицы динамики конверсии убираем 'cohort' из dimensions
if 'cohort' in dimensions:
dimensions = []
# получаем таблицу динамики конверсии
result_in_time = group_by_dimensions(
result_raw, dimensions + ['dt'], horizon_days
)
# возвращаем обе таблицы и сырые данные
return result_raw, result_grouped, result_in_time
# загружаем данные
users = pd.read_csv('ch02_problems02_users.csv') # профили
purchases = pd.read_csv('ch02_problems02_orders.csv') # покупки
# преобразование данных о времени
users['dt'] = pd.to_datetime(users['dt']).dt.date
users['first_ts'] = pd.to_datetime(users['first_ts'])
purchases['event_dt'] = pd.to_datetime(purchases['event_dt'])
observation_date = users['dt'].max() # момент анализа
analysis_horizon = 7 # горизонт анализа
conversion_raw, conversion, conversion_history = get_conversion(
users, purchases, observation_date, analysis_horizon, dimensions=['channel']
plt.figure(figsize=(20, 5))# размер сетки для графиков
# в одной ячейке — кривые конверсии
report = conversion.drop(columns=['cohort_size'])
report.T.plot(
grid=True, xticks=list(report.columns.values), ax=plt.subplot(1, 2, 1)
)
plt.title('Конверсия первых семи дней с разбивкой по каналам привлечения')
report = (
conversion_history[6]
.reset_index()
.pivot_table(index='dt', columns='channel', values=6, aggfunc='mean')
.fillna(0)
# выберите нужный день «жизни» и постройте сводную таблицу
# постройте график и задайте его параметры
report.plot(
# во второй ячейке строим график истории изменений
grid=True, ax=plt.subplot(1, 2, 2)
plt.title('Динамика конверсии 7-го дня с разбивкой по каналам привлечения')
plt.show()Editor is loading...