스터티노트 15일차

손성우 (sacn1129)·2024년 2월 18일

SQL

목록 보기
14/57
  1. 카드 거래이력 분석을 통한 고객 특성 파악 -> 데이터 EDA 및 인사이트 추출
    :A사는 신규 브랜드의 점포를 입점 시키려는 계획을 가지고 있다. 신규 브랜드이기 때문에 과거 상권에 대한 정보가 없어,
    어느 지역에 입점을 시켜야할지 고민이 많다. 고민 끝에 후보 지역A를 최종 후보로 정했다.
    하지만 자신들의 브랜드와 해당 지역에 거주하는 고객의 소비성향과 비슷한지가 아직 의문이다.
    따라서 신용카드 Spending data를 활용하여 고객의 소비 성향을 파악하고자 한다.
    파악된 고객의 소비성향과 브랜드의 성향이 맞는지 비교해보고 최종 결정을 내리고자 한다.

문제정의
:신규 브랜드 입점 상권 불분명
기대효과
:신규 상권 입점 여부 결정 및 상권의 고객 소비성향 파악
해결방안
:카드 Spending data 활용 지역 거주 고객 소비성향 파악 및 브랜드와 매칭을 통해 입점 결정
성과측정
:신규 진입 결정 여부
현업적용
:인사이트 Report 작성 및 보고

항상 Data읽고 전처리 먼저
: data shape -> data type -> Null값 확인하기 -> outlier확인하기
#과정에서 installments가 일시불은 빈문자열이라서 null이 있어서 null자리를 인식 가능한 문자로 채워준다.
:df['installments'].fillna(0,inplace=True)

-업종별 이용 및 매출 비중 분석
:df['store_id'].value_counts() #상점이 얼마나 있는지 확인

-업종별 이용 횟수 비중
:df_store = pd.DataFrame(df['store_id'].value_counts()).reset_index()
df_store.columns = ['store_id', 'cnt']

-업종별 이용 횟수 비중을 퍼센트화
df_store['total'] = df_store['cnt'].sum()
df_store['ratio'] = round( (df_store['cnt'] / df_store['total']) * 100,2)

-업종별 매출액 비중 (※ groupby.sum() 활용)
:df_amt = pd.DataFrame(df['amount'].groupby(df['store_id']).sum()).reset_index()

-그 후에 매출액 순위를 보기 위해 내림차순 정렬
:df_amt = df_amt.sort_values(by=['amount'], ascending=False)
#여기서 매출액,이용횟수비중 보다는 비슷한 업종끼리 묶어서 분석을 하는게 도움이 됨

-핵심 업종 탐색
df_store.columns = ['store_id', 'cnt', 'cnt_total', 'cnt_ratio']
df_amt.columns = ['store_id', 'amt', 'amt_total', 'amt_ratio']
#각각 위에서 정의한 업종별 이용횟수 , 업종별 매출별로 나누어서 의미가 있는 칼럼들 끼리 묶어서 재정의했다.

-위에서 정의한 데이터를 한번에 보게 합침
df_merge = pd.merge(df_store, df_amt , how='left', on='store_id')
!#left join , merge(조인할 데이터,조인할데이터, how ='left'or'right' , on = ' 공통된 칼럼중에 선택'

-이용 고객수(Unique)
df_customer = pd.DataFrame(df['card_id'].groupby(df['store_id']).nunique()).reset_index()
df_customer.columns = ['store_id', 'customer']
df_customer['customer_total'] = df['card_id'].nunique()
df_customer['customer_ratio'] = round((df_customer['customer'] / df_customer['customer_total'])*100,2)
#이용 고객수라는 새로운 데이터를 추출하는 과정

-1회 사용금액
df_merge['amt_per_use'] = round(df_merge['amt'] / df_merge['cnt'],0)
#한번 결제를 할때 얼마나 결제를 하는지 보기위해
-객단가
df_merge['cus_per_use'] = round(df_merge['amt'] / df_merge['customer'],0)
#한명의 고객이 이 매장에서 보통 얼마나 결제를 하냐를 보기위해

