본문 바로가기
Analysis/Example

스포츠센터 회원 분석 - 클러스터링, 회귀분석

by 5ole 2021. 1. 30.

1. 전제조건 

  • 스포츠센터 고객분석 데이터 사용
  • 고객별 이용 횟수 등의 예측

2021/01/30 - [Data Analysis] - 스포츠센터 회원 분석 - 데이터 가공, 통계량 파악

 

스포츠센터 고객분석

1. 전제조건 (1) 3가지의 회원권 종류 종일회원 : 언제든 사용할 수 있음 주간회원 : 낮에만 사용가능 야간회원 : 밤에만 사용가능 (2) 입회비 일반적으로는 입회비 비용 있음 비정기적으로 입회비

5ohyun.tistory.com

 

2. 데이터 정보

  • use_log.csv
  • customer.csv
import os
import pandas as pd
import matplotlib.pyplot as plt

os.chdir('C:\\Users\\leeso\\Downloads\\pyda100-master\\3장')

use_log=pd.read_csv('use_log.csv')
customer=pd.read_csv('customer.csv')

 

3. Kmeans 클러스터링

 

(1) 이용 이력을 통해 그룹화

  • 변수는 고객의 한달 사용 이력 데이터 (mean, median, max, min, customer_period)
customer_clustering = customer[['mean', 'median', 'max', 'min', 'customer_period']]

 

 

(2) 표준화 및 KMeans

  • customer_period가 큰 수로 결과를 좌지우지할 수 있기에 표준화 진행
  • KMeans 클러스터 개수는 4로 설정
# 표준화
sc= StandardScaler()
customer_clustering_sc = sc.fit_transform(customer_clustering)

# KMeans 클러스터링
kmeans = KMeans(n_clusters=4, random_state=0)
clusters = kmeans.fit(customer_clustering_sc)
customer_clustering['cluster'] = clusters.labels_

customer_clustering['cluster'].unique() # 3 1 0 2

 

 

(3) 클러스터링 결과 보기

  • 그룹 0 > 그룹 3 > 그룹 2 > 그룹 1
  • 그룹별로 나타나는 특징 시각화 필요
customer_clustering.groupby('cluster').count()

customer_clustering.groupby('cluster').mean()

 

클러스터별 count
클러스터별 통계량

 

4. 클러스터링 시각화

  • 5개의 변수를 2차원으로 나타내기 위해 차원 축소 (PCA)
from sklearn.decomposition import PCA

# PCA 차원축소
X = customer_clustering_sc
pca = PCA(n_components=2)
pca.fit(X)
x_pca = pca.transform(X)
pca_df = pd.DataFrame(x_pca)
pca_df['cluster'] = customer_clustering['cluster']

# 시각화
for i in pca_df["cluster"].unique():
    clus=pca_df.loc[pca_df['cluster']==i]
    plt.scatter(clus[0],clus[1])

 

5. 클러스터링 결과 파악

 

(1) 그룹에서 탈퇴회원과 지속회원 비교 

  • 0은 골고루, 지속회원이 많음
  • 1은 탈퇴회원만 존재
  • 2는 지속회원이 다수 존재 (회원기간이 짧음) - 초반 의욕적인 집단
  • 3도 지속회원이 대다수 (회원기간이 김) - 안정적인 집단
customer_deleted=pd.concat([customer_clustering,customer['is_deleted']], axis=1)

customer_deleted = customer_deleted.groupby(['cluster','is_deleted'],as_index=False).count()[['cluster','is_deleted','customer_period']]
customer_deleted.rename(columns={'customer_period':'count'},inplace=True)

 

 

(2) 그룹에서 루틴이 있는 회원 비교

  • 0은 지속회원이 좀 더 비중을 차지하며, 루틴이 있는 회원이 대다수
  • 1은 탈퇴회원만 존재 - 루틴이 없는 회원이 다수
  • 2는 지속회원이 다수 존재 (회원기간이 짧음) - 초반 의욕적인 집단, 루틴이 대다수로 있음
  • 3도 지속회원이 대다수 (회원기간이 김) - 안정적인 집단, 루틴이 대다수가 있음

 

