# функция для расчёта конверсии 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