데이터 분석 5-4 탐색적 데이터 분석(3)

addison·2022년 5월 14일
0

데이터 분석

목록 보기
44/48

탐색적 데이터 분석 (3)

4) 이용 이력 데이터로부터 정기 이력 플래그 작성

스포츠 센터의 경우에 지속 요소 중 하나로 습관을 생각할 수 있습니다. 여기서는 정기적으로 센터를 이용하는 고객을 특정해봅시다. 정기적이라는 것은 정의하는 방법에 따라 다르지만, 여기서는 매주 같은 요일에 왔는지 아닌지로 판단합니다.

월별 정기적 이용 여부는 고객에 따라 다르겠지만, 여기서는 고객마다 월/요일별로 집계하고 최댓값이 4이상인 요일이 하나라도 있는 회원은 플래그를 1로 처리합니다.

먼저, 고객마다 월/요일별로 집계합니다.

# 요일을 숫자로 변환. 0에서부터 6까지의 숫자가 각각 월요일부터 일요일에 해당.
uselog["weekday"] = uselog["usedate"].dt.weekday

# 고객, 연월, 요일별로 log_id를 카운트.
uselog_weekday = uselog.groupby(["customer_id","연월","weekday"], 
                                as_index=False).count()
del uselog_weekday['usedate']
uselog_weekday.rename(columns={"log_id":"count"}, inplace=True)
uselog_weekday.head()

>>>>

출력된 결과를 보면, 회원 AS002855는 2018년 4월, weekday 5(토요일)에 4번, 2018년 5월에도 토요일에 4번 스포츠 센터에 왔으므로 매주 토요일은 체육관에 오는 날로 생각하는 것 같습니다.
그럼 고객별로 최댓값을 계산하고, 그 최댓값이 4이상인 경우에 플래그를 지정해봅시다.
where 이라는 새로운 함수가 나오는데 전혀 어렵지 않습니다!

where(조건문, 해당 조건을 '만족하지 않으면' 여기 적은 값으로 변경)

# 고객 단위로 집계하고 최댓값을 구합니다. 
uselog_weekday = uselog_weekday.groupby("customer_id",as_index=False).max()

del uselog_weekday['연월']
del uselog_weekday['weekday']

# routine_flg에 0을 입력하고
uselog_weekday["routine_flg"] = 0

#  횟수가 4미만인 경우는 원래의 값인 0을 그대로 두고 4 이상인 경우에만 1을 대입합니다.
uselog_weekday["routine_flg"] = uselog_weekday["routine_flg"].where(uselog_weekday["count"]<4, 1)
uselog_weekday.head()

1행에서 고객 단위로 집계하고 최댓값을 구합니다. 다시 말해, 특정 월, 특정 요일에 가장 많이 이용한 횟수입니다. 이 횟수가 4 또는 5인 사람은 적어도 어떤 달의 매주 특정 요일에 정기적으로 방문한 고객입니다.

2행에서는 routine_flg에 0을 입력하고, 3행에서는 횟수가 4미만인 경우는 원래의 값인 0을 그대로 두고 4 이상인 경우에만 1을 대입합니다.

결과를 보면 count가 4이상인 고객은 플래그에 1이 들어 있는 것을 알 수 있습니다.

이렇게 플래그 작성이 완료됐습니다. 다음으로, 고객 데이터와 결합해서 최대 이력을 포함한 고객 데이터를 수정합시다.

5) 고객 데이터와 이용 이력 데이터의 결합

uselog_customer, uselog_weekday를 customer_join과 결합합니다.

customer_join = pd.merge(customer_join, uselog_customer, on="customer_id", how="left")
customer_join = pd.merge(customer_join, uselog_weekday[["customer_id", "routine_flg"]], on="customer_id", how="left")
customer_join.head()

>>>>>>>>>>>>>>>>>

두 번에 걸쳐 결합했으며, 결합에 사용한 조인키는 customer_id, 결합 방법은 레프트 조인입니다. 결과를 보면, 앞에서 집계한 데이터와 routine_flg가 결합돼 있는 것을 알 수 있습니다.
2행에서는 결합할 데이터를 uselog_weekday의 customer_id와 routine_flg로 한정했습니다.
만약을 위해 결측치도 확인해둡시다

customer_join.isnull().sum()

>>>>>>>>>>>>>>>

customer_id         0
name                0
class               0
gender              0
start_date          0
end_date         2842
campaign_id         0
is_deleted          0
class_name          0
price               0
campaign_name       0
mean                0
median              0
max                 0
min                 0
routine_flg         0
dtype: int64

코드를 실행했을 때 end_date 이외에는 결측치가 없는 것을 보아 결합이 문제 없다는 것을 확인했습니다. 드디어, 이용 이력도 추가되어 고객 분석이 가능해졌습니다. 이용 이력인 시간적인 변화 데이터를 추가했기 때문에 분석을 시작하기 전에 회원 기간 칼럼을 하나 더 추가해둡시다

6) 회원 기간을 계산해서 열로 추가하기

이번에는 회원 기간을 계산해서 열로 추가합시다.

회원 기간은 단순하게 start_date와 end_date의 차이입니다. 다만, 2019년 3월까지 탈퇴하지 않은 회원은 end_date에 결측치가 들어있기 때문에 그 차이를 계산할 수 없습니다. 그래서 탈퇴하지 않은 회원은 2019년 4월 30일로 채워서 회원 기간을 계산합니다.

2019년 3월 31일로 계산할 경우, 실제로 2019년 3월 31일에 탈퇴한 사람(2월 말까지 탈퇴 신청을 한 사람은 원래 2019년 3월 31일이 탈퇴일입니다.)과 구별할 수 없기 때문입니다.

