์ด๋ฒ ํฌ์คํ ์์๋ 5์ ๊ณ ๊ฐ๊ตฐ ๋ถ์์ ์ด์ด, ์ฝํธํธ ๋ถ์์ ์งํํ๋ค.
Cohort Analysis
์ฝํธํธ๋ ์ด๋ค ๊ณตํต์ ์ ๊ณต์ ํ๋ ์ฌ๋๋ค์ ๊ทธ๋ฃน์ ์๋ฏธํ๋ค.
์ด๋ฌํ ๊ณตํต์ ์ ์ฑ ๊ฐ์ ๋ ์ง, ์ฒ์ ๊ตฌ๋งคํ ๋ฌ, ์ง๋ฆฌ์ ์์น, ํ๋ ์ฑ๋ (์ผ๋ฐ ์ฌ์ฉ์, ๋ง์ผํ ์ ์ ์ ๋ฑ) ๋ฑ์ด ๋ ์ ์๋ค.
์ฝํธํธ ๋ถ์์์๋ ์ด๋ฌํ ์ฌ์ฉ์ ๊ทธ๋ฃน์ ์๊ฐ์ ๋ฐ๋ผ ์ถ์ ํ์ฌ ์ผ๋ฐ์ ์ธ ํจํด์ด๋ ํ๋์ ์๋ณํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
๋ณธ ์์ ์์๋ ์ฝํธํธ ๋ถ์ ํจ์๋ฅผ ์ ์ํ์ผ๋ฉฐ, ํจ์๊ฐ ๊ธด ๊ด๊ณ๋ก ๋์ด์ ์ค๋ช ํ๊ณ ๋ง์ง๋ง์ ์ต์ข ํจ์๋ฅผ ๊ธฐ๋กํ ๊ฒ์ด๋ค.
cohort(์ต์ด ์ฃผ๋ฌธ์ผ๊ณผ ๊ณ ๊ฐ ๋น ์ฃผ๋ฌธ ๊ฑด์ ๋ ์ง ์ถ์ถ)
- ๋ฐ์ดํฐ ํ๋ ์์ ๋ณต์ฌ
- ๊ณ ๊ฐ ID, ์ก์ฅ๋ฒํธ, ์ฃผ๋ฌธ๋ ์ง๋ง ์ถ์ถํ๊ณ , ์ค๋ณต๋ ํ ์ ๊ฑฐ
- ๋ ์ง๋ฅผ ์ ๋จ์์ ๊ธฐ๊ฐ(Period)์ผ๋ก ๋ณํ : ๊ฐ ์ฃผ๋ฌธ์ ๋ ์ง๋ฅผ ํด๋น ์์ ์ฒซ ๋ฒ์งธ ๋ ๋ก ๋ณํํ๊ณ ํด๋น ์์ ๋ํ๋ด๋ ๊ธฐ๊ฐ์ผ๋ก ํํ
- ๊ณ ๊ฐ ID๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ทธ๋ฃนํ :
- ๊ฐ ๊ณ ๊ฐ์ ๋ํด, ์ฃผ๋ฌธ๋ ์ง(InvoiceDate)์ด์ ์ต์๊ฐ(๊ฐ์ฅ ์ด๋ฅธ ์ฃผ๋ฌธ ๋ ์ง)์ ์ฐพ๋๋ค.
- ๊ฐ์ฅ ์ด๋ฅธ ์ฃผ๋ฌธ ๋ ์ง๋ฅผ ์ ๋จ์ ๊ธฐ๊ฐ์ผ๋ก ๋ณํ
- cohort ์ด๊ณผ order_month ์ด์ ๊ธฐ์ค์ผ๋ก ๊ทธ๋ฃนํ :
- ๊ฐ ๊ทธ๋ฃน์ ๋ํด ๊ณ ์ ํ ๊ณ ๊ฐID์ ์์ ๊ณ์ฐํ์ฌ n_customers ์ ์ ์ฅ
def CohortAnalysis(dataframe):
data = dataframe.copy()
data = data[["CustomerID", "InvoiceNo", "InvoiceDate"]].drop_duplicates()
data['order_month'] = data['InvoiceDate'].dt.to_period('M')
data['cohort'] = data.groupby('CustomerID')['InvoiceDate'].transform('min').dt.to_period('M')
cohort_data = (
data.groupby(['cohort', 'order_month']).agg(n_customers = ('CustomerID', 'nunique'))\
.reset_index(drop = False)
)
์ต์ด ์ฃผ๋ฌธ์ผ๊ณผ ์ฃผ๋ฌธ ๊ฑด๋ณ ์ผ์ ์ฐจ์ด ๊ณ์ฐ
- order_month ์ cohort ์ ๋ ์ง ์ฐจ์ด๋ฅผ ๊ณ์ฐํ๋ .apply(attrgetter('n')) ํจ์๋ฅผ ์ ์ฉํ์ฌ ๊ฐ์ฒด์์ n ์์ฑ ๊ฐ์ ์ถ์ถํ๋ค.
- attrgetter๋ ํ์ด์ฌ์ operator ๋ชจ๋์์ ์ ๊ณตํ๋ ํจ์ ์ค ํ๋์ด๋ค.
from operator import attrgetter
cohort_data['period_number'] = (cohort_data.order_month - cohort_data.cohort).apply(attrgetter('n'))
pivot_table ๋ก ์ฝํธํธ(์ต์ด ๊ตฌ๋งค์ผ) ๊ธฐ์ค, ๊ฒฝ๊ณผ ์๊ฐ ๋ณ ๊ตฌ๋งค ๊ณ ๊ฐ ์ ๊ณ์ฐ
cohort_pivot = cohort_data.pivot_table(
index = 'cohort', columns = 'period_number', values = 'n_customers'
)
# ์ฝํธํธ ์ด๊ธฐ ๊ณ ๊ฐ์
cohort_size = cohort_pivot.iloc[:, 0]
๊ณ ๊ฐ ์ ์ง์จ ๊ณ์ฐ
- ํผ๋ฒํ
์ด๋ธ์ ๊ฐ ํ์ 'cohort_size' ๋ณ์๋ก ๋๋์ด, ๊ณ ๊ฐ ์ ์ง์จ(์ดํ์จ ํ์
์ฉ) ๊ณ์ฐ
- divide() ํจ์๋ ํ์ ๋๋ ๋ ์ฌ์ฉ๋๋ฉฐ, axis = 0 ๋งค๊ฐ๋ณ์๋ก ๊ฐ ํ์ ๋๋๊ณ ์์์ ๋ํ๋ธ๋ค.
- ์ด๋ ๊ฒ ๊ฐ cohort์ ๋ํ ์ดํ๋ฅ ์ด ๊ณ์ฐ๋๋ฉฐ, ๊ฒฐ๊ณผ๊ฐ retention_matrix ๋ณ์์ ์ ์ฅ๋๋ค.
retention_matrix = cohort_pivot.divide(cohort_size, axis = 0)
๐ ๊ณ ๊ฐ ์ ์ง์จ ์๊ฐํ(heatmap)
- with sns.axes_style('white') : ๋ฐฐ๊ฒฝ์ ํฐ์์ผ๋ก
- fig, ax ~ : sharey = True (๋ ๊ฐ์ ํ์ ๊ทธ๋ฆผ์ด ๋์ผํ y-์ถ์ ๊ณต์ )
- gridspec_kw = {'width_ratios':[0.1, 1]} : ๋ ๊ทธ๋ฆผ์ ๋๋น ๋น์จ ์ค์
- ax[1] ํํธ๋งต : retention_matrix ํ์ฉํ๊ณ , null ๊ฐ์ ๊ฐ๋ฆผ
- white_cmap ์์ฑ : ๋ฆฌ์คํธ๋ก ์ง์ ํ ์ปฌ๋ฌ๋ก colormap ๋ง๋ค๊ธฐ
- import matplotlib.colors as mcolors
- mcolors.ListedColormap() ํจ์
- cohort_size ์ธ๋ฑ์ค์ ๊ฐ์ ๋ฐ์ดํฐํ๋ ์์ผ๋ก ๋ณํํ์ฌ ํํธ๋งต ์ผ์ชฝ์ ์ถ๊ฐ
- fmt = 'g' : ์ฃผ์์ ์ซ์ ํ์์ ์ผ๋ฐ ์ซ์ ํ์(general)๋ก ์ง์
- ์๋ฅผ ๋ค์ด, fmt='g'๋ก ์ค์ ๋ ๊ฒฝ์ฐ, ์ซ์ 1000์ "1000"์ผ๋ก ํ์๋๊ณ , ์ซ์ 0.001์ "0.001"๋ก ํ์๋จ!
with sns.axes_style('white'): # ๋ฐฐ๊ฒฝ์ ํฐ์์ผ๋ก ์ค์
fig, ax = plt.subplots(
1, 2, figsize = (12, 8), sharey = True, gridspec_kw = {'width_ratios':[0.1, 1]}
)
sns.heatmap(retention_matrix,
mask = retention_matrix.isnull(),
annot = True,
cbar = True,
fmt = '.0%',
cmap = 'coolwarm',
ax = ax[1])
ax[1].set_title("Monthly Cohorts: User Retention", fontsize=14)
ax[1].set(xlabel='# of periods', ylabel = " ")
white_cmap = mcolors.ListedColormap(['white'])
sns.heatmap(pd.DataFrame(cohort_size).rename(columns = {0:'cohort_size'}),
annot = True, cbar = False, fmt = 'g', cmap = white_cmap, ax = ax[0])
fig.tight_layout()
๐ ๊ณ ๊ฐ ์ ์ง์จ ์๊ฐํ ์ ์ฒด ํจ์
ํผ์ณ๋ณด์ธ์!
๋๋ณด๊ธฐ
def CohortAnalysis(dataframe):
data = dataframe.copy()
data = data[["CustomerID", "InvoiceNo", "InvoiceDate"]].drop_duplicates()
data['order_month'] = data['InvoiceDate'].dt.to_period('M')
data['cohort'] = data.groupby('CustomerID')['InvoiceDate'].transform('min').dt.to_period('M')
cohort_data = (
data.groupby(['cohort', 'order_month']).agg(n_customers = ('CustomerID', 'nunique'))\
.reset_index(drop = False)
)
cohort_data['period_number'] = (cohort_data.order_month - cohort_data.cohort).apply(attrgetter('n'))
cohort_pivot = cohort_data.pivot_table(
index = 'cohort', columns = 'period_number', values = 'n_customers'
)
cohort_size = cohort_pivot.iloc[:, 0]
# ๊ณ ๊ฐ ์ดํ์จ/์ ์ง์จ ๊ณ์ฐ
retention_matrix = cohort_pivot.divide(cohort_size, axis = 0)
# ์๊ฐํ
with sns.axes_style('white'): # ๋ฐฐ๊ฒฝ์ ํฐ์์ผ๋ก ์ค์
# ๋ ๊ฐ์ ํ์ ๊ทธ๋ฆผ์ด ๋์ผํ y-์ถ์ ๊ณต์ (sharey = True) / ํ์ ๊ทธ๋ฆผ์ ๋๋น ๋น์จ(๋์ผ)
fig, ax = plt.subplots(
1, 2, figsize = (12, 8), sharey = True, gridspec_kw = {'width_ratios':[0.1, 1]}
)
sns.heatmap(retention_matrix,
mask = retention_matrix.isnull(),
annot = True,
cbar = True,
fmt = '.0%',
cmap = 'coolwarm',
ax = ax[1])
ax[1].set_title("Monthly Cohorts: User Retention", fontsize=14)
ax[1].set(xlabel='# of periods', ylabel = " ")
white_cmap = mcolors.ListedColormap(['white'])
sns.heatmap(pd.DataFrame(cohort_size).rename(columns = {0:'cohort_size'}),
annot = True, cbar = False, fmt = 'g', cmap = white_cmap, ax = ax[0])
fig.tight_layout()
728x90
'Machine Learning > Case Study ๐ฉ๐ปโ๐ป' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[BG/NBD] ๊ณ ๊ฐ ๊ฑฐ๋ ํ๋ ์์ธก ๋ชจ๋ธ (2) | 2023.10.10 |
---|---|
[Kaggle] ์ด์ปค๋จธ์ค ๋ฐ์ดํฐ ๋ถ์ 7 (CRM Analytics ๐๏ธ๐) (1) | 2023.10.10 |
[Kaggle] ์ด์ปค๋จธ์ค ๋ฐ์ดํฐ ๋ถ์ 5 (CRM Analytics ๐๏ธ๐) (1) | 2023.10.08 |
[Kaggle] ์ด์ปค๋จธ์ค ๋ฐ์ดํฐ ๋ถ์ 4 (CRM Analytics ๐๏ธ๐) (1) | 2023.10.08 |
[Kaggle] ์ด์ปค๋จธ์ค ๋ฐ์ดํฐ ๋ถ์ 3 (CRM Analytics ๐๏ธ๐) (1) | 2023.10.08 |