Untitled

From Chartreuse Owl, 2 Months ago, written in Plain Text, viewed 42 times.
URL http://codebin.org/view/0dc4c7b1 Embed
Download Paste or View Raw
  1. def get_retention(profiles, sessions, observation_date, horizon_days, dimensions = [], ignore_horizon = False):
  2.    
  3.     # добавляем столбец payer в передаваемый dimensions список
  4.     dimensions = ['payer'] + dimensions
  5.    
  6.     # исключаем пользователей, не «доживших» до горизонта анализа
  7.     # тех, которые присоединились позже, чем observation_date - horizon
  8.     last_suitable_acquisition_date = observation_date
  9.     if not ignore_horizon:
  10.         last_suitable_acquisition_date = observation_date - timedelta(days = horizon_days - 1)
  11.     result_raw = profiles.query('dt <= @last_suitable_acquisition_date')
  12.  
  13.     # собираем «сырые» данные для расчёта удержания
  14.     result_raw = result_raw.merge(sessions[['user_id', 'session_start']], on = 'user_id', how = 'left')
  15.     result_raw['lifetime'] = (result_raw['session_start'] - result_raw['first_ts']).dt.days
  16.    
  17.     # функция для группировки таблицы по желаемым признакам
  18.     def group_by_dimensions(df, dims, horizon_days):    
  19.         result = df.pivot_table(index = dims, columns = 'lifetime', values = 'user_id', aggfunc = 'nunique')     # строим «треугольную таблицу»
  20.         cohort_sizes = df.groupby(dims).agg({'user_id': 'nunique'}).rename(columns = {'user_id': 'cohort_size'}) # определяем размеры когорт
  21.         result = cohort_sizes.merge(result, on = dims, how = 'left').fillna(0)                                   # присоединяем размеры когорт к «треугольной» таблице
  22.         result = result.div(result['cohort_size'], axis = 0)                                                     # делим каждую «ячейку» на соответствующий размер когорты и получаем retention rate
  23.         result = result[['cohort_size'] + list(range(horizon_days))]                                             # исключаем все лайфтаймы, превышающие горизонт анализа
  24.         result['cohort_size'] = cohort_sizes                                                                     # восстанавливаем размеры когорт
  25.         return result
  26.    
  27.     # получаем таблицу удержания
  28.     result_grouped = group_by_dimensions(result_raw, dimensions, horizon_days)
  29.    
  30.     # получаем таблицу динамики удержания
  31.     result_in_time = group_by_dimensions(result_raw, dimensions + ['dt'], horizon_days)
  32.    
  33.     # возвращаем обе таблицы и сырые данные
  34.     # сырые данные пригодятся, если нужно будет отыскать ошибку в расчётах
  35.     return result_raw, result_grouped, result_in_time
  36.  
  37. def get_conversion(
  38.     profiles,
  39.     purchases,
  40.     observation_date,
  41.     horizon_days,
  42.     dimensions=[],
  43.     ignore_horizon=False,
  44. ):
  45.  
  46.     # исключаем пользователей, не «доживших» до горизонта анализа
  47.     last_suitable_acquisition_date = observation_date
  48.     if not ignore_horizon:
  49.         last_suitable_acquisition_date = observation_date - timedelta(
  50.             days=horizon_days - 1
  51.         )
  52.     result_raw = profiles.query('dt <= @last_suitable_acquisition_date')
  53.  
  54.     # определяем дату и время первой покупки для каждого пользователя
  55.     first_purchases = (
  56.         purchases.sort_values(by=['user_id', 'event_dt'])
  57.         .groupby('user_id')
  58.         .agg({'event_dt': 'first'})
  59.         .reset_index()
  60.     )
  61.  
  62.     # добавляем данные о покупках в профили
  63.     result_raw = result_raw.merge(
  64.         first_purchases[['user_id', 'event_dt']], on='user_id', how='left'
  65.     )
  66.  
  67.     # рассчитываем лайфтайм для каждой покупки
  68.     result_raw['lifetime'] = (
  69.         result_raw['event_dt'] - result_raw['first_ts']
  70.     ).dt.days
  71.  
  72.     # группируем по cohort, если в dimensions ничего нет
  73.     if len(dimensions) == 0:
  74.         result_raw['cohort'] = 'All users'
  75.         dimensions = dimensions + ['cohort']
  76.  
  77.     # функция для группировки таблицы по желаемым признакам
  78.     def group_by_dimensions(df, dims, horizon_days):
  79.         # строим «треугольную» таблицу конверсии
  80.         result = df.pivot_table(
  81.             index=dims, columns='lifetime', values='user_id', aggfunc='nunique'
  82.         )
  83.         # считаем сумму с накоплением для каждой строки
  84.         result = result.fillna(0).cumsum(axis = 1)
  85.         # вычисляем размеры когорт
  86.         cohort_sizes = (
  87.             df.groupby(dims)
  88.             .agg({'user_id': 'nunique'})
  89.             .rename(columns={'user_id': 'cohort_size'})
  90.         )
  91.         # добавляем размеры когорт в таблицу конверсии
  92.         result = cohort_sizes.merge(result, on=dims, how='left').fillna(0)
  93.         # делим каждую «ячейку» в строке на размер когорты
  94.         # и получаем conversion rate
  95.         result = result.div(result['cohort_size'], axis=0)
  96.         # исключаем все лайфтаймы, превышающие горизонт анализа
  97.         result = result[['cohort_size'] + list(range(horizon_days))]
  98.         # восстанавливаем размеры когорт
  99.         result['cohort_size'] = cohort_sizes
  100.         return result
  101.  
  102.     # получаем таблицу конверсии
  103.     result_grouped = group_by_dimensions(result_raw, dimensions, horizon_days)
  104.  
  105.     # для таблицы динамики конверсии убираем 'cohort' из dimensions
  106.     if 'cohort' in dimensions:
  107.         dimensions = []
  108.  
  109.     # получаем таблицу динамики конверсии
  110.     result_in_time = group_by_dimensions(
  111.         result_raw, dimensions + ['dt'], horizon_days
  112.     )
  113.  
  114.     # возвращаем обе таблицы и сырые данные
  115.     return result_raw, result_grouped, result_in_time

Reply to "Untitled"

Here you can reply to the paste above