프로젝트 | Kaggle 스타벅스 마케팅 데이터 분석 : 분석 개요
1. 분석 개요 ☑️ 분석 목적 Starbucks Customer DataStarbucks customer datasetwww.kaggle.comKaggle 에서 제공되는 'Starbucks Customer Data' 의 고객/ 프로모션/고객 행동 테이블을 사용하여 프로모션 성과 분석 및
cookievlog.tistory.com
↑ 앞서 확인한 내용을 기반으로 데이터 전처리 하고, 전체 테이블 MERGE 진행
2. 데이터 전처리
☑️ 전처리 전 ERD
- 테이블 primary & foreign key 는 id (pk) person(pk) value(fk) offer_id (pk)
☑️ 중복값 처리
- 앞서 확인한 대로, `Transcript` 테이블의 중복값 397개를 제거 완료
# 중복 제거
transcript.drop_duplicates(inplace=True)
#중복 결과 확인
transcript.duplicated().sum()
☑️ 데이터/데이터 타입 변환
- `Profile` 테이블의 became_member_on 컬럼의 타입이 datetime이 아닌 int 로 저장되어있음. 년 /월별 데이터분석을 위해 datetime 타입으로 변환.
#profile 컬럼명 & 형 변환(날짜가 int 로 저장되어있음 )
profile['became_member_on'] = profile['became_member_on'].astype('str')
profile['became_member_on'] = pd.to_datetime(profile['became_member_on'])
profile= profile.rename(columns={'id':'customer_id'})
- `Transcript` 테이블에 value 컬럼의 `json` 형태로 vaule_offer_id / amount / reward 값이 저장됨. portfolio 테이블과 join 하기 위해 offer_id 가 필요하므로 값을 분리.
- 또한, value 키 값은 [offer id, offer_id,amount, reward] 총 4가지로 구성. offer id 와 offer_id 의 경우 중복값이 없으므로 데이터 수집시 오류(오타)가 났다고 판단함. 따라서 offer_id 컬럼에 offer id 값을 대치시켜 모든 offer_id 값을 offer_id 컬럼에 추가 저장해줬음. (offer id 컬럼 삭제)
#value json값 전처리
from ast import literal_eval
# 문자열을 파싱하여 딕셔너리로 변환 (AST 모듈 사용)
transcript['value_parsed'] = transcript['value'].apply(lambda x: literal_eval(x))
# offer id와 amount 컬럼으로 분리
transcript['value_offer_id'] = transcript['value_parsed'].apply(lambda x: x.get('offer_id', None))
transcript['value_offer id'] = transcript['value_parsed'].apply(lambda x: x.get('offer id', None))
transcript['value_amount'] = transcript['value_parsed'].apply(lambda x: x.get('amount', None))
transcript['value_reward'] = transcript['value_parsed'].apply(lambda x: x.get('reward', None))
# value_parsed 컬럼 제거
transcript = transcript.drop(columns=['value_parsed'])
#offer id 값 offer_id로 대치
transcript['value_offer_id'] = transcript['value_offer_id'].fillna(transcript['value_offer id']) # fillna 둘다 null 이여도null 에러 안남
#열 필터링
transcript = transcript[['person','event','time','value_offer_id','value_amount','value_reward']]
☑️ 결측값/이상치 처리
- `Profile ` 테이블의 gender / income 컬럼에 각각 동일하게 결측값 `2,715`가 존재함. (전체의 약 12%)
- 결측치 비중이 10%이상이므로 최대한 대치하여 사용하고자 했으나, gender, income 값을 추정 할 수있는 컬럼이나 정보가 없어 왜곡 방지를 위해 삭제하기로 결정. (결측 행 age 컬럼도 동일하게 이상치(118)로 저장되어있음 삭제해도 무방 )
#결측치 처리(age/income Nan값)
profile = profile.dropna(subset=['income'])
- `transcript` offer_id 결측값 대치 : `transcript` value 컬럼에서 분리한 offer_id , amount, value_reward 컬럼 중 amount 컬럼은 `고객이 발생시킨 매출`을 의미함. 추후 고객의 매출 분석 뿐 아니라, 프로모션의 매출 분석을 위해 amount 행에 비어있는 offer_id 컬럼값을 추가하고자 함. 기준은 event 컬럼의 `offer completed` 와 'transaction` 이 동일한 time에 발생한 경우 amount 의 offer_id를 offer completed 의 값으로 변경함. ( 동일한 시각에 발생한 매출은 프로모션과 직접적인 연관이 있다고 판단 )
- offer_id 결측치는 138,953 (53%) . event ='transaction' 일때만 offer_id 결측치가 존재함. 위 내용으로 결측치 처리후 offer_id 최종 결측치는 19,7801 (44%) 입니다. 약 10%p 결측치 대체 완료.
#Transcript offer_id 일부 결측치 처리
# 고객별 시각이 동일한 이벤트만 추출
con1=transcript['event'].isin(['offer completed','transaction']) # 대치시켜줄 2 값만 추출
df = transcript[con1]
con2 = df.duplicated(subset=['person','time'],keep=False) # 이벤트 발생시각이 동일한 고객 추출 (중복행 모두 추출)
#이벤트 순서 변경 : offer complted -> transantion
df = df[con2].sort_values(by=['person','time','event'],ascending=[True,True,True])
#이전값(offer completed) 가져오기 & transaction 행에 채우기
df['prev_offer_id'] = df['value_offer_id'].shift()
df['value_offer_id'] = df['value_offer_id'].fillna(df['prev_offer_id'])
# 기존 테이블에 offer_id 추가
transcript['value_offer_id'] = transcript['value_offer_id'].fillna(df['value_offer_id'])
☑️ 전처리 후 최종 테이블 ERD
- 테이블 primary & foreign key 는 customer_id (pk) customer_id (pk) offer_id(fk) offer_id (pk) 입니다.
# 패키지 설치 & 데이터 마운틴
import pandas as pd
import numpy as np
import math
import datetime
import seaborn as sns
import matplotlib.pyplot as plt
from ast import literal_eval
portfolio = pd.read_csv('portfolio.csv',index_col =0) # 시트 1개씩 있음
profile = pd.read_csv('profile.csv',index_col =0)
transcript = pd.read_csv('transcript.csv',index_col =0)
#value 값 형 변환 전처리 (json -> 컬럼으로)
# 문자열을 파싱하여 딕셔너리로 변환 (AST 모듈 사용)
transcript['value_parsed'] = transcript['value'].apply(lambda x: literal_eval(x))
transcript['value_offer_id'] = transcript['value_parsed'].apply(lambda x: x.get('offer_id', None))
transcript['value_offer id'] = transcript['value_parsed'].apply(lambda x: x.get('offer id', None))
transcript['value_amount'] = transcript['value_parsed'].apply(lambda x: x.get('amount', None))
transcript['value_reward'] = transcript['value_parsed'].apply(lambda x: x.get('reward', None))
transcript = transcript.drop(columns=['value_parsed'])
transcript['value_offer_id'] = transcript['value_offer_id'].fillna(transcript['value_offer id']) # fillna 둘다 null 이여도null 에러 안남
transcript = transcript[['person','event','time','value_offer_id','value_amount','value_reward']]
#profile 값 형 변환(int -> datetime)
profile['became_member_on'] = profile['became_member_on'].astype('str') #int 타입임 -> str -> date로 변환해줬음
profile['became_member_on'] = pd.to_datetime(profile['became_member_on'])
profile= profile.rename(columns={'id':'customer_id'})
# 중복 처리 397 행 제외 -> 306137
transcript.drop_duplicates(inplace=True)
#value_offer_id 결측치 처리
con1=transcript['event'].isin(['offer completed','transaction']) # 이벤트 두개만 추출후
df = transcript[con1]
con2 = df.duplicated(subset=['person','time'],keep=False) # 중복행 모두 추출
df = df[con2].sort_values(by=['person','time','event'],ascending=[True,True,True])
df['prev_offer_id'] = df['value_offer_id'].shift()
df['value_offer_id'] = df['value_offer_id'].fillna(df['prev_offer_id'])
df['value_offer_id'].isna().sum()
del df['prev_offer_id']
# 기존 테이블에 offer_id 추가
transcript['value_offer_id'] = transcript['value_offer_id'].fillna(df['value_offer_id'])
#transcript컬럼명 변경
transcript = transcript.rename(columns={'person':'customer_id','value_offer_id':'offer_id','value_amount':'amount'})
#portfolio 컬럼명 변경
portfolio= portfolio.rename(columns={'id':'offer_id'})
# 전체 테이블 병합 : all
trans_port = pd.merge(transcript,portfolio,on='offer_id',how='left')
trans_prof = pd.merge(transcript,profile,on='customer_id') #모든 고객의 이벤트 데이터가 있음 306137 행 갯수 동일함.
all= pd.merge(trans_port,profile,on='customer_id')
'PYTHON' 카테고리의 다른 글
프로젝트 회고 | Kaggle 스타벅스 마케팅 데이터 분석 : 프로모션 성과 분석 (0) | 2025.01.05 |
---|---|
프로젝트 회고 | Kaggle 스타벅스 마케팅 데이터 분석 : 데이터 EDA (0) | 2025.01.05 |
프로젝트 회고 | Kaggle 스타벅스 마케팅 데이터 분석 : 분석 개요 (0) | 2024.12.30 |
실습 | PANDAS 누락 기간 생성 / 조건별 증감율 계산하기( date_range/reindex/apply) (1) | 2024.12.26 |
실습 | PANDAS 결측값 및 IQR 기준 이상치 처리하기(dropna/drop /quantile/str.contains/apply/isdigit) (0) | 2024.12.26 |