competition - M5 EDA

Page content

강의 홍보

공지

제 수업을 듣는 사람들이 계속적으로 실습할 수 있도록 강의 파일을 만들었습니다. 늘 도움이 되기를 바라며. 참고했던 교재 및 Reference는 꼭 확인하셔서 교재 구매 또는 관련 Reference를 확인하시기를 바랍니다.

I. 개요

  • Kaggle에서 데이터를 다운로드 하는 방법에 대해서는 생략한다.
  • 본 포스트는 Google Colab을 기반으로 작성하였다.
  • Kaggle + Google Colab 데이터 연동하는 방법은 이전 포스트를 참고한다.

  • 데이터는 크게 4가지로 구성되어 있다. (원문 인용)
    • calendar.csv - Contains information about the dates on which the products are sold.
    • sales_train_validation.csv - Contains the historical daily unit sales data per product and store [d_1 - d_1913]
    • sample_submission.csv - The correct format for submissions. Reference the Evaluation tab for more info.
    • sell_prices.csv - Contains information about the price of the products sold per store and date.

II. 데이터 불러오기

!pip install kaggle
from google.colab import files
files.upload()
Requirement already satisfied: kaggle in /usr/local/lib/python3.6/dist-packages (1.5.6)
Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (from kaggle) (4.41.1)
Requirement already satisfied: certifi in /usr/local/lib/python3.6/dist-packages (from kaggle) (2020.4.5.1)
Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from kaggle) (2.23.0)
Requirement already satisfied: python-dateutil in /usr/local/lib/python3.6/dist-packages (from kaggle) (2.8.1)
Requirement already satisfied: python-slugify in /usr/local/lib/python3.6/dist-packages (from kaggle) (4.0.0)
Requirement already satisfied: six>=1.10 in /usr/local/lib/python3.6/dist-packages (from kaggle) (1.12.0)
Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from kaggle) (1.24.3)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->kaggle) (3.0.4)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->kaggle) (2.9)
Requirement already satisfied: text-unidecode>=1.3 in /usr/local/lib/python3.6/dist-packages (from python-slugify->kaggle) (1.3)
Saving kaggle.json to kaggle.json





{'kaggle.json': b'{"username":"your_name","key":"your_key"}'}
ls -1ha kaggle.json
kaggle.json
!mkdir -p ~/.kaggle # 파일 생성
!mv kaggle.json ~/.kaggle/ # kaggle.json 파일 이동
!chmod 600 ~/.kaggle/kaggle.json # 권한 부여
! kaggle competitions download -c m5-forecasting-accuracy
Warning: Looks like you're using an outdated API Version, please consider updating (server 1.5.6 / client 1.5.4)
Downloading sales_train_validation.csv.zip to /content
100% 15.5M/15.5M [00:00<00:00, 56.9MB/s]

Downloading sample_submission.csv.zip to /content
  0% 0.00/163k [00:00<?, ?B/s]
100% 163k/163k [00:00<00:00, 146MB/s]
Downloading sell_prices.csv.zip to /content
 63% 9.00M/14.2M [00:00<00:00, 52.0MB/s]
100% 14.2M/14.2M [00:00<00:00, 69.6MB/s]
Downloading calendar.csv to /content
  0% 0.00/101k [00:00<?, ?B/s]
100% 101k/101k [00:00<00:00, 98.8MB/s]
!unzip sales_train_validation.csv.zip
!unzip sample_submission.csv.zip
!unzip sell_prices.csv.zip
Archive:  sales_train_validation.csv.zip
  inflating: sales_train_validation.csv  
Archive:  sample_submission.csv.zip
  inflating: sample_submission.csv   
Archive:  sell_prices.csv.zip
  inflating: sell_prices.csv         
!ls
calendar.csv			sample_data		   sell_prices.csv
sales_train_validation.csv	sample_submission.csv	   sell_prices.csv.zip
sales_train_validation.csv.zip	sample_submission.csv.zip
import pandas as pd
sales_train_val = pd.read_csv('sales_train_validation.csv')
print(sales_train_val.head())
                              id        item_id  ... d_1912 d_1913
0  HOBBIES_1_001_CA_1_validation  HOBBIES_1_001  ...      1      1
1  HOBBIES_1_002_CA_1_validation  HOBBIES_1_002  ...      0      0
2  HOBBIES_1_003_CA_1_validation  HOBBIES_1_003  ...      1      1
3  HOBBIES_1_004_CA_1_validation  HOBBIES_1_004  ...      7      2
4  HOBBIES_1_005_CA_1_validation  HOBBIES_1_005  ...      2      4

[5 rows x 1919 columns]
calendar = pd.read_csv('calendar.csv')
print(calendar.head())
         date  wm_yr_wk    weekday  ...  snap_CA  snap_TX  snap_WI
