7 день возврата / удержания - PullRequest
       2

7 день возврата / удержания

0 голосов
/ 12 декабря 2018

Я пытался вычислить 7-дневный коэффициент возврата (также известный как классический коэффициент удержания, как описано здесь: https://www.braze.com/blog/calculate-retention-rate/), а затем взял среднее значение за 30 дней, чтобы уменьшить шум в Postgresql.

Тем не менее, я уверен, что я делаю что-то не так. Во-первых, цифры выглядят намного выше, чем интуитивно я думаю, что они должны быть (обычно около 5% для остальной части сектора). Кроме того, я считаю, что первые 7дни должны показывать 0, так как теоретически пользователям должно потребоваться не менее 7 дней, чтобы считаться «возвратом». Однако я получаю около 40-70%, как показано ниже.

Не возражает ли кто-нибудь взглянуть наПриведенный ниже код и выяснение, есть ли какие-либо ошибки? 7-дневная норма возврата - это действительно распространенная метрика для приложений, и я не нашел никаких вопросов, используя postgresql, чтобы вычислить его до этого уровня сложности в Stack Exchange (или даже в остальной части), поэтому я чувствую, что твердый ответ может быть очень полезен для многих людей.

Пример данных

Wednesday, August 1, 2018 12:00 AM    71.14
Thursday, August 2, 2018 12:00 AM     55.44
Friday, August 3, 2018 12:00 AM       50.09
Saturday, August 4, 2018 12:00 AM     45.81
Sunday, August 5, 2018 12:00 AM       43.27
Monday, August 6, 2018 12:00 AM       40.61
Tuesday, August 7, 2018 12:00 AM      39.38
Wednesday, August 8, 2018 12:00 AM    38.46
Thursday, August 9, 2018 12:00 AM     36.81
Friday, August 10, 2018 12:00 AM      35.94
with

user_first_event as (
    select distinct id, min(timestamp)::date as first_event_date
    from log
    where 
        timestamp <= current_date
        and timestamp >= {{start_date}} and timestamp <= {{end_date}}
    group by id),

event as (
    select distinct id, timestamp::date as user_event_date
    from log
    where timestamp <= current_date and timestamp >= {{start_date}}),

gap as (
    select 
        user_first_event.id, 
        user_first_event.first_event_date,
        event.user_event_date,
        event.user_event_date - user_first_event.first_event_date as days_since_signup
    from user_first_event
    join event on user_first_event.id = event.id
    where user_first_event.first_event_date <= event.user_event_date),

conversion_rate as (
select
    first_event_date,
    (sum(case when days_since_signup = 7 then 1 else 0 end) * 100.0 /
        count(distinct id)
      ) as seven_day_retention_rate
from gap
group by first_event_date
)

SELECT first_event_date,  
       AVG(seven_day_retention_rate)
            OVER(ORDER BY first_event_date ROWS BETWEEN 29 PRECEDING AND CURRENT ROW) AS rolling_avg_retention_rate
FROM conversion_rate

1 Ответ

0 голосов
/ 14 декабря 2018

Проблема немного проще, чем кажется из вашего запроса, вы можете сделать это с помощью всего одного подзапроса и одного запроса следующим образом:

select first_event_date
 , avg(seven_day_return) as seven_day_return_day_only
 , avg( avg(seven_day_return) ) OVER(ORDER BY first_event_date asc ROWS BETWEEN 29 preceding AND CURRENT ROW ) AS thirty_day_rolling_retention
from (
  --inner query to get value for user, 1 if they retain and 0 if they do not
  select min(timestamp)::date as first_event_date
   , case when array_agg(timestamp::date) @> ARRAY[ (min(timestamp)::date + 7) ] then 1 else 0 end as seven_day_return
  from log
  group by id ) t

group by t.first_event_date;

Обратите внимание, что это весит каждый день одинаково, а не пользователь одинаково по дням.Если вы хотите взвесить среднее значение по пользователям по дням, вы можете обновить внешний расчет, используя больше агрегатов и окон, чтобы вычислить значение с весами.

Ссылка: http://sqlfiddle.com/#!17/ee17e/1/0

Если вы неу вас нет доступа к array_agg (но есть доступ к оконным функциям), который вы можете использовать:

select first_event_date
 , avg(seven_day_return) as day_seven_day_return
 , avg( avg(seven_day_return) ) OVER(ORDER BY first_event_date asc ROWS BETWEEN 29 preceding AND CURRENT ROW ) AS thirty_day_rolling_retention
from (
  --inner query to get value for user
  select min(timestamp)::date as first_event_date
   , case when exists(select 1 from log l2 where l2.id = log.id and l2.timestamp::date = min(log.timestamp)::date + 7) then 1 else 0 end as seven_day_return
  from log
  group by id ) t

group by t.first_event_date;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...