파이썬으로 코호트분석하기

매일매일 쏟아지는 데이터들 - 노출수, 클릭수, CTR, ROAS 등 - 여러 지표들은 현재 상황에 대하여 혹은 특정 기간에 대하여 유의미한 정보를 제공하지만 "한 번 우리 홈페이지에 들어온 고객들은 우리 홈페이지를 계속적으로 이용하고 있는가?" 혹은 "우리 앱을 설치한 이후, 계속적으로 이용하고 있는가? "라는 사용자 유지의 관점에 대하여는 인사이트를 얻을 수 없습니다.

이러한 질문에 대하여 데이터로 답을 제시하고자 할 때, 코호트 분석(Cohort Analysis)은 위 질문에 대한 효과적인 대답이 될 수 있습니다.

구글애널리틱스에서 제공하는 코호트 분석(동질 집단 분석)

로그분석으로 주로 사용되는 구글애널리틱스에서도 코호트 분석을 제공하고 있습니다. 위 분석의 주제는 "사용자 유지율"에 대한 코호트 분석입니다. 인덱스(y축)는 첫 방문일자를, 칼럼(x축)은 기간을 보여주고 있는데, 이는 코호트 분석의 두 가지 조건 - 동일한 경험, 동일한 기간 - 을 인덱스와 칼럼으로 표현하고 있는 것입니다.

따라서 파이썬에서 코호트 분석을 하기 위하여는 '동일한 경험'과 '동일한 시간'이 데이터에서 표현되도록 데이터를 전처리해야합니다. 그렇다면 아래의 내용을 통해 어떻게 파이썬에서 코호트 분석을 할 수 있는지 그 과정을 알아보도록 하겠습니다.

본 포스팅은 파이썬 코호트 분석을 위해 자주 인용되는 글 - Cohort Analysis with Python, Greg Reda - 에 기초하였습니다. 블로그 저자 분께 이메일을 보내 블로그 소개 및 스크립트 이용 허락을 받았음을 미리 말씀드립니다. 그런데 해당 블로그의 코드는 파이썬과 판다스에 익숙치 않은 분들이라면 선뜻 이해하기 어려울 수 있기 때문에 좀 더 쉬운 문법으로 대체하여 본 포스팅을 작성하였습니다.



코호트 분석(Cohort Analysis)

- 사용자 유지율 파악하기

1. 실습데이터 불러오기

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

판다스의 read_excel함수에 예제로 사용할 relay-foods.xlsx 파일이 있는 URL을 입력하여 데이터를 가져옵니다. 그리고 head함수를 사용하여 데이터를 살펴보면 하나의 raw에 유저아이디(UserId)와 주문날짜(OrderDate)가 함께 구성되어 있어, 코호트의 기본 전제조건(동일한 경험, 동일한 기간)을 충족하는 데이터로 전처리할 수 있습니다. 자세한 방법은 이어지는 내용을 통해 살펴보도록 하겠습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

info함수를 사용하면 데이터의 구성을 확인할 수 있습니다. 데이터의 칼럼은 'OrderId', 'OrderDate', 'UserId', 'TotalCharges', 'CommonId', 'PupId', 'PickupDate'로 구성되어 있습니다. 또 모든 칼럼에 결측치가 없는 것을 확인할 수 있습니다.

* 코호트 분석을 위한 칼럼 외의 불필요한 칼럼 삭제

'CommonId','PupId','PickupDate','TotalCharges' 칼럼들은 분석에 필요하지 않은 칼럼들입니다. 굳이 삭제하지 않아도 되지만 포스팅 지면을 효율적으로 사용하기 위하여 필요없는 칼럼을 삭제합니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

2. 주문일자(OrderDate) 칼럼으로 단위 기간 만들기

코호트 분석시 데이터를 집계하기 위한 단위 기간은 보통 월단위로 진행됩니다. 실습 데이터에서 시간을 표현하는 OrderDate칼럼의 데이터는 일단위로 구성되어 있으므로, 이 칼럼의 데이터를 사용하여 월단위 데이터를 추출할 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

이때 OrderDate의 데이터타입을 살펴보면 위와 같이 시계열 데이터인 것을 확인할 수 있습니다. 이러한 경우, 시리즈의 dt accessor를 적용하여 시계열 데이터를 간단히 처리할 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

dt accessor 중 strftime함수에 '%Y-%m'를 전달하여 "년-월"의 형태로 데이터를 처리하고, 해당 데이터를 사용하여 OrderPeriod 칼럼을 새로 만듭니다. 이렇게 각 raw에 분석의 기준이 되는 월단위 데이터를 추가할 수 있습니다.

3. 유저의 첫번째 주문을 토대로 유저별 코호트 그룹 설정하기

코호트 분석의 전제조건 중 동일한 경험을 만드는 과정입니다. 현재 코호트 분석의 주제는 사용자유지율 분석 인데, 실습데이터에서의 동일한 경험이란 첫 번째 주문입니다. 이번 과정에서는 각각의 raw에 고객ID별 첫 번째 주문일자를 추가하도록 하겠습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

