์ด ํฌ์คํ ์ ์ด์ปค๋จธ์ค ๋ฐ์ดํฐ ๋ถ์ ๊ณผ์ ์ ์คํฐ๋ํ๊ธฐ ์ํด ๋ค์ kaggle ๋ ธํธ๋ฅผ ์ฐธ๊ณ ํ์ต๋๋ค.
https://www.kaggle.com/code/sercanyesiloz/crm-analytics
๋ผ์ด๋ธ๋ฌ๋ฆฌ import
import os
import datetime
# import squarify
import warnings
import pandas as pd
import numpy as np
import datetime as dt
from operator import attrgetter
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import plotly.graph_objs as go
from plotly.offline import iplot
from sklearn.metrics import (silhouette_score,
calinski_harabasz_score,
davies_bouldin_score)
from lifetimes import BetaGeoFitter, GammaGammaFitter
from lifetimes.plotting import plot_period_transactions
%matplotlib inline
%load_ext nb_black
warnings.filterwarnings('ignore')
sns.set_style('whitegrid')
palette = 'Set2'
๋ฐ์ดํฐ์ ๋ก๋ ๋ฐ ํ์ธ
๐ ์ฌ๊ธฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ฌ ๋ ์ต์ ์ ์ถ๊ฐ๋ก ์ค๋ค. ์ธ์ฝ๋ฉ๋ฟ๋ง ์๋๋ผ ๋ฐ์ดํฐ ํ์ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
- encoding='unicode_escape : ํน์๋ฌธ์๊ฐ ์๋ csv ํ์ผ์ ๋ํด ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์ธ์ฝ๋ฉ ๋ฐฉ์
- dtype = {'CustomerID':str, 'InvoiceDate':str} : ๊ฐ ์ปฌ๋ผ์ ๋ฌธ์์ด(str)๋ก ์ฒ๋ฆฌ
- parse_dates = ['InvoiceDate'] : InvoiceDate ์ด์ ๋ ์ง ๋ฐ ์๊ฐ ๊ฐ์ฒด๋ก ํ์ฑ ํ๋๋ก ์ง์(๋ฐ์ดํฐ ํ์ ๋ณ๊ฒฝ)
- infer_datetime_format = True : ์์ parse_dates์ ํจ๊ป ์ฌ์ฉ๋๋ฉฐ, InvoiceDate์ด์ ๋ ์ง ๋ฐ ์๊ฐ ํ์์ ์ถ๋ก ํ์ฌ ํ์ฑ ์๋๋ฅผ ํฅ์ํจ
df = pd.read_csv('./data.csv', encoding = 'unicode_escape',
dtype = {'CustomerID':str,
'InvoiceDate':str},
parse_dates = ['InvoiceDate'],
infer_datetime_format = True)
df.head()
๋ฐ์ดํฐ ๋ณ์ ํ์ธ
InvoiceNo: 6์๋ฆฌ๋ก ์ด๋ฃจ์ด์ง ์ก์ฅ ๋ฒํธ์
๋๋ค. ์ด ์ฝ๋๊ฐ 'c'๋ก ์์ํ๋ฉด ์ทจ์๋ ๊ฑฐ๋์์ ๋ํ๋
๋๋ค.
StockCode: 5์๋ฆฌ ์ซ์๋ก ์ด๋ฃจ์ด์ง ์ ํ ์ฝ๋์
๋๋ค.
Description: ์ ํ ์ด๋ฆ์
๋๋ค.
Quantity: ๊ฐ ์ ํ์ ๊ฑฐ๋๋น ์๋์
๋๋ค.
InvoiceDate: ๊ฐ ๊ฑฐ๋๊ฐ ์์ฑ๋ ๋ ์ง์ ์๊ฐ์ ๋ํ๋
๋๋ค.
UnitPrice: ์ ํ ๋จ๊ฐ์
๋๋ค.
CustomerID: 5์๋ฆฌ ์ซ์๋ก ์ด๋ฃจ์ด์ง ๊ณ ๊ฐ ๋ฒํธ์
๋๋ค. ๊ฐ ๊ณ ๊ฐ์ ๊ณ ์ ํ ๊ณ ๊ฐ ID๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
Country: ๊ฐ ๊ณ ๊ฐ์ด ๊ฑฐ์ฃผํ๋ ๊ตญ๊ฐ์ ์ด๋ฆ์
๋๋ค.
df.info()
๋ฐ์ดํฐ ์ฒดํฌํ๋ ํจ์ ์ ์ : check_data()
- rows, columns ๊ฐ์ ํ์ธ
- ์นผ๋ผ๋ณ ๋ฐ์ดํฐ ํ์
- head, tail
- ๊ฒฐ์ธก์น : df.isnull().sum()
- ์ค๋ณต๊ฐ
[์ฐธ๊ณ ]
โ center(width, fillchar)
์ด ๋ฉ์๋๋ ๋ฌธ์์ด์ ๊ฐ์ด๋ฐ ์ ๋ ฌํ๋ ๋ฐ ์ฌ์ฉ๋จ.
- width: ์ ๋ ฌ๋ ๊ฒฐ๊ณผ ๋ฌธ์์ด์ ์ ์ฒด ๋๋น๋ฅผ ๋ํ๋ด๋ฉฐ, ์ด ๊ฒฝ์ฐ์๋ 70์ด๋ค.
- fillchar: ํ์ํ ๊ฒฝ์ฐ ๋ฌธ์์ด์ ์ฑ์ธ ๋ฌธ์๋ฅผ ๋ํ๋ ๋๋ค. ์ด ๊ฒฝ์ฐ์๋ '-' ๋ฌธ์๊ฐ ์ฌ์ฉ๋๋ค
def check_data(df, head = 5):
print(" SHAPE ".center(70, '-'))
print('Rows: {}'.format(df.shape[0]))
print('Columns: {}'.format(df.shape[1]))
print(' Type '.center(70, '-'))
print(df.dtypes)
print(' HEAD '.center(70, '-'))
print(df.head(head))
print(' TAIL '.center(70, '-'))
print(df.tail(head))
print(' Missing Values '.center(70, '-'))
print(df.isnull().sum())
print(' Duplicated Values '.center(70, '-'))
print(df.duplicated().sum())
check_data(df)
World Map : ๋งค์ถ์ด ๋ฐ์ํ ๊ตญ๊ฐ ์๊ฐํ
์ง๋ ๊ตฌํ์ ์ํด pandas, plotly, plotly-express ๊ฐ ํ์ํจ
# import plotly.graph_objs as go
# Import Pandas
# import plotly.express as px
- ๊ณ ๊ฐ Id, ์ก์ฅ, ๊ตญ๊ฐ ๋ณ๋ก ๊ทธ๋ฃนํ -> ๊ฐ ๊ทธ๋ฃน์ count ๊ณ์ฐ
- ๊ฐ ๊ตญ๊ฐ๊ฐ ์ฃผ๋ฌธ๋ฐ์ ํ์๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด, '๊ตญ๊ฐ' ์ด ๊ธฐ๋ฐ์ผ๋ก value_counts()
- data๋ก ์ ์ฅ๋ ๋์
๋๋ฆฌ : ์ง๋ ์ค์ (choropleth)
- type : ์๊ฐํ ์ข ๋ฅ๋ก, choropleth ์ง๋๋ฅผ ์ง์
- locations : ๊ฐ ๊ตญ๊ฐ๋ฅผ ๋ํ๋ด๋ ์ธ๋ฑ์ค
- locationmode : ์์น ๋ชจ๋๋ก '๊ตญ๊ฐ๋ช ' ์ฌ์ฉ
- z : ๊ฐ ๊ตญ๊ฐ์ ๋ํ ์ฃผ๋ฌธ ์
- text : ๋ง์ฐ์ค๋ฅผ ๊ฐ์ ธ๋ค ๋๋ฉด ํ์ํ ํ ์คํธ ๋ฐ์ดํฐ
- colorbar : ์์ ๋ง๋ ์ ๋ชฉ
- colorscale : ์ฌ์ฉํ ์์ ์ฒ๋
- reversescale : ์์ ์ฒ๋ ๋ฐ์ ์ฌ๋ถ ์ค์
- layout์ผ๋ก ์ ์ฅ๋ ๋์
๋๋ฆฌ : ์ง๋์ ๋ ์ด์์๊ณผ ์คํ์ผ ์ค์
- title : ์ง๋ ์ ๋ชฉ, ์์น, ์ต์ปค
- geo : ์ง๋์ ์ง๋ฆฌ์ ์์ฑ(ํด์๋, ๋ฐ๋ค์, ์ก์ง ์, ํ๋ ์ ํ์ ์ฌ๋ถ)
- template : ํ๋กฏ ๋ฆฌํฌํธ์ ํ ํ๋ฆฟ
- height, width : ์ง๋์ ๋์ด์ ๋๋น
- choromap ๋ณ์ : data์ layout์ ์ฌ์ฉํ์ฌ ์ง๋ ์์ฑ
- iplot : ์ง๋๋ฅผ ์ธํฐ๋ ํฐ๋ธ ํ๊ฒ ํ์ (validate = False : ๊ฒ์ฆ์ ๋นํ์ฑํํ๋ ๊ฒ์ผ๋ก, ์ง๋๊ฐ ์ ์์ ์ผ๋ก ๋ ๋๋ง ๋๋์ง ํ์ธํ์ง ์๋๋ค.
# ๊ณ ๊ฐId, ์ก์ฅ, ๊ตญ๊ฐ ๋ณ๋ก ๊ทธ๋ฃนํ -> ๊ฐ ๊ทธ๋ฃน์ count ๊ณ์ฐ
world_map = df[['CustomerID', 'InvoiceNo', 'Country']].groupby(['CustomerID', 'InvoiceNo', 'Country']).count().reset_index(drop=False)
# ๊ทธ๋ฃนํ ๊ฒฐ๊ณผ์์ '๊ตญ๊ฐ' ์ด ๊ธฐ๋ฐ์ผ๋ก ๊ตญ๊ฐ์ ์ฃผ๋ฌธ์ ๊ณ์ฐ
countries = world_map['Country'].value_counts()
data = dict(type = 'choropleth', # ์์ฑํ๋ ค๋ ์ง๋ ์ข
๋ฅ(choropleth)
locations = countries.index, # ์ง๋์ ๋ํ๋ด๋ ์ง์ญ ์ธ๋ฑ์ค
locationmode = 'country names',
z = countries,
text = countries.index,
colorbar = {'title':'Orders'}, # ์์ ๋ง๋์ ์ ๋ชฉ
colorscale = 'Viridis',
reversescale = False) # ์์ ์ฒ๋ ๋ฐ์ ์ฌ๋ถ(false : ๊ฐ์ด ์ปค์ง ์๋ก ์งํ ์์/true: ๋ฐ์์์)
layout = dict(title = {'text': "Number of Orders by Countries",
'y': 0.9,
'x' : 0.5,
'xanchor': 'center',
'yanchor': 'top'},
geo = dict(resolution = 50,
showocean = True,
oceancolor = 'LightBlue',
showland = True,
landcolor = 'whitesmoke',
showframe = True),
template = 'plotly_white',
height = 600,
width = 1000)
choromap = go.Figure(data = [data], layout = layout)
iplot(choromap, validate = False)
๐ ์ด๋ ๊ฒ ๋ง์ฐ์ค๋ฅผ ํธ๋ฒ ํ๋ฉด ๊ตญ๊ฐ๋ช ๊ณผ ์ฃผ๋ฌธ ๊ฑด์๊ฐ ๋ํ๋๋ ์ธํฐ๋ ํฐ๋ธ ํ ์ง๋๊ฐ ํ์๋๋ค!