RFM 분석하는 이유는?

고객별 RFM 3가지 지표들을 통해서 고객 점수 부여 및 등급화에 따른 서비스 등급을 부여합니다.
그리고 월마다 중요한 그룹에 대한 비중이 떨어지고 있는지 올라가고 있는지 확인 하는 것이 RFM 분석입니다.

즉, RFM 분석을 하게 되면 어떤 그룹에 타겟팅하여 마케팅할 지 정할 수 있게 됩니다.


1. 문제 정의

런칭 이후 서비스 정체기로 인한 영업이익, 사용 고객 수 감소

2. 해결방안

구매 데이터 활용 서비스 이용 현황 파악(지표 기획)

3. 기대 효과

정체 원인 파악 및 대응책 수립 및 실행을 통한 영업이익, 사용 고객 수 증가


🔈Process01

1. Data 전처리

1.1 Null값 확인

# ▶ Null 값 확인
print(df.isnull().sum())

코드 결과

코드 결과를 보니 두 개의 컬럼 값에서 Nan값이 확인 되었습니다.

저는 CustomerID가 Nan값이면 알 수 있는 방법이 없기 때문에 삭제하도록 하겠습니다.

 

1.2 Null값 삭제

# ▶ null value drop
# ▶ CustomerID 기준으로 Null value drop
df.dropna(subset=['CustomerID'], how='all', inplace=True)
df.isnull().sum()

코드 결과

CustomerID의 값을 삭제한 결과 Description의 Nan값 또한 같이 사라진 것을 확인 할 수 있습니다.

 

1.3 Outlier 확인

df.describe()

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use(['dark_background'])

sns.distplot(df['Quantity'])

코드 결과

describe()를 통해 평균 최대값 최소값 사분위수 확인 결과 최소값에 이상하게도 Quantity와 UnitPrice의 컬럼값에 음수가 있는 것을 확인 할 수 있었습니다. 

 

추가적으로 시각화 해본 결과 Outlier가 존재하는 것을 확인 할 수 있었습니다.

 

1.4 Outlier 삭제

df = df[df['UnitPrice']>0]
df = df[df['Quantity']>0]
df.describe()

코드 결과

음수 값이 Outlier였으므로 0보다 큰 수만 가져오면 Outlier를 없앨 수 있습니다. 그리고 Outlier 제거 후 확인 결과 깔끔하게 Outlier는 없어진 것을 볼 수 있습니다.

 

1.5 고객수, 총 구매 수량, 국가 그리고 평균 구매 건수 확인

df['CustomerID'].nunique(), df['Quantity'].sum(), df['Country'].nunique()

df.groupby('CustomerID')['InvoiceNo'].count().mean()

 

이용 고객수는 4338, 총 구매 수량은 5,167,812개, 국가는 37개국입니다.

그리고 인당 평균 구매 건수는 약 91개로 확인 되었습니다.


🔈Process02

지표 기획 및 데이터 추출 -> RFM 구하기

Recency(최근성)

우선 며칠의 데이터가 있는지 확인 해본 결과 2010-12-01 ~ 2011-12-09일 까지 약 1년 정도의 데이터가 있는 것을 확인하였습니다.

 

2.1 고객들의 마지막 구매일 구하고 Recency 구하기

# ▶ 고객ID별 가장 마지막 구매일
recency_df = df.groupby('CustomerID',as_index=False)['Date'].max()
recency_df.columns = ['CustomerID','LastPurchaseDate']

# ▶ 고객의 가장 마지막 구매일로 부터 몇일이 지났는지를 계산하기 위함
recency_df['Recency'] = recency_df['LastPurchaseDate'].apply(lambda x : (df['Date'].max() - x).days)
recency_df.drop(columns=['LastPurchaseDate'],inplace=True)

 

코드 결과

Recency를 구하기 위해 df['Date'].max()를 사용하여 가장 최근 날짜 기준을 구해줍니다. 그리고 고객들의 최근 구매를 빼주면 고객별 가장 마지막 구매일로 부터 며칠이 지났는지를 계산할 수 있습니다.

 

2.2 Recency 분포 확인

plt.style.use(['dark_background'])

sns.displot(data=recency_df, x="Recency")
plt.gcf().set_size_inches(16.5, 3)

코드 결과

최근에 구매한 고객들이 매우 많은 것으로 확인 되었습니다.

 

2.3 Frequency(최빈성) 구하기

frequency_df = df.copy()
frequency_df.drop_duplicates(subset=['CustomerID', 'InvoiceNo'], keep='first', inplace=True)
frequency_df = frequency_df.groupby('CustomerID', as_index=False)['InvoiceNo'].count()
frequency_df.columns = ['CustomerID', 'Frequency']
frequency_df.head()

코드 결과

고객ID와 송장번호를 기준으로 중복되는 값이 있는 경우 첫 번째 값만 제외하고 모두 제거해주면 고객이 여러 물품을 구매했어도 하나의 주문으로 셀 수 있게 만들수 있습니다.

 

그리고 groupby를 통해 고객ID로 묶어준 뒤 송장번호 개수를 세주면 고객별 구매빈도를 확인할 수 있습니다.

 

2.4 Monetary(금액) 구하기

# ▶ 구매금액 = 구매개수 * 구매단가
df['Total_cost'] = df['UnitPrice'] * df['Quantity']
monetary_df=df.groupby('CustomerID',as_index=False)['Total_cost'].sum()
monetary_df.columns = ['CustomerID','Monetary']
monetary_df.head()

구매 금액을 구하기위해 하나의 주문에 여러개의 수량일 수 있으므로 구매개수 * 구매 단가를 해줍니다.

그리고 고객ID를 groupby를 통해 묶어준 뒤 금액들을 모두 더해주면 고객별로 구매 금액을 측정할 수 있습니다.

 

2.5 RFM 테이블로 합쳐주기

# ▶ Data merge

# ▶ recency and frequency
rf = recency_df.merge(frequency_df,how='left',on='CustomerID')

# ▶ monetary

rfm = rf.merge(monetary_df,how='left',on='CustomerID')

rfm.head(5)

코드 결과

위에서 구한 R, F, M 테이블들을 고객ID를 기준으로 merge()해주면 테이블이 위의 이미지와 같이 깔끔하게 합쳐진 것을 볼 수 있습니다.


확실히 RFM을 또 공부하고 프로젝트를 시도해보니 훨씬 이해가 잘되고 깔끔하게 만들 수 있었습니다.

그리고 다음 글에서는 RFM을 이용하여 서비스 이용 수준 측정을 해볼 것입니다.

이 글은 제로베이스 데이터 분석 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.

이상입니다.

728x90
hmm06