set_index함수를 사용하여 데이터프레임의 인덱스를 지정할 수 있습니다. 함수에 'UserId'를 전달하여 데이터프레임의 인덱스가 고객ID가 되도록 합니다. 예시의 코드에 사용된 inplace 매개변수는 기존 변수에 함수의 결과를 적용하는 역할을 합니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

set_index함수를 사용한 데이터프레임을 groupby함수로 그룹화합니다. 이 때 df.index(데이터프레임의 인덱스, 즉 UserId로 그룹화하면 고객의 UserId 별로 데이터가 그룹화 되며, OrderDate 칼럼값을 따로 추출합니다. 그리고 집계함수 min을 사용하여 최소값을 추출하면 각 UserId별 첫 주문일자가 추출됩니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

코호트 분석의 기준은 월 단위이므로 dt accessor에 "%Y-%m"을 전달하여 데이터를 년-월로 변경합니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

위 셀의 첫 행처럼 index가 UserId인 기존 데이터프레임(df)에 FirstOrder변수로 FirstOrder 칼럼을 추가하면 df와 FirstOrder의 동일한 인덱스를 기준으로 데이터를 배치해줍니다. 그리고 reset_index함수를 사용한 결과를 살펴보면 기존 데이터프레임의 각 raw에 첫 주문일자가 입력된 것을 확인할 수 있습니다.

4. 코호트 그룹과 주문기간으로 데이터 집계하기

다음 코딩을 진행하기 전에, 고객들이 우리 홈페이지에 방문한 횟수를 집계하는 방법에 대해 살펴보겠습니다. 고객들이 우리의 홈페이지를 처음 방문한 후, 자신의 니즈에 따라 계속적으로 이용할 수도 있고, 이용하지 않을 수도 있습니다. 이러한 활동을 월단위로 구분지어 본다면 아래의 표와 같을 것입니다.(이해를 돕기 위해 예시로 구성된 데이터입니다)

첫 달두번째달세번째 달네번째 달다섯번째 달여섯번째 달
고객 A1085432
고객 B201584
고객 C325

월별 방문자수(Monthly Visitor)

그러나 사용자 유지율을 파악하기 위한 코호트 분석에서는 위의 표처럼 각각의 방문을 모두 집계하는 것이 아니라 아래의 표처럼 순방문자(UV)로 집계해야 합니다. 파이썬에서 데이터를 아래의 방식으로 집계하기 위하여는 어떻게 코딩해야하는지 알아보도록 하겠습니다.

첫 달두번째달세 번째 달네 번째 달다섯번째 달여섯번째 달
고객 A111111
고객 B1111
고객 C111

월별 순방문자수(Monthly Unique Visitor)

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

groupby 함수에 첫 주문일자를 나타내는 FirstOrder와 주문별 기간을 나타내는 OrderPeriod를 함께 전달하여 첫 방문기간과 주문기간을 기준으로 데이터를 그룹화 합니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

grouped 객체에 고객아이디(UserId)를 집계하며, 집계함수로 각 unique값의 개수를 세는 nunqiue함수를 사용합니다. 이렇게 코딩하면 고객이 여러번 방문했다 하더라도 한 번으로 집계하게 되어 월별 순방문자수를 파악할 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

reset_index함수를 사용한 데이터프레임을 살펴보면 FirstOrder, OrderPeriod, UserId 칼럼으로 구성되어 있는 것을 살펴볼 수 있습니다. 그런데 UserId칼럼은 처음 데이터를 가져왔을 때 47, 95, 98, 112, 141 등 고객별 UserId 데이터로 구성되어 있었는데, 현재는 순방문자수를 집계한 데이터로 구성되어 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

따라서 순방문자수라는 의미에 맞게 rename함수를 사용하여 TotalUsers로 변경한 후 계속적으로 데이터 전처리를 진행합니다.

5. 데이터가 없는 기간 체크 및 데이터 전처리

코호트 분석 화면을 보면 기간을 표현하는 칼럼(x축)은 0부터 9까지 표기 되어 있습니다. 고객이 언제 구매하였던 간에 처음 들어온 기간은 0, 두 번째 기간은 1, 세 번째 기간은 2, 네 번째 기간은 3으로 표기합니다.

모든 기간을 종합해보면, 첫 번째 코호트(y축의 첫 번째)에 N번의 기간이 있다고 가정하면 두 번째 코호트에는 (N-1)번, 세 번째 코호트에는 (N-2)번, ... 마지막 코호트에는 기간이 1번 생성되어야 합니다. 그렇다면 실습 데이터도 이러한 형식을 갖추었는지 살펴보도록 하겠습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

첫 주문(동일한 경험) 데이터가 있는 데이터프레임의 FirstOrder칼럼에 value_counts함수를 사용하여 unique value별로 카운팅 한 후, sort_index함수를 사용하여 인덱스를 오름차순 정렬하여 살펴보면 위의 결과와 같습니다.

그런데 첫 번째 코호트 기간은 15번으로 구성되어 있기 때문에 두 번째 코호트 기간은 15-1= 14여야 하는데 13인것을 확인할 수 있습니다. 그 외의 데이터를 살펴보면 13,12,11,10... 등 정상적으로 처리되어 있는 것을 확인할 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

첫 방문일자가 '2009-02'인 데이터를 좀 더 구체적으로 확인하기 위하여 불리언으로 데이터를 선택해보면 OrderPeriod가 2010-03인 데이터가 없는 것을 확인할 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

다른 코호트의 데이터도 살펴보면 위 표와 같이 OrderPeriod가 2010-03인 데이터가 있는 것을 살펴볼 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

데이터가 없는 기간도 포함하여 코호트 분석을 진행하기 위하여 해당기간의 FirstOrder와 OrderPeriod를 입력하고 TotalUsers에 0을 입력합니다. 그리고 sort_values함수로 전체 데이터의 순서를 정렬해 줍니다. 그리고 첫 방문일자가 '2009-02'인 데이터를 다시 한 번 확인해보면 데이터가 올바로 추가된 것을 확인할 수 있습니다.

현업에서 다루는 데이터도 이와 같이 모종의 이유(서버 혹은 운영의 문제)로 데이터가 없을 수 있습니다. 이러한 경우 전체적인 데이터처리가 꼬이게 되는데 위와 같은 방법으로 데이터를 확인하고 전처리할 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

다시 한 번 전체 데이터를 확인해보면 정상적으로 전처리 된 것을 확인할 수 있습니다.

6. 기간별 레이블 붙이기

5항 서두에서 알아본 것과 같이, 코호트 분석에서 처음 들어온 기간은 0, 두 번째 기간은 1, 세 번째 기간은 2, 네 번째 기간은 3으로 표기합니다. 우리가 실습하고 있는 데이터에도 이러한 방식으로 숫자 레이블을 붙여야 합니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

each_period 변수에는 15부터 0까지의 숫자가 나열되어 있습니다. 이를 중첩for문을 사용하여 기간을 생성하고 cohortperiod라는 리스트에 할당합니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

그리고 이를 원래의 cohort 변수에 CohortPeriod 칼럼으로 만들고 데이터를 확인해보면 레이블이 차례대로 입력된 것을 확인할 수 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

그리고 이번에는 FirstOrder(동일한 경험)와 CohortPeriod(동일한 기간)으로 인덱스로 만들어줍니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

이 때 unstack(1)을 하게되면 생성된 멀티인덱스 중 두 번째 인덱스(CohortPeriod)가 칼럼으로 변경되고, 그 결과 y축은 코호트, x축은 기간으로 표현되는 코호트 분석의 형태를 갖추게 됩니다.

7. 코호트별 사용자 유지율 구하기

우리가 흔히 접하는 코호트 분석에는 숫자가 아닌 비율로 표현되는 경우가 많습니다. 따라서 본 포스팅에서도 비율로 코호트 분석을 진행해보겠습니다.

그런데 여기에서 말하는 비율의 의미에 대해 생각해보면, 처음의 순방문자 수에 비해 각 기간의 순방문자수가 얼마나 변화하였는지에 대한 것입니다. 따라서 비율을 구하려면 전체 데이터를 첫 코호트 기간의 순방문자로 나누어주면 됩니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

cohorts[0]을 입력하면 cohorts의 첫 번째 칼럼을 선택하게 되고, 이 칼럼은 각 코호트 첫 번째 기간(0주)에 대한 데이터로 구성되어 있습니다.

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

따라서 위 처럼 코딩하여 전체 데이터(cohorts)를 첫 코호트 기간의 순방문자(cohorts[0])로 나누어(divide) 주면 됩니다. 이때, divide 함수에 axis=0을 명시해야 전체 데이터를 첫 코호트 기간의 데이터로 나눌 수 있습니다.

8. 코호트 시각화

powered by Advanced iFrame free. Get the Pro version on CodeCanyon.

시각화 라이브러리 Seaborn을 사용하면 분석에 대한 결과를 시각적으로 표현할 수 있습니다. 코호트 분석의 시각화에는 히트맵을 그려주는 heatmap 함수가 사용됩니다. 이때 annot 매개변수는 각 데이터를 히트맵상에 표기할 것인지를 불리언으로 결정합니다. 또 fmt매개변수는 숫자 표시형식인데, 입력된 .0%는 백분율로 표현하되, 1의 자리까지 표현하라는 뜻입니다.

이렇게 코호트 분석을 파이썬으로 진행해보았습니다. 코호트 분석은 현업에서 할 수 있는 여러 분석방법 중 유용하게 사용하실 수 있는 방법입니다. 준비된 코드를 사용하시어 현업에 많은 도움이 되시기 바랍니다.

1 thought on “파이썬으로 코호트분석하기”

Leave a Comment