LESSON

Store Salesデータセットの理解

「データを理解しないまま分析を始めるのは、地図なしで航海に出るようなものだ。」

田中VPoEがKaggleのコンペティションページを開く。

「Store Sales - Time Series Forecasting。エクアドルの大手スーパーマーケットチェーンCorporacion Favoritaの売上データだ。54店舗、33商品カテゴリ、約4年分。まずはデータ構造を徹底的に理解しよう。」

コンペティション概要

項目内容
コンペ名Store Sales - Time Series Forecasting
目的店舗×商品カテゴリの日次売上を予測
評価指標RMSLE(Root Mean Squared Logarithmic Error)
データ期間2013年1月〜2017年8月
予測対象2017年8月16日〜8月31日(16日間)

RMSLE(評価指標)

import numpy as np

def rmsle(y_true, y_pred):
    """Root Mean Squared Logarithmic Error"""
    return np.sqrt(np.mean((np.log1p(y_pred) - np.log1p(y_true)) ** 2))

# 特徴: 過大予測より過小予測にペナルティが大きい
# log変換するため、大きな売上値の影響が緩和される

データセットの構成

train.csv / test.csv

メインの売上データ。

カラム説明
idint一意のID
datedate日付(2013-01-01 〜 2017-08-15)
store_nbrint店舗番号(1〜54)
familystr商品カテゴリ(33種類)
salesfloat売上数量(目的変数)
onpromotionintプロモーション中の商品数
import pandas as pd

train = pd.read_csv('train.csv', parse_dates=['date'])
print(f"レコード数: {len(train):,}")
print(f"期間: {train['date'].min()}{train['date'].max()}")
print(f"店舗数: {train['store_nbr'].nunique()}")
print(f"商品カテゴリ数: {train['family'].nunique()}")
print(f"時系列数: {train.groupby(['store_nbr', 'family']).ngroups}")

# レコード数: 3,000,888
# 期間: 2013-01-01 〜 2017-08-15
# 店舗数: 54
# 商品カテゴリ数: 33
# 時系列数: 1,782

stores.csv

店舗のメタデータ。

カラム説明
store_nbr店舗番号
city都市名
state州名
type店舗タイプ(A〜E)
clusterクラスター番号(1〜17)

oil.csv

日次の石油価格データ。エクアドルは産油国であり、石油価格が経済全体に大きな影響を与える。

カラム説明
date日付
dcoilwticoWTI原油価格(USD/barrel)

holidays_events.csv

祝日・イベントデータ。

カラム説明
date日付
typeHoliday / Transfer / Additional / Bridge / Event / Work Day
localeNational / Regional / Local
locale_name適用地域名
descriptionイベントの説明
transferred振替されたかどうか

transactions.csv

店舗ごとの日次取引数。

カラム説明
date日付
store_nbr店舗番号
transactions取引数

データの初期確認

# 基本統計量
print(train['sales'].describe())
# count    3,000,888
# mean         357.8
# std          1101.5
# min             0.0
# 25%             0.0
# 50%            11.0
# 75%           197.0
# max         125,497

# sales = 0のレコードが多い(約25%以上)
zero_sales = (train['sales'] == 0).mean()
print(f"sales=0の割合: {zero_sales:.1%}")

# 商品カテゴリ別の売上分布
category_sales = train.groupby('family')['sales'].mean().sort_values(ascending=False)
print(category_sales.head(10))
# GROCERY I が最大、次いで BEVERAGES, PRODUCE ...

データの注意点

  1. 欠損値: oil.csvに欠損あり。補間が必要
  2. ゼロ売上: 特定の店舗×カテゴリで常にゼロの組み合わせがある
  3. 2016年4月の地震: エクアドル大地震の影響で売上パターンが変化
  4. 祝日の複雑さ: 振替休日、地域限定祝日など複雑な構造
  5. プロモーション: onpromotionカラムは2014年以前に欠損が多い

まとめ

項目ポイント
データ規模300万レコード、1,782時系列
目的変数sales(日次売上数量)
評価指標RMSLE(対数変換した二乗平均平方根誤差)
外部変数石油価格、祝日、店舗情報、取引数
注意点ゼロ売上、地震影響、祝日の複雑さ

チェックリスト

  • Store Salesデータセットの各テーブルの役割を説明できる
  • RMSLEの特徴を理解した
  • データの主要な注意点を把握した
  • 1,782時系列の構造(54店舗 x 33カテゴリ)を理解した

次のステップへ

データ構造を理解したところで、次は時系列データの分解手法を学び、トレンド・季節性・残差を分離しよう。

推定読了時間: 30分