* 자료 출처: Kaggle - Google Analytics Customer Revenue Prediction
1. 문제 배경
- GA 로그데이터로 유저별 평균 세션 시간을 ECDF로 시각화
- 평균 세션 시간 데이터가 따로 제공되지 않아 User_id와 방문시작시간 칼럼을 활용해 세션ID 생성
2. 세션ID 생성
- 각 유저의 방문시작시간의 차가 30분 이내인 값에 동일한 세션ID 부여
- 방문시작시간의 차가 30분 이상일 경우 다른 세션ID 부여
- 1) 방문시작시간으로 정렬하고, 2) diff로 전 행과의 시간 차이가 30분 미만인지 체크하고, 3) cumsum으로 id 부여
## sessoin_id 생성하기
# 1. 시간, 방문자id 기준으로 정렬한 데이터 프레임 생성
df_sorted = df[['visitStartTime', 'fullVisitorId']]
df_sorted = df_sorted.sort_values(by=['visitStartTime', 'fullVisitorId'])
df_sorted['visit_ymd'] = df_sorted['visitStartTime'].dt.strftime('%Y-%m-%d')
# 2. 유저id와 일별로 세션 시작시간 차이 diff()하여, ['diff']열 생성
df_sorted['diff'] = df_sorted.groupby(['fullVisitorId', 'visit_ymd'])['visitStartTime'].diff()
# 3. 조건에 따라 cumsum하여 id 부여
# sessoin_id 부여할 조건절 변수 지정 # diff 값 null이거나 30분 이상
diff_cond = (df_sorted['diff'].isnull()) | (df_sorted['diff'] > dt.timedelta(minutes=30))
# 조건이 true면, cumsum을, 아니면 null을 출력
df_sorted['new_id'] = np.where(diff_cond, diff_cond.cumsum(), None)
# 데이터프레임을 id 기준으로 재정렬
df_sorted = df_sorted.sort_values(by='fullVisitorId')
# diff_cond 조건에 맞지 않아 null 처리된 열은 위 행과 동일한 id 값 부여
df_sorted['new_id'] = df_sorted['new_id'].fillna(method='ffill')
- 세션id 적용 예시
- 그룹바이하여 diff와 cumsum을 한 번에 처리해보고자 했으나 세션ID가 제대로 분류되지 않아 상기 방법 활용
# 잘못된 코드
# 유저별로 그룹핑하여 방문시간 차이가 30분 이상인 경우 신규 값 지정
# 동일 일자 방문 시간 30분 이내에 3번 이상 방문한 경우 모두 동일한 세션id가 부여되지 않음
# 2개는 동일한 세션ID, 1개는 다른 세션ID가 부여됨
df_sorted['session_cum_id'] = (df_sorted.groupby(['fullVisitorId','visit_ymd'])['visitStartTime'].diff(axis=0, periods=1) >= dt.timedelta(minutes=30)).transform('cumsum')
3. 평균 세션 시간 구하기
- 평균 세션 시간은 유저별 일별 세션시간의 평균 값을 구해야 함
└ (마지막 세션시간-최초 세션시간 / 총 세션수 )
## 평균 세션 시간 구하기
# 유저별-일별로 max, mim time & total session count 생성
df_sorted['daily_max_time'] = df_sorted.groupby(['fullVisitorId','visit_ymd'])['visitStartTime'].transform('max')
df_sorted['daily_min_time'] = df_sorted.groupby(['fullVisitorId','visit_ymd'])['visitStartTime'].transform('min')
df_sorted['daily_total_seesion'] = df_sorted.groupby(['fullVisitorId','visit_ymd'])['new_id'].transform('nunique')
# 유저별 일별 세션 시간
# max time - min time / total session 으로 일 평균 세션 시간 구하기
df_sorted['daily_session_time'] = (df_sorted['daily_max_time']-df_sorted['daily_min_time'])
df_sorted['daily_avg_session_time'] = (df_sorted['daily_max_time']-df_sorted['daily_min_time']) / df_sorted['daily_total_seesion']
# 초 > 분으로 단위 변경
df_sorted['daily_avg_session_time'] = df_sorted['daily_avg_session_time'].dt.seconds / 60
# 유저별 평균 세션 시간
# 평균 세션 시간이 0인 비중이 94%
# 0포함 버전
df_avg_session_time = pd.DataFrame(df_sorted.groupby('fullVisitorId')['daily_avg_session_time'].mean())
# 0제외 버전
df_session_time_not_zero = df_sorted[df_sorted['daily_avg_session_time'] > 0]
df_avg_session_time_not_zero = pd.DataFrame(df_session_time_not_zero.groupby('fullVisitorId')['daily_avg_session_time'].mean())
4. ECDF 시각화
- ECDF는 Empirical cumulative distribution function의 약어로 경험적 누적 분포 함수라고 부름
- 서로 다른 표본의 분포를 비교할 때 주로 사용하며, 각 집단의 백분위를 추정
#ECDF 그래프 시각화
plt.figure(figsize= (12,5))
plt.subplot(1,2,1)
sns.ecdfplot(data=df_avg_session_time, x='daily_avg_session_time')
plt.subplot(1,2,2)
sns.ecdfplot(data=df_avg_session_time_not_zero, x='daily_avg_session_time')
'TIL' 카테고리의 다른 글
[240215] 피벗 테이블을 활용한 히트맵 시각화 (0) | 2024.02.16 |
---|---|
[240214] 파이차트: 기준값 추가 / 막대그래프: X축 이름 및 간격 변경 (0) | 2024.02.14 |
[240208] 날짜 데이터 타입 변환 및 처리(to_datetime, datetime) (0) | 2024.02.08 |
[240207] 문자열, 숫자 데이터 타입 변환(astype, to_numeric) (0) | 2024.02.08 |
[240206] 중첩 딕셔너리? JSON 포맷 데이터프레임으로 평면화 (0) | 2024.02.06 |