0  2011-01-29     11101   Saturday  ...        0        0        0
1  2011-01-30     11101     Sunday  ...        0        0        0
2  2011-01-31     11101     Monday  ...        0        0        0
3  2011-02-01     11101    Tuesday  ...        1        1        0
4  2011-02-02     11101  Wednesday  ...        1        0        1

[5 rows x 14 columns]
sample_submission = pd.read_csv('sample_submission.csv')
print(sample_submission.head())
                              id  F1  F2  F3  F4  ...  F24  F25  F26  F27  F28
0  HOBBIES_1_001_CA_1_validation   0   0   0   0  ...    0    0    0    0    0
1  HOBBIES_1_002_CA_1_validation   0   0   0   0  ...    0    0    0    0    0
2  HOBBIES_1_003_CA_1_validation   0   0   0   0  ...    0    0    0    0    0
3  HOBBIES_1_004_CA_1_validation   0   0   0   0  ...    0    0    0    0    0
4  HOBBIES_1_005_CA_1_validation   0   0   0   0  ...    0    0    0    0    0

[5 rows x 29 columns]
sell_prices = pd.read_csv('sell_prices.csv')
print(sell_prices.head())
  store_id        item_id  wm_yr_wk  sell_price
0     CA_1  HOBBIES_1_001     11325        9.58
1     CA_1  HOBBIES_1_001     11326        9.58
2     CA_1  HOBBIES_1_001     11327        8.26
3     CA_1  HOBBIES_1_001     11328        8.26
4     CA_1  HOBBIES_1_001     11329        8.26

III. Data Exploration

  • 데이터 탐색을 위해 사전준비를 진행해보자.
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
import seaborn as sns
from itertools import cycle
pd.set_option('max_columns', 50)
plt.style.use('bmh')
color_pal = plt.rcParams['axes.prop_cycle'].by_key()['color']
color_cycle = cycle(plt.rcParams['axes.prop_cycle'].by_key()['color'])
  • pd.set_optinos('max_columns', 50), 컬럼 출력개수를 의미한다.
  • 그 외 나머지 코드는 그래프의 색상과 의미가 있다.

(1) 각 id에 대한 시각화

  • 다음과 같은 순서대로 시각화를 진행한다.
    • item을 선택한다.
    • id를 index로 지정 후, sales sales 데이터의 column만 지정한다.
    • 위 값을 column으로 변환한다.
    • 데이터를 시각화 한다.
# extract sales data columns
d_cols = [c for c in sales_train_val.columns if 'd_' in c] # sales data columns
# print(d_cols)

sales_train_val.loc[sales_train_val['id'] == 'FOODS_3_090_CA_3_validation']\
  .set_index('id')[d_cols]\
  .T\
  .plot(figsize=(15,5), 
        title = 'FOODS_3_090_CA_3 sales by "d" number', color = next(color_cycle))
plt.legend('')
plt.show()

png

  • Tcolumns & index 위치를 바꿔주는 기능을 가지고 있다.

(2) 데이터 Merge

  • 2개의 데이터를 Merge 하도록 한다.
temp = sales_train_val[sales_train_val['id'] == 'FOODS_3_090_CA_3_validation'][d_cols].T
print(temp.head())
     8412
d_1   108
d_2   132
d_3   102
d_4   120
d_5   106
  • 8412의 column명을 FOODS_3_090_CA_3_validation로 변경한다.
  • 그리고 indexdcolumn명을 변경 한다.
temp = temp.rename(columns={8412:'FOODS_3_090_CA_3'}).reset_index().rename(columns={'index': 'd'})
print(temp.head())
     d  FOODS_3_090_CA_3
0  d_1               108
1  d_2               132
2  d_3               102
3  d_4               120
4  d_5               106
  • calender 데이터셋과 Merge 한다.
temp = temp.merge(calendar, how='left', validate='1:1')
print(temp.head())
     d  FOODS_3_090_CA_3        date  wm_yr_wk    weekday  wday  month  year  \
0  d_1               108  2011-01-29     11101   Saturday     1      1  2011   
1  d_2               132  2011-01-30     11101     Sunday     2      1  2011   
2  d_3               102  2011-01-31     11101     Monday     3      1  2011   
3  d_4               120  2011-02-01     11101    Tuesday     4      2  2011   
4  d_5               106  2011-02-02     11101  Wednesday     5      2  2011   

  event_name_1 event_type_1 event_name_2 event_type_2  snap_CA  snap_TX  \
0          NaN          NaN          NaN          NaN        0        0   
1          NaN          NaN          NaN          NaN        0        0   
2          NaN          NaN          NaN          NaN        0        0   
3          NaN          NaN          NaN          NaN        1        1   
4          NaN          NaN          NaN          NaN        1        0   

   snap_WI  
0        0  
1        0  
2        0  
3        0  
4        1  
  • 날짜별 기준으로 FOODS_3_090_CA_3에 관한 그래프를 작성한다.
temp.set_index('date')['FOODS_3_090_CA_3']\
  .plot(figsize=(15,5), 
        color=next(color_cycle), 
        title='FOODS_3_090_CA_3 sales by actual sale dates')