-핵심업종 정의
이용 비중, 이용 금액 비중, 이용 고객수 비중에 가중치를 적용하여 새로운 Score를 정의
a = 0.3
b = 0.35
c = 0.35
df_merge['core_store'] = df_merge['cnt_ratio']a + df_merge['amt_ratio']b + df_merge['customer_ratio']*c
#가중치를 결정한다 , 여기서 가중치는 회사마다 달라서 어떤 회사는 a에 좀더 치중할수도 있고 어떤 회사는 c에 더 가중을 둘 수 있기때문에 상황에 맞게 용이하게 가중치를 정해서 계산하여 core_store 데이터를 하나 만드는 과정

Min-max 표준화를 통해 100점 만점의 점수로 변환
df_merge['core_store_scaled'] = df_merge['core_store'].apply(lambda x: (x - df_merge['core_store'].min()) / (df_merge['core_store'].max() - df_merge['core_store'].min()) )
df_merge['core_store_scaled'] = round(df_merge['core_store_scaled'] * 100,0)
#보기 불편해서 100점만점으로 만든다.

-위에서 구한 핵심업종을 위주로 분석

-상위에서 정의한 핵심업종 Data만 가져오기
df_core_store = df[df['store_id'].isin([753, 0, 1342, 221, 428])]
df_core_store['store_id'].value_counts()

각 요일별 데이터 확인
df_core_store['days_of_week'].value_counts()

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

sns.catplot(x="days_of_week", kind="count",palette="pastel", edgecolor=".6",data=df_core_store);
plt.gcf().set_size_inches(10, 3)
#그래프를 사용하여 무슨 요일이 가장 영향력이 있는 보기

-주말(1), 주중(0) 소비형태 비교
import numpy as np
df_core_store['weekend'] = np.where(df_core_store['days_of_week'].isin([5,6]), 1, 0)
df_core_store['weekend'].value_counts()
#주말과 주중도 비교해보기 , 당연히 주중이 많이 영향이 있음

-핵심업종 일시불 및 할부결제 분석
sns.catplot(x="installments", kind="count",palette="pastel", edgecolor=".6",data=df_core_store);
plt.gcf().set_size_inches(10, 3)
#0-일시불 , 그외는 할부로 정의했을때 , 사전에 우리는 일시불이 아닌 null값이 비율이 엄청 높았기 때문에 당연히 일시불이 많다.

-취소금액 매출 비중 0.8%
abs(df_core_store[df_core_store['amount'] < 0]['amount'].sum()) / df_core_store['amount'].sum() * 100

753, 0, 1342, 221, 428 -> 점수가 가장 높았던 5개
'Store 0'이 가장 많은 취소 금액 비중
df1 = df_core_store[df_core_store['store_id']==753]
df2 = df_core_store[df_core_store['store_id']==0]
df3 = df_core_store[df_core_store['store_id']==1342]
df4 = df_core_store[df_core_store['store_id']==221]
df5 = df_core_store[df_core_store['store_id']==428]

print("store(753) :", abs(df1[df1['amount'] < 0]['amount'].sum()) / df1['amount'].sum() 100)
print("store(0) :", abs(df2[df2['amount'] < 0]['amount'].sum()) / df2['amount'].sum()
100)
print("store(1342) :", abs(df3[df3['amount'] < 0]['amount'].sum()) / df3['amount'].sum() 100)
print("store(221) :", abs(df4[df4['amount'] < 0]['amount'].sum()) / df4['amount'].sum()
100)
print("store(428) :", abs(df5[df5['amount'] < 0]['amount'].sum()) / df5['amount'].sum() * 100)
#상위 5개 업종에 대하여 취소 금액 비중을 계산하기

-Time data 처리
import datetime
df_core_store['Date_merge'] = df['date'].astype(str) + ' ' + df['time'].astype(str)
#초기 테이블에서 date,time 칼럼이 각각 object 변수였기 때문에 datetime으로 바꿔줌

-2016년 8월 1일 ~ 2018년 7월 31일까지의 Data
df_core_store['Date_merge'].min(), df_core_store['Date_merge'].max()

-핵심업종별 매출 금액 by 년도
df_year = pd.DataFrame(df_core_store.groupby(['store_id', 'year'])['amount'].sum()).reset_index()
#기간이 2016 중간 ~ 2018 중간이 라서 2017년을 제외하고는 1년을 다 못채워서 확실한 데이터자료는 아니다.

profile
안녕하세용

0개의 댓글