[case] 앱 로그 데이터로 유저의 접속 시간 계산하기
메신저 어플을 관리하는 회사의 프리랜서 외주 일을 하면서 특정 유저의 행동 단위 접속시간을 계산해야했던 적이 있다. 보통같으면 유저가"앱에 접속한 경우" 부터 "앱을 종료한 경우" 까지 모두 하나하나 태그를 심어 트래킹을 하고, 그런 경우라면 그냥 데이터끼리 빼주기만 하면 되겠지만은,, 이 회사는 후자를 트래킹하지 않은 회사였다 ㅠ
그래서 우리는 일단 다음과 같은 방법을 쓰기로 했다..
연속적으로 2분이내 일어나는 타임스탬프는 지속 접속으로 보고 그 이상의 시간이 흐른후에 타임스탬프가 찍히면 가장 마지막에 찍힌 타임스탬프 +2분을 더해 접속시간을 간접 도출
예를 들어 a 유저가..
12:00:00 에 접속
12:01:11 에 채팅침
12:01:22 에 좋아요 누름
12:02:33 에 사진 봄
…..(이하 이벤트들은 모두 2분 이내 발생)
12:17:11 에 채팅 침
17:09:22에 접속함
이번 12:00:00에 접속해서 총 접속한 시간은 12:17:11 이벤트 이후 2분 이내 새로운 이벤트가 없었기 때문에 ,
a유저의 접속 시간은 17분 11초 + 2분 = 19분 11초로 계산
내가 이 작업을 위해 추출해온 데이터는 우선 다음과 같은 형태를 띄고 있었다
유저명 | 채팅방 id | 채팅방 주인 명 | 시간 |
철수 | 345_9232 | 세비 | 2022-01-04 08:12:30 +00 |
철수 | 345_9232 | 세비 | 2022-01-04 08:12:31 +00 |
짱구 | null | null | 2022-01-04 08:12:32 +00 |
짱구 | 345_1565 | 민재 | 2022-01-04 08:12:38 +00 |
이 데이터에 대해 잠시 설명하자면, 이는 "철수" 유저가 "세비" 의 채팅방에서 30분에 한번, 31분에 한번 무언가 어떤 활동을 한 것을 확인할 수 있고, "짱구" 유저는 채팅방이 아닌 앱 활동을 32분에 한번, 그리고 "민재"의 채팅방 내 활동을 38분에 한 번 한 것을 알 수 있다.
(원래 로그데이터는 이렇게 쌓인다.._)
때문에 데이터에 어떤 추출 조건들을 걸어서 작업할 것인가도 고민했는데,
예시처럼 모든 행에 모든 값이 not null 인 것은 아니다. 우선 데이터베이스에서 추출해올 때 유저명과 시간은 필수적으로 null 이 아닌 것들만 뽑아왔고, 나머지 두 개는 null 일 수 있는 것들로 사용했다.
예를 들어, 어떤 유저가 앱 안에서 누군가의 프로필을 조회하는 등의 action 을 했다면 채팅방과 그 action 은 전혀 관련이 없기 때문에 그 행에는 채팅방 id , 채팅방 주인은 뜨지 않는다. 이 값으로 작업을 할 경우
"유저가 특정 채팅방에서 보낸 시간" 은 잡을 수 없다.
(이래서 태그는 가능하면 많이 심어야 한다.. 앱 무거워진다고? 그건 뭐 프엔 분이 해결해 주시겠지 ㅋ)
만약 저걸 잡고 싶다면 채팅방 id 에도 not null 조건을 걸고 데이터를 가져와서 채팅방 내에서 일어난 활동기록에 대해서만 시간 간접 도출을 하면 된다. 대신 그렇게 할 경우 채팅방 외부에서 보낸 시간들은 측정하기 어렵다. 그렇게 작업할 경우
"유저의 앱 내애서의 전체 접속 시간" 을 잡을 수 있게 된다
다음 코드는 위 작업을 할 때 사용한 코드다
#접속시간을 계산할 blank 한 timedelta 형의 시리즈 만들어주기
df['remain_time'] = timedelta(days=0,hours=0,minutes=0,seconds=0)
#행과 값으로 loop
for row, val in df['col'].items():
try:
#만약 특정 행의 유저명과 그 다음 행의 유저명이 같은 경우
if df['user_nickname'][row] == df['user_nickname'][row+1]:
#시차 계산
timediff = df['time'][row+1]- df['time'][row]
#시차가 2분 미만인 경우
if timediff < timedelta(days=0,hours=0,minutes=2,seconds=0):
#값 할당
df['remain_time'][row] = timediff
#시차가 2분 이상인 경우
else:
df['remain_time'][row] = timedelta(days=0,hours=0,minutes=2,seconds=0)
#만약 그 다음 행의 유저명이 앞 행의 유저명과 다른 경우
else:
df['remain_time'][row] = timedelta(days=0,hours=0,minutes=2,seconds=0)
#마지막 행은 인덱스 에러가 남 -> 마지막 행 버림..
except:
pass
분명 이것보다 더 좋은 방법이 있을 것이다.. 하하
피드백은 언제나 환영!