-
<TIL> 2024-04-09내일배움캠프(데이터 분석 부트캠프 1기)/TIL & WIL 2024. 4. 9. 22:08
- 오늘 진행한 일
- 최종 프로젝트 파이썬 함수 작성(리텐션)
- SQL 코드테스트
https://datarian.io/blog/rolling-retention
리텐션 (2) Rolling Retention
롤링 리텐션은 '사용자가 이탈하지 않고 남아있는가?'에 초점을 맞추기 때문에 Unbounded Retention 이라고도 부릅니다.
datarian.io
오늘은 파이썬을 이용해 롤링 리텐션과 n_day 리텐션을 구하는 함수를 작성하였다.
롤링 리텐션은 위의 데이터리안 링크를 참고하였다.
롤링 리텐션은 기준일을 포함하여 그 이후에 한 번이라도 재방문한 유저의 비율을 나타내는데,
기준일 이후에 방문 기록이 있다면, 기준일 당시에는 이탈하지 않은 사용자로 계산한단 것이다.
함수는 아래와 같다.
def visualize_retention(retention_percent:pd.DataFrame) : plt.plot(retention_percent.loc[0]) plt.xticks(rotation=45) plt.show()
def rolling_retention(retention_table:pd.DataFrame, retention_period:int) : for idx in retention_table.index : if retention_table.loc[idx][f'retention_{retention_period*6}'] == 1 : retention_table.loc[idx] = 1 elif retention_table.loc[idx][f'retention_{retention_period*5}'] == 1 : retention_table.loc[idx, [f'retention_{retention_period}', f'retention_{retention_period*2}', f'retention_{retention_period*3}', f'retention_{retention_period*4}']] = 1 elif retention_table.loc[idx][f'retention_{retention_period*4}'] == 1 : retention_table.loc[idx, [f'retention_{retention_period}', f'retention_{retention_period*2}', f'retention_{retention_period*3}']] = 1 elif retention_table.loc[idx][f'retention_{retention_period*3}'] == 1 : retention_table.loc[idx, [f'retention_{retention_period}', f'retention_{retention_period*2}']] = 1 elif retention_table.loc[idx][f'retention_{retention_period*2}'] == 1 : retention_table.loc[idx, [f'retention_{retention_period}']] = 1 return retention_table
def retention(transaction:pd.DataFrame, year_month:str, retention_period:int) : # 받아온 테이블에서 필요한 데이터만을 저장한 후 메모리 정리 transaction_time_by_customer = transaction[['customer_id', 'created_at']] del transaction # 계산 및 비교가능한 날짜 형식으로 변환 transaction_time_by_customer = transaction_time_by_customer.assign(created_at = transaction_time_by_customer['created_at'].dt.strftime('%Y-%m-%d')) transaction_time_by_customer = transaction_time_by_customer.assign(created_at = pd.to_datetime(transaction_time_by_customer['created_at'])) # 받아온 날짜 형변환 picked_time = datetime.strptime(year_month, '%Y-%m') for_retain_start_time = picked_time - timedelta(days=retention_period) # picked_time 이전 retention기간일(기준 retention을 잡기 위함) for_retain_end_time = picked_time + timedelta(days=retention_period*6) # picked_time 이후 retention기간*6 일 # 리텐션에 사용할 데이터 picked_data = transaction_time_by_customer[(transaction_time_by_customer['created_at']>=for_retain_start_time) &(transaction_time_by_customer['created_at']<for_retain_end_time)] # 메모리 정리 del transaction_time_by_customer # retain 기간별로 dataframe 적재 retain_period = [] retain_period.append(picked_data.loc[(picked_data['created_at']>=for_retain_start_time)& (picked_data['created_at']<picked_time)]) for i in range(6) : retain_period.append(picked_data.loc[(picked_data['created_at']>=picked_time+timedelta(days=retention_period*i))& (picked_data['created_at']<picked_time+timedelta(days=retention_period*(i+1)))]) # retain 기간 별로 유저가 방문했는지 여부 # groupby('customer_id').count로 계산 retention_group = [] for i, df in enumerate(retain_period) : retention_group.append(df.groupby('customer_id').count().rename(columns={'created_at':f'retention_{i*retention_period}'})) # 리텐션 테이블 생성 retention = pd.concat(retention_group, axis=1) retention = retention[~retention['retention_0'].isnull()] # retention_0값이 비어있는 경우 삭제 retention = retention.fillna(0) # 그 외 null값은 0으로 채움 retention = retention.astype(int) retention[retention>1] = 1 # retention에 rolling 적용 rolling_retention_table = rolling_retention(retention, retention_period) rolling_retention_percent = (rolling_retention_table.mean().to_frame().T*100).round(2) print('rolling_retention_table') display(rolling_retention_table) print('-----------------------------------------------\nrolling_retention_percentage') display(rolling_retention_percent) print('-----------------------------------------------\nrolling_retention_curve') visualize_retention(rolling_retention_percent) return retention, rolling_retention_table, rolling_retention_percent
unrolled_retention, rolling_retention_table, rolling_retention_percent = retention(paid_transaction_trend, '2018-01', 60)
retention_period를 기준으로해서 해당 기간 안에 한 번이라도 접속 이력이 있으면 retention이 있는 것으로 판단하고
그 이후에라도 접속했다면 이전 기간 또한 이탈하지 않은 것으로 간주되도록 rolling하는 코드를 작성하였다.
그리고 리텐션의 퍼센트를 계산하여 리텐션 커브 곡선까지 시각화 되도록 하였다.
그리고 위 코드를 조금 수정하여서 n_day retention 코드 또한 작성하였다.
def retention_nday(transaction:pd.DataFrame, year_month_day:str, n_day:list) : # 받아온 테이블에서 필요한 데이터만을 저장한 후 메모리 정리 transaction_time_by_customer = transaction[['customer_id', 'created_at']] del transaction # 계산 및 비교가능한 날짜 형식으로 변환 transaction_time_by_customer = transaction_time_by_customer.assign(created_at = transaction_time_by_customer['created_at'].dt.strftime('%Y-%m-%d')) transaction_time_by_customer = transaction_time_by_customer.assign(created_at = pd.to_datetime(transaction_time_by_customer['created_at'])) # 받아온 날짜 형변환 picked_time = datetime.strptime(year_month_day, '%Y-%m-%d') n_day.insert(0, 0) # n_day리스트 맨 앞에 0 추가 # n_day에 해당하는 날짜 데이터 값을 적재 retain_period = [] for n in n_day : retain_period.append(transaction_time_by_customer[(transaction_time_by_customer['created_at']==picked_time+timedelta(days=n))]) # 메모리 정리 del transaction_time_by_customer # retain 기간 별로 유저가 방문했는지 여부 # groupby('customer_id').count로 계산 retention_group = [] for i, df in enumerate(retain_period) : retention_group.append(df.groupby('customer_id').count().rename(columns={'created_at':f'retention_{n_day[i]}'})) # 리텐션 테이블 생성 retention = pd.concat(retention_group, axis=1) retention = retention[~retention['retention_0'].isnull()] # retention_0값이 비어있는 경우 삭제 retention = retention.fillna(0) # 그 외 null값은 0으로 채움 retention = retention.astype(int) retention[retention>1] = 1 retention_percent = (retention.mean().to_frame().T*100).round(2) print('retention_table') display(retention) print('-----------------------------------------------\nrolling_retention_percentage') display(retention_percent) print('-----------------------------------------------\nrolling_retention_curve') visualize_retention(retention_percent) return retention, retention_percent
n_day에 대한 리스트를 예를 들어 [1, 7, 30]으로 넣은 경우 아래와 같이 해당 날짜 이후 1일, 7일, 30일에
다시 구매를 했는가 여부를 리텐션으로 확인할 수 있다.
아무래도 패션 데이터다보니 1일뒤에는 대부분 돌아오지 않았고 30일 뒤에는 소수의 사람이 재구매를 한 것으로
확인되었다.
내일은 중간 발표를 대비하여 EDA를 정리하고 발표 자료를 작성할 예정이다.
'내일배움캠프(데이터 분석 부트캠프 1기) > TIL & WIL' 카테고리의 다른 글
<TIL> 2024-04-04 (0) 2024.04.04 <TIL> 2024-04-02 (0) 2024.04.02 <WIL> 2024년 3월 마지막 주 회고 (0) 2024.03.29 <TIL> 2024-03-29 (0) 2024.03.29 <TIL> 2024-03-28 (1) 2024.03.28 - 오늘 진행한 일