plt.show()

png

  • 이번에는 HOBBIES_1_234_CA_3에 대한 데이터를 Merge하여 시각화를 작성해보자.
temp2 = sales_train_val[sales_train_val['id'] == 'HOBBIES_1_234_CA_3_validation'][d_cols].T
temp2 = temp2.rename(columns={6324:'HOBBIES_1_234_CA_3'}) # name it correctly
temp2 = temp2.reset_index().rename(columns={'index':'d'}) # make the index 'd'
temp2 = temp2.merge(calendar, how='left', validate='1:1')
print(temp2.head())
     d  HOBBIES_1_234_CA_3        date  wm_yr_wk    weekday  wday  month  \
0  d_1                   0  2011-01-29     11101   Saturday     1      1   
1  d_2                   0  2011-01-30     11101     Sunday     2      1   
2  d_3                   0  2011-01-31     11101     Monday     3      1   
3  d_4                   0  2011-02-01     11101    Tuesday     4      2   
4  d_5                   0  2011-02-02     11101  Wednesday     5      2   

   year event_name_1 event_type_1 event_name_2 event_type_2  snap_CA  snap_TX  \
0  2011          NaN          NaN          NaN          NaN        0        0   
1  2011          NaN          NaN          NaN          NaN        0        0   
2  2011          NaN          NaN          NaN          NaN        0        0   
3  2011          NaN          NaN          NaN          NaN        1        1   
4  2011          NaN          NaN          NaN          NaN        1        0   

   snap_WI  
0        0  
1        0  
2        0  
3        0  
4        1  
temp2.set_index('date')['HOBBIES_1_234_CA_3']\
  .plot(figsize=(15,5), 
        color=next(color_cycle), 
        title='HOBBIES_1_234_CA_3 sales by actual sale dates')
plt.show()

png

  • 이번에는 HOUSEHOLD_1_118_CA_3_validationMerge 하여 시각화를 진행해보자.
temp3 = sales_train_val[sales_train_val['id'] == 'HOUSEHOLD_1_118_CA_3_validation'][d_cols].T
temp3 = temp3.rename(columns={6776:'HOUSEHOLD_1_118_CA_3'}) # name it correctly
temp3 = temp3.reset_index().rename(columns={'index':'d'}) # make the index 'd'
temp3 = temp3.merge(calendar, how='left', validate='1:1')
temp3.set_index('date')['HOUSEHOLD_1_118_CA_3']\
  .plot(figsize=(15,5), 
        color=next(color_cycle), 
        title='HOUSEHOLD_1_118_CA_3 sales by actual sale dates')
plt.show()

png

(3) 연월 요일 기준으로 한 Sales 시각화

  • 연도, 월, 요일을 기준으로 위 3가지 데이터에 대한 값 시각화를 진행한다.
temps = ['FOODS_3_090_CA_3','HOBBIES_1_234_CA_3','HOUSEHOLD_1_118_CA_3']
temps_df = [temp, temp2, temp3]

for i in [0, 1, 2]:
  fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15,3))
  # wday 시각화
  temps_df[i].groupby('wday').mean()[temps[i]]\
    .plot(kind='line', 
          title='average sale: day of week',
          lw = 5, 
          color=color_pal[0], 
          ax=ax1)
  
  # month 시각화
  temps_df[i].groupby('month').mean()[temps[i]]\
    .plot(kind='line', 
          title='average sale: day of month',
          lw = 5, 
          color=color_pal[4], 
          ax=ax2)
  
  # year 시각화
  temps_df[i].groupby('year').mean()[temps[i]]\
    .plot(kind='line', 
          title='average sale: day of year',
          lw = 5, 
          color=color_pal[2], 
          ax=ax3)

  # suptitle
  fig.suptitle(f'Trens for item: {temps[i]}', 
               size=20, 
               y=1.1)
  plt.tight_layout()
  plt.show()  

png

png

png

  • tight_layout 함수는 각 데이터에 관한 여백(padding)에 관련된 subplot 파라미터를 조정한다.
  • 위 3개의 item만 가지고 비교 했을 경우에는 HOBBIES_1_234_CA_3이 다른 두 아이템에 비해 평균적인 sales가 높은 것으로 확인되고 있다.

IV. 결론

  • Kaggle에서 데이터를 다운로드 받는 부분을 수행하였고, 이 부분을 통해서 이제 여러분들이 적극적으로 코드를 경험하기를 바란다.
  • 오늘 코드에서 중요한 부분은 서로 다른 데이터를 어떻게 Merge할 것인가가 핵심이고, 이 때 T라는 함수를 활용하여 행과 열을 transpose하는 것이 주요 핵심 사항이다.
  • 다음에는 sample item 30개를 조회해서 시각화를 구현하고, sector별로 판매개수 추이를 확인할 수 있는 시각화를 진행한다.

V. Reference