6. 다음 달 이용횟수 예측 - 회귀분석 변수 만들기

 

(1) 손님마다 해당연월에 온 횟수 count

use_log.dtypes

use_log['usedate']=pd.to_datetime(use_log['usedate'])
use_log['useYm']=use_log['usedate'].dt.strftime('%Y%m')
customer_ym_use=use_log.groupby(['useYm','customer_id'],as_index=False).count()
del customer_ym_use['log_id']
customer_ym_use.rename(columns={'usedate':'count'},inplace=True)

 

 

(2) 회귀분석을 위해 데이터 시간별로 차곡차곡 쌓기 ( y와 1달전부터 6개월전 데이터인 X )

  • pred_count를 y로, count_0이 pred_count 에서 1달전이고 count_5가 6개월전 달이다.
ym = list(customer_ym_use['useYm'].unique())
predict_data = pd.DataFrame()
for i in range(6,len(ym)) :
    tmp=customer_ym_use.loc[customer_ym_use['useYm']==ym[i]]
    tmp.rename(columns={'count':'pred_count'},inplace=True)
    for j in range(1,7) :
        tmp_before = customer_ym_use.loc[customer_ym_use['useYm']==ym[i-j]]
        del tmp_before['useYm']
        tmp_before.rename(columns={'count':'count_{}'.format(j-1)},inplace=True)
        tmp = pd.merge(tmp,tmp_before,on='customer_id',how='left')
    predict_data = pd.concat([predict_data,tmp],ignore_index=True)
    

 

 

(3) NA값 처리

  • 6개월 전 달이 없는 경우는 등록한지 6개월이 안된 회원이라 null값

(4) 변수 추가 생성

  • 회원 기간을 추가해 시계열 변화 볼 수 있음
# start_date 변수 추가
predict_data2= pd.merge(predict_data, customer[['customer_id','start_date']],on='customer_id',how='left')
predict_data2.isnull().sum()

# y값 - start_date 기간 구하기
from dateutil.relativedelta import relativedelta
predict_data2.dtypes
predict_data2['start_date'] = pd.to_datetime(predict_data2['start_date'])
predict_data2['useYm'] = pd.to_datetime(predict_data2['useYm'],format='%Y%m')
predict_data2['customer_period']=0

for cus in range(len(predict_data2)) :
    delta_days = relativedelta(predict_data2['useYm'].iloc[cus], predict_data2['start_date'].iloc[cus])
    predict_data2['customer_period'].iloc[cus] = delta_days.years*12 + delta_days.months #월단위계산
    

 

 

 

7. 다음 달 이용횟수 예측 - 회귀분석 모델

 

(1) 전체 가입 회원

  • 낮은 정확도
from sklearn import linear_model
import sklearn.model_selection

model = linear_model.LinearRegression()
X=predict_data2[['count_0','count_1','count_2','count_3','count_4','count_5','customer_period']]
y=predict_data2['pred_count']
X_train,X_test,y_train,y_test = sklearn.model_selection.train_test_split(X,y)
model.fit(X,y)


model.score(X_train,y_train)
model.score(X_test,y_test)

 

 

(2) 2018/04 이후에 가입한 회원만 이용

  • 오래전부터 있던 회원은 가입시기 데이터가 존재하지 않거나 불확실 가능성 증가
predict_data2=predict_data2.loc[predict_data2['start_date']>=pd.to_datetime('20180401')]
X=predict_data2[['count_0','count_1','count_2','count_3','count_4','count_5','customer_period']]
y=predict_data2['pred_count']
X_train,X_test,y_train,y_test = sklearn.model_selection.train_test_split(X,y)
model.fit(X,y)


model.score(X_train,y_train)
model.score(X_test,y_test)

 

 

8.  회귀계수 확인

  • 1달 전을 나타내는 횟수가 다음 달의 이용횟수에 영향을 미치며
  • 과거로 갈수록 기여도가 낮아짐을 확인
pd.DataFrame({'Feature_name':X.columns,'coef':model.coef_})

 

 

9. 보완점

  • 변수들을 다양하게 만들어 시도해 볼 필요가 있음

+ 참고 자료 및 출처

 

댓글