-
기상데이터와 GS25 판매량 데이터를 이용한 분석 리포트 - 1Data Analysis 2021. 3. 8. 22:38반응형
Data download and python code link
진행사항
- 일단위로 진행하기엔 무리가 있을듯 하여, 월 단위로 분석을 진행할 예정입니다.
분석 진행 사항
- 애자일 방식으로 진행 예정, 틀을 정하지 않고서 자유로운 분석을 추구했습니다.
- 이번 리포트는 도메인 지식을 쌓는 시간으로 정했습니다.
- 데이터 전처리에 신경을 많이 쓰고, 최대한 데이터를 파악하려고 합니다.
- 중간고사 리포트는 EDA와 시각화를 통한 추세파악 진행예정
- 유통 데이터와 기상 데이터를 사용할 예정
- 세부적으로 경기도 권역만 분석을 실시할 예정
- 그 외 서울과 인천 지역은 지역별 판매량 시각화와 날짜별 판매량 시각화 총 두개만 진행 후 더이상 진행하지 않을 예정
추후 진행 방안
- 세부적으로 경기도 광주시와 경기도 성남시의 판매를 통계학적으로 비교하고, 가설을 세워서 검증할 예정
- ex) 라면판매량은 경기광주시와 경기성남시의 차이가 없다.
- ex2) 날씨가 추워지면 라면판매량이 증가할까?
에로사항
- GS25.csv의 데이터중 법정구역이 합쳐져있음, 기존에 집계 처리가 되어있는 상태여서 복구할 수 없음
- 날씨 데이터와 병합하여 분석할 예정이여서 삭제하고 진행 하였습니다.
- '가평군양평군'
- '여주시이천시'
- '연천군포천군'
- '오산시안성시평택시'
Data Load
- Library load
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns plt.rcParams['figure.figsize'] = [18, 12] plt.rcParams['font.family'] = 'NanumGothic' from statannot import add_stat_annotation import numpy as np from scipy import stats
gs25 = pd.read_csv('Data/GS25.csv',encoding='cp949')
data_w = pd.read_csv('Data/기상데이터.csv',encoding='cp949')
Data Validation
GS25 데이터 확인
- 전체 판매량
gs25['date_year'] = gs25['korea_cvs.sale_dt'].astype(str).str[:4]
print('총 판매량 : ',len(gs25), '\n' '2017년 판매량 : ',len(gs25[gs25['date_year'] == '2016']),'비율 : ', round(len(gs25[gs25['date_year'] == '2016'])/len(gs25)*100,2),'%', '\n' '2018년 판매량 : ',len(gs25[gs25['date_year'] == '2017']),'비율 : ', round(len(gs25[gs25['date_year'] == '2017'])/len(gs25)*100,2),'%' '\n' '2019년 판매량 : ',len(gs25[gs25['date_year'] == '2018']),'비율 : ', round(len(gs25[gs25['date_year'] == '2018'])/len(gs25)*100,2),'%')
총 판매량 : 2707786
2017년 판매량 : 923321 비율 : 34.1 %
2018년 판매량 : 904207 비율 : 33.39 %
2019년 판매량 : 880258 비율 : 32.51 %- 성별 판매량
print('총 판매량 : ',len(gs25), '\n' '여성 판매량 : ',len(gs25[gs25['korea_cvs.gen_cd'] == 'F']),'비율 : ', round(len(gs25[gs25['korea_cvs.gen_cd'] == 'F'])/len(gs25)*100,2),'%', '\n' '남성 판매량 : ',len(gs25[gs25['korea_cvs.gen_cd'] == 'M']),'비율 : ', round(len(gs25[gs25['korea_cvs.gen_cd'] == 'M'])/len(gs25)*100,2),'%')
총 판매량 : 2707786
여성 판매량 : 1442960 비율 : 53.29 %
남성 판매량 : 1264826 비율 : 46.71 %- 연령별 판매량
age_list = list(set(gs25['korea_cvs.age_cd'])) age_list.sort() age_list
['00~19', '20~39', '40~59', '60~99']
print('총 판매량 : ',len(gs25), '\n' '00~19 : ',len(gs25[gs25['korea_cvs.age_cd'] == age_list[0]]),'비율 : ', round(len(gs25[gs25['korea_cvs.age_cd'] == age_list[0]])/len(gs25)*100,2),'%', '\n' '20~39 : ',len(gs25[gs25['korea_cvs.age_cd'] == age_list[1]]),'비율 : ', round(len(gs25[gs25['korea_cvs.age_cd'] == age_list[1]])/len(gs25)*100,2),'%', '\n' '40~59 : ',len(gs25[gs25['korea_cvs.age_cd'] == age_list[2]]),'비율 : ', round(len(gs25[gs25['korea_cvs.age_cd'] == age_list[2]])/len(gs25)*100,2),'%', '\n' '60~99 : ',len(gs25[gs25['korea_cvs.age_cd'] == age_list[3]]),'비율 : ', round(len(gs25[gs25['korea_cvs.age_cd'] == age_list[3]])/len(gs25)*100,2),'%', '\n')
총 판매량 : 2707786
00~19 : 389610 비율 : 14.39 %
20~39 : 1118350 비율 : 41.3 %
40~59 : 924433 비율 : 34.14 %
60~99 : 275393 비율 : 10.17 %- 카테고리별 판매량
category_list = list(set(gs25['korea_cvs.category'])) category_list.sort() category_list
['과자',
'라면',
'마스크',
'맥주',
'면도기',
'생리대',
'생수',
'숙취해소제',
'스타킹',
'아이스크림',
'우산',
'탄산음료']category_rank = dict() print('총 판매량 : ',len(gs25)) for category in category_list: print('{} : '.format(category),len(gs25[gs25['korea_cvs.category'] == category]), '비율 : ',round(len(gs25[gs25['korea_cvs.category'] == category])/len(gs25)*100,2),'%') category_rank[category] = round(len(gs25[gs25['korea_cvs.category'] == category])/len(gs25)*100,2)
총 판매량 : 2707786
과자 : 428685 비율 : 15.83 %
라면 : 413521 비율 : 15.27 %
마스크 : 65748 비율 : 2.43 %
맥주 : 313128 비율 : 11.56 %
면도기 : 51970 비율 : 1.92 %
생리대 : 158116 비율 : 5.84 %
생수 : 310041 비율 : 11.45 %
숙취해소제 : 184866 비율 : 6.83 %
스타킹 : 103876 비율 : 3.84 %
아이스크림 : 318908 비율 : 11.78 %
우산 : 55153 비율 : 2.04 %
탄산음료 : 303774 비율 : 11.22 %category_df = pd.DataFrame([category_rank], index = ['판매량(%)']).T
category_df = category_df.sort_values('판매량(%)',ascending=False)
category_df
시각화
sns.barplot(x=category_df.index, y=category_df['판매량(%)'], data=category_df) plt.title('카테고리별 판매량', fontsize=20) plt.ylabel('판매량(%)', fontsize=18) plt.xlabel('품목', fontsize=18) plt.show()
기상데이터 확인
데이터 전처리 진행
data_w.columns=['관측일', '관측번호', '지역', '법정동', '최고기온', '최대풍속', '최소기온', '평균기온', '평균상대습도', '평균풍속', '합계강수량']
feature 생성
data_w['관측일(월)'] = (data_w['관측일'].astype(str).str[:6]).astype(int)
데이터 형변환
data_w['관측일'] = pd.to_datetime(data_w['관측일'],format="%Y%m%d")
weather_col = ['최고기온','최대풍속','최소기온','평균기온', '평균상대습도','평균풍속', '합계강수량'] def whether_line_visualizition(data_w,weather_col,x='관측일',title=''): for col in weather_col: ax = sns.lineplot(x=x, y=col ,hue='지역',data=data_w) plt.title('{0} 지역별 {1}'.format(title,col), fontsize=20) plt.ylabel('{}'.format(col), fontsize=14) plt.xlabel('Date', fontsize=14) plt.legend(fontsize=12, loc='best') plt.show()
Data Preprocessing
gs25['korea_cvs.sale_dt(month)'] = (gs25['korea_cvs.sale_dt'].astype(str).str[:6]).astype(int)
gs25 = gs25.drop('korea_cvs.sale_dt',axis=1)
# 데이터 집계 처리 gs25_month = gs25.groupby(['korea_cvs.pvn_nm', 'korea_cvs.sale_dt(month)', 'korea_cvs.gen_cd','korea_cvs.age_cd', 'korea_cvs.category', 'korea_cvs.bor_nm']).sum().reset_index()
data_w_mean=(data_w[['관측일(월)', '법정동', '최고기온', '최대풍속', '최소기온', '평균기온', '평균풍속', '합계강수량']].groupby(['관측일(월)','법정동']).mean().reset_index())
# 합쳐진 법정동 제외진행 gs25_month = gs25_month[(gs25_month['korea_cvs.bor_nm'] != '가평군양평군') & (gs25_month['korea_cvs.bor_nm'] != '여주시이천시') & (gs25_month['korea_cvs.bor_nm'] != '연천군포천군') & (gs25_month['korea_cvs.bor_nm'] != '오산시안성시평택시')]
# 기온 데이터와 GS25데이터 조인 merge_data = pd.merge(gs25_month, data_w_mean, how='inner', left_on=['korea_cvs.sale_dt(month)', 'korea_cvs.bor_nm'],right_on=['관측일(월)','법정동'])
# 년 단위 추가 merge_data['korea_cvs.sale_dt(year)'] = (merge_data['korea_cvs.sale_dt(month)'] .astype(str).str[:4]).astype(int)
지역분할
gyunggido = merge_data[merge_data['korea_cvs.pvn_nm'] == '경기도'] seoul = merge_data[merge_data['korea_cvs.pvn_nm'] == '서울특별시'] incheon = merge_data[merge_data['korea_cvs.pvn_nm'] == '인천광역시']
gyunggido_area_list = list(set(gyunggido['korea_cvs.bor_nm'])) seoul_area_list = list(set(seoul['korea_cvs.bor_nm'])) incheon_area_list = list(set(incheon['korea_cvs.bor_nm']))
날짜 분할
full_month = list(set(merge_data['korea_cvs.sale_dt(month)'])) full_month.sort()
# 201601~201812 월별로 분할 def month_slice(dataframe,full_month): month_slice = [] for month in full_month: month_slice.append(dataframe[dataframe['korea_cvs.sale_dt(month)'] == month]) return month_slice
gyunggido_month_slice = month_slice(gyunggido,full_month) seoul_month_slice = month_slice(seoul,full_month) incheon_month_slice = month_slice(incheon,full_month)
지역 세분화
# 지역별 dictionary 생성 def area_slice(dataframe,area_list): area_dict = dict() for area in area_list: area_dict[area] = dataframe[dataframe['korea_cvs.bor_nm'] == area] return area_dict
gyunggido_area = area_slice(gyunggido,gyunggido_area_list) seoul_area = area_slice(seoul,seoul_area_list) incheon_area = area_slice(incheon,incheon_area_list)
temp = (gyunggido_area['광주시'][['korea_cvs.sale_dt(month)', '최고기온', '최대풍속', '최소기온', '평균기온', '평균풍속', '합계강수량']]).drop_duplicates('korea_cvs.sale_dt(month)')
temp.index = temp['korea_cvs.sale_dt(month)']
시각화 (지역별)
X는 품목별, Y는 Count, 분류를 성별로 나눠서 box plot으로 확인합니다.
여기서는 날짜별로 하나씩 찍어내면서 성별로 어떤 품목이 가장 많이 판매되었는지 확인하는 시각화 자료입니다.
def visualization_area(dataframe_dict, area_list, x='korea_cvs.category', y='korea_cvs.adj_qty', category=str('korea_cvs.gen_cd')): plt.rcParams['figure.figsize'] = [20, 8] for area in area_list: for year in [2016,2017,2018]: sns.boxplot(x=x, y=y, hue=category, data=gyunggido_area[area][gyunggido_area[area]['korea_cvs.sale_dt(year)'] == year]) plt.ylabel('Count', fontsize=18) plt.xlabel('품목', fontsize=18) plt.title('{0} 년도 {1} 판매량 '.format(year,area), fontsize=20) plt.legend(fontsize=14,loc='upper right') plt.show()
visualization_area(gyunggido_area,gyunggido_area_list)
이미지가 20개가 넘어서 생략합니다.
시각화 (날짜별)
def visualization(dataframe,full_month, x='korea_cvs.category', y='korea_cvs.adj_qty', category=str('korea_cvs.gen_cd'), title=''): plt.rcParams['figure.figsize'] = [24, 10] for month, data in zip(full_month,dataframe): sns.barplot(x=x, y=y, hue=category, data=data,dodge=True) # default : dodge=True plt.ylabel('Count', fontsize=18) plt.xlabel('품목', fontsize=18) plt.title('{} {} 판매량'.format(title,month), fontsize=20) plt.legend(fontsize=14) plt.show()
경기도, 서울, 인천 구역
X는 품목명, Y는 Count, 나이대로 분류한 시각화 자료입니다.
대부분 시각적으로 보기 편하게 나이대에 맞춰서 판매량을 보고 싶었습니다.
이 시각화 자료도 마찬가지로 경기도, 서울, 인천 지역으로 크게 나누어서 차이점을 확인하고 싶었습니다.
또한 날짜로 for문을 이용함으로써 추세를 확인할 수도 있습니다.
visualization(gyunggido_month_slice,full_month,category='korea_cvs.age_cd',title='경기도')
visualization(seoul_month_slice,full_month,category='korea_cvs.age_cd',title='서울')
visualization(incheon_month_slice,full_month,category='korea_cvs.age_cd',title='인천')
반응형'Data Analysis' 카테고리의 다른 글
P-Value, T-Test, Z-Test 설명 (0) 2023.06.27 기상데이터와 GS25 판매량 데이터를 이용한 분석 리포트 - 2 (0) 2021.03.08 뉴스데이터를 이용한 문서유사도 확인 (0) 2021.03.05 - 일단위로 진행하기엔 무리가 있을듯 하여, 월 단위로 분석을 진행할 예정입니다.