기상데이터와 GS25 판매량 데이터를 이용한 분석 리포트 - 1
Data download and python code link
Joonyeong97/GS25_weather_data
Contribute to Joonyeong97/GS25_weather_data development by creating an account on GitHub.
github.com
진행사항
- 일단위로 진행하기엔 무리가 있을듯 하여, 월 단위로 분석을 진행할 예정입니다.
분석 진행 사항
- 애자일 방식으로 진행 예정, 틀을 정하지 않고서 자유로운 분석을 추구했습니다.
- 이번 리포트는 도메인 지식을 쌓는 시간으로 정했습니다.
- 데이터 전처리에 신경을 많이 쓰고, 최대한 데이터를 파악하려고 합니다.
- 중간고사 리포트는 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='인천')