리텐션 분석 과제
리텐션 분석 과제 노션 문서에 정리해서 공유드립니다~
답변 1
0
붕어빵님 안녕하세요!
리텐션 분석 과제 잘 진행해주셨네요! 처음에 Weekly 리텐션을 보신 후에, Retain User 그룹으로 보신 것 잘하셨어요. Retain User 나누신 것이 제가 그린 그래프와 유사하게 나오네요.
Retain 유저 그룹
Retain 유저 그룹 그래프를 보면 말씀하신 것처럼 New가 갑자기 줄어들고 Resurrected가 늘어나는 추세를 보이지요. 이 부분은 약간 특이한 부분입니다. 부활한 유저가 많은 상황이지요. 신규 유저는 감소하고. 이런 부분을 해석해보시는 것을 추천드려요(1~2줄로 해석할 수도 있는데, 조금 더 생각해보고 가설을 만들어 보는 것이지요)
일단 신규 유저가 줄어들고 있지만, Current와 Resurrected가 늘어나는 추세입니다. 이럴 때 New를 Current로 전환을 시키면 더 많은 사용자들이 서비스를 사용하게 될거에요. Resurrected가 왜 높은가에 대해 생각해볼 수도 있는데, 회사라고 하면 어떤 Action을 해서 이게 올라가고 있을 가능성이 있습니다. 회사 위키나 다른 조직에서 무엇을 했나 확인해보면 왜 이런 결과가 나왔는지 알 수 있을거에요. 혹은 아무것도 안했는데 이런 현상이 발생했다면 이 부분에 대해 추가적으로 데이터를 확인해볼 필요가 있지요.
New => Current로 전환하면 해당 그래프에서 다시 New가 올라가서 사용자가 늘어날 것이다!라는 생각을 하고 어떻게 해야 전환될지를 생각하면서 데이터를 보면, Action Item을 생각하기 수월할거에요(제일 중요한 것은 우리가 뭘 해야할까에 대해 답을 찾는 것)
리텐션이 높은 유저 그룹
리텐션이 높은 유저 그룹에선 그래프의 Cohort가 10월 Current 유저인가요? 이 그래프를 처음 봤을 때 어떻게 해석해야 하지?라는 생각이 들었네요. 10월 활성 유저와 아닌 유저들의 리텐션 차이인지 10월 활성 유저와 다른 달 활성 유저의 차이인지가 헷갈렸습니다. 쿼리를 보면 10월 활성 유저 / 그 외로 처리하신 것 같네요. 비교 하는 집단을 그 외로 하신 이유는 무엇인가요?
코어 이벤트
코어 이벤트를 봐주셨는데, 퍼널도 같이 봐주셔도 좋을 것 같아요. 특정 주차에 갑자기 많이 주문을 했는지 혹은 연휴나 주말에 더 많이 구매했는지 등의 패턴도 존재할 수 있거든요. 이 부분에 대해서도 추가적으로 데이터 파악해보시면 결과 해석에 도움이 될거에요. 다 연결되는 부분이 존재해요(그리고 데이터를 만들 때 이런 부분을 고려해서 만들었어요)
쿼리 피드백
TIMESTAMP_ADD(TIMESTAMP_MICROS(event_timestamp), INTERVAL 540 MINUTE) AS event_timestamp : 이런 표현을 사용해주셨는데, 540을 추가하는 방법을 사용하면 데이터의 타임존이 달라질 때 이슈가 생길 수 있어요. 차라리 DATETIME으로 바꾸면서 Asia/Seoul을 명시해주는 것이 더 좋을 것 같아요(기본편 시간 데이터 다루기에 나오는 내용)
다음과 같이 변경하는 것을 추천드리고 싶어요
DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime
제가 작성했던 쿼리도 공유드려요. 약간의 차이가 존재해요. 데이터를 일요일 기준으로 하는지 월요일 기준으로 하는지 등. WEEK을 사용하셨는데, 저는 ISO_WEEK을 선호하곤 해요. New, Current 등을 구분할 때는 first와 prev activity week을 구해서 처리했어요. 이 기준은 근거에 따라 달라질 수 있어서, 말씀해주신 조건도 괜찮답니다(회사에서는 이 기준에 대해 조금 더 데이터를 보고 결정하면 되겠지요!)
WITH weekly_user_activity AS (
SELECT
user_pseudo_id,
DATE_TRUNC(event_date, WEEK) AS event_week,
MIN(DATE_TRUNC(event_date, WEEK)) OVER (PARTITION BY user_pseudo_id) AS first_activity_week,
LAG(DATE_TRUNC(event_date, WEEK)) OVER (PARTITION BY user_pseudo_id ORDER BY DATE_TRUNC(event_date, WEEK)) AS prev_activity_week
FROM
advanced.app_logs
GROUP BY
user_pseudo_id,
event_date
), weekly_user_type AS (
# 첫 사용이 첫 주차일 경우 new
# 1주 전에도 사용한 경우 current
# 첫 사용한지 2주가 지났고, 이전 사용과 지금 사용이 2주가 지났으면 resurrected
# 그 외엔 이탈로 간주해서 dormant
SELECT
*,
CASE
WHEN event_week = first_activity_week THEN 'new_user'
WHEN DATE_DIFF(event_week, prev_activity_week, WEEK) = 1 THEN 'current_user'
WHEN DATE_DIFF(event_week, first_activity_week, WEEK) > 2 AND DATE_DIFF(event_week, prev_activity_week, WEEK) > 2 THEN 'resurrected_user'
ELSE 'dormant_user'
END AS user_type
FROM weekly_user_activity
)
SELECT
event_week,
user_type,
COUNT(DISTINCT user_pseudo_id) AS user_count
FROM
weekly_user_type
GROUP BY
event_week,
user_type
ORDER BY
event_week
다른 분의 글에 제가 남긴 의견도 보시면 좋을 것 같아 남겨보아요.
제한된 데이터에서 이렇게 데이터를 추가적으로 보고, 가설을 만들고, 근거를 찾는 과정을 하는 것이 제가 문제를 출제한 의도에요. 이런 의도를 잘 충족하시면서 문제를 풀어주셨어요. 너무 고생하셨습니다!
1
상세하게 답변주셔서 감사합니다! 😃
Resurrected가 늘어나는 부분은 저도 흥미롭긴 했는데.. 추가로 살펴보고 공유드리겠습니다!
특정 코호트인 유저 vs 아닌 유저의 경우에는 쿼리를 여러 코호트랑 한 번에 비교하는 쿼리를 어떻게 작성해야할지 몰라서 약간 코호트 하나하나씩 봤던 것 같아요ㅠ 일단 아래 처럼 작성했었습니다..!
#과제3. 리텐션이 높은 유저 그룹 찾는 쿼리 작성하기
WITH base AS (
SELECT
TIMESTAMP_ADD(TIMESTAMP_MICROS(event_timestamp), INTERVAL 540 MINUTE) AS event_timestamp, -- 한국 시간 기준으로 변경
event_name,
user_id,
user_pseudo_id,
platform
FROM `advanced.app_logs`
WHERE
1=1
AND event_name = "screen_view" -- screen_view 이벤트가 있으면 활동한 유저
),
-- 1. 유저 그룹 쿼리
usergroup_base AS (
SELECT
user_pseudo_id,
event_week,
LAG(event_week) OVER(PARTITION BY user_pseudo_id ORDER BY event_week ASC) AS prior_event_week,
MIN(event_week) OVER(PARTITION BY user_pseudo_id ORDER BY event_week ASC) AS first_event_week
FROM (
SELECT
DISTINCT
user_pseudo_id,
event_name,
DATE_TRUNC(PARSE_DATE('%Y-%W', FORMAT_TIMESTAMP('%Y-%W', event_timestamp)), WEEK(MONDAY)) AS event_week,
FROM base
)
),
usergroup AS (
SELECT
user_pseudo_id,
event_week,
DATE_DIFF(event_week, prior_event_week, WEEK(MONDAY)) AS diff_of_prior_week,
DATE_DIFF(event_week, first_event_week, WEEK(MONDAY)) AS diff_of_first_week,
CASE
WHEN prior_event_week IS NULL THEN "New" -- 첫 접속 주차와 동일하 경우 New로 정의
WHEN DATE_DIFF(event_week, prior_event_week, WEEK(MONDAY)) = 1 THEN "Current" -- 주 평균 1.6회 배달앱 사용하므로 일주일 내로 접속 시 Current 유저로 정의
WHEN DATE_DIFF(event_week, prior_event_week, WEEK(MONDAY)) > 1 THEN "Resurrected" -- 나머지는 복귀 유저로 정의
WHEN DATE_DIFF(event_week, prior_event_week, WEEK(MONDAY)) > 5 THEN "Dormant" -- 보통 배달 앱의 경우 한 달 단위로 멤버십 변경되기 때문에 5주(한 달) 초과하여 재접속한 경우 휴먼 유저로 정의
END AS user_group
FROM usergroup_base
),
cohortusergroup AS (
SELECT
DISTINCT
user_pseudo_id
FROM usergroup
WHERE
1=1
AND user_group = "Resurrected"
AND FORMAT_DATE("%Y-%m", event_week) = "2022-10"
),
-- 2. 위클리 리텐션 기본 쿼리
retain_base AS (
SELECT
user_pseudo_id,
event_name,
event_date,
MIN(event_date) OVER(PARTITION BY user_pseudo_id ORDER BY event_date ASC) AS first_date,
cohort
FROM (
SELECT
DISTINCT
DATE(b.event_timestamp) AS event_date,
b.event_name,
b.user_pseudo_id,
CASE
WHEN c.user_pseudo_id IS NULL THEN "Not"
ELSE "Cohort"
END AS cohort -- 코호트 그룹과 아닌 그룹과 비교할 값 추가하기
FROM base AS b
LEFT JOIN cohortusergroup AS c
ON b.user_pseudo_id = c.user_pseudo_id
)
),
weekly_retention AS (
SELECT
diff_of_week,
cohort,
COUNT(DISTINCT user_pseudo_id) AS user_cnt
FROM (
SELECT
user_pseudo_id,
event_name,
event_date,
first_date,
cohort,
DATE_DIFF(event_date, first_date, WEEK(MONDAY)) AS diff_of_week
FROM retain_base
)
GROUP BY ALL
)
SELECT
diff_of_week,
cohort,
user_cnt,
first_week_user_cnt,
ROUND(SAFE_DIVIDE(user_cnt, first_week_user_cnt),3) AS retention_rate
FROM (
SELECT
diff_of_week,
cohort,
user_cnt,
FIRST_VALUE(user_cnt) OVER(PARTITION BY cohort ORDER BY diff_of_week) AS first_week_user_cnt
FROM weekly_retention
)
ORDER BY
1, 2코어 이벤트 관련해서도 시간날 때 보고 과제 업데이트해보겠습니다~!
최종 과제 제출
0
79
3
BigQuery 활용편 18강 질문있습니다!
0
80
1
리텐션 공부하다가 궁금한게 생겨 질문드립니다
0
79
2
안녕하세요 강사님 코호트 쿼리 공부하다가 의문점이 생겨서 문의드립니다
0
70
2
biquery 테이블 생성 오류 이슈
0
51
2
동일하게 쿼리를 작성했는데 화면과 다른 값이 나옵니다
0
72
2
[과제] 퍼널 PIVOT 테이블 작성하기
0
64
2
array 등
0
61
2
N day 리텐션 쿼리 관련 질문
0
61
2
이동평균 계산 시 order by 기본값은 뭔가요?
0
66
2
윈도우 연습문제 1번 질문
0
61
1
user_id에 NULL이 나오는데 정상인가요?
0
70
2
3-13 리텐션 과제 제출
0
92
2
최종 과제 제출
0
129
3
weekly retention 구하기 과제
0
90
2
1-9. 피벗 쿼리 작성
0
78
2
app_logs 테이블 생성 문제
0
70
2
Weekly Retention 구하기 완성하였습니다.
0
75
2
[과제] 퍼널 쿼리(피벗테이블 적용) 작성 완료
0
104
2
3-7 Weekly, Monthly Retention 쿼리 작성
0
91
2
정성 데이터 분석 방법 문의
0
163
1
최종 과제 제출
0
105
3
1-6 예시 문제 풀이
0
66
2
최종과제 제출
0
141
2