그럼 기간을 계산해봅시다. 여기서는 월 단위로 집계합니다.

▶ [코드스니펫] 회원 기간 계산

# 날짜 비교 함수 relativedelta를 사용하기 위해 라이브러리를 임포트
from dateutil.relativedelta import relativedelta

# date 부분 다 datetime 타입으로 변경
customer_join["start_date"] = customer_join["start_date"].apply(pd.to_datetime)
customer_join["end_date"] = customer_join["end_date"].apply(pd.to_datetime)

# 날짜 계산용 열을 end_date를 초기값으로 하여 추가.
customer_join["calc_date"] = customer_join["end_date"]

# 결측치에 2019년 4월 30일을 대입
customer_join["calc_date"] = customer_join["calc_date"].fillna(pd.to_datetime("20190430"))

# 날짜 비교 함수 relativedelta를 사용.
# cal_date와 start_date의 차이를 계산 후에 membership_period에 회원 기간을 월 단위 추가
customer_join["membership_period"] = 0
for i in range(len(customer_join)):
    delta = relativedelta(customer_join["calc_date"][i], customer_join["start_date"][i])
    customer_join["membership_period"][i] = delta.years*12 + delta.months
customer_join.head()

>>>>>

회원 기간을 월 단위로 계산합니다. 이렇게 회원 기간 열을 추가합니다


탐색적 데이터 분석 (4) - 인사이트 도출

7) 고객 행동의 각종 통계량 파악

데이터 가공으로 추가한 mean, median, max, min을 describe를 이용해서 파악합니다.

.describe() 는 각 항목별 개수, 평균, 표준편차 등을 출력해주는 함수입니다.

customer_join[["mean", "median", "max", "min"]].describe()

>>>>>>>>>>>>>>>>>>>>

코드를 실행하면 개수, 평균값 등이 표시됩니다.

여기서 사용한 열의 이름이 mean, median, max, min이라서 헷갈리기 쉬우니 주의 합시다.

열 이름 mean은 고객의 매월 평균 이용 횟수이며, 행에 있는 mean은 고객의 매월 평균 이용 횟수의 평균입니다. 다시 말해 표시된 값은 한 사람당 매월 평균 이용 횟수입니다. 평균값, 중앙값에는 큰 차이가 없으며, 고객 1명당 이용 횟수는 약 5번 정도인 것을 알 수 있습니다.

계속해서 routine_flg도 집계해봅시다. routine_flg는 flg마다 고객 수를 집계합니다.

customer_join.groupby("routine_flg")["customer_id"].count()

>>>>>>>>>>>>>

routine_flg
0     779
1    3413
Name: customer_id, dtype: int64

코드를 실행하면 0이 779이고 1이 3413으로, 정기적으로 이용하는 회원의 수가 많다는 것을 알 수 있습니다.
마지막으로 회원 기간(membership_period)의 분포를 살펴봅시다. matplotlib을 사용해서 히스토그램을 작성합니다.

import matplotlib.pyplot as plt

plt.hist(customer_join["membership_period"])

>>>>>>>>>>>>>>>>>>>

코드를 실행하면 히스토그램이 표시됩니다. 회원 기간이 10개월 이내인 고객이 많고, 10개월 이상의 고객 수는 거의 일정한 것을 알 수 있습니다. 이것은 짧은 기간에 고객이 빠져나가는 업계라는 것을 시사합니다.

그러면 탈퇴하는 회원은 어떤 특징을 가지는지 살펴봅시다.

8) 탈퇴 회원과 지속 회원의 차이를 파악하자

탈퇴 회원의 특징을 찾아봅시다. 탈퇴 회원과 지속 회원으로 나눠서 비교를 해봅시다.

앞서 파악한 탈퇴 회원과 지속 회원의 수는 각각 1,350명과 2,840명입니다.

# is_delete 열의 값이 1이면 탈퇴 회원만 필터링
customer_end = customer_join[customer_join["is_deleted"]==1]
customer_end.describe()

# is_deleted 열이 0이면 지속 회원만 필터링
customer_stay = customer_join[customer_join["is_deleted"]==0]
customer_stay.describe()

>>>>>>>>>>>>>>>>>>>>>>>>

결과를 보면 탈퇴 회원의 매월 이용 횟수의 평균값, 중앙값, 최댓값, 최솟값은 모두 지속 회원보다 작습니다. 특히, 평균값과 중앙값은 1.5배 정도 차이가 나는 것을 알 수 있습니다.

반면에 매월 최대 이용 횟수의 평균값은 지속 회원이 높지만, 탈퇴 회원도 6.4 정도입니다.

routine_flg의 평균값은 차이가 크게 나서 지속 회원은 0.98로 많은 회원이 정기적으로 이용하고 있다는 것을 알 수 있지만, 탈퇴 회원은 0.45로 거의 절반은 랜덤하게 이용하고 있다고 생각할 수 있습니다.

이렇게 탈퇴 회원과의 차이를 확인할 수 있으며, 기간을 줄이거나 회원의 재적 기간별로 조사해 나가면 좀 더 많은 것이 보일 것으로 생각됩니다.

마지막으로 여기까지 사용한 customer_join을 csv로 출력해둡시다.


customer_join.to_csv("customer_join.csv", index=False)customer_join.to_csv("customer_join.csv", index=False)

머신 러닝의 성능은 어떤 데이터로 학습시킬 것인지가 좌우한다고 해도 과언이 아닙니다. 그래서 데이터의 선택을 위해서 데이터의 주요 특성이 될만한 변수를 잘 파악해야 합니다.

0개의 댓글