こかげむら

ゲーム好きな理系大学生のお話

【前処理大全】サンプリングをする時は単位を揃えよう

はじめに

データの前処理,サンプリングの時の注意点の話

機械学習について勉強していて,そこでは前処理が大切になってくる

最近『前処理大全』という本を読んでいて,サンプリング時に大切だと思った点,注意しなければならないと思ったことについて書く

コードはPythonです.

前処理大全[データ分析のためのSQL/R/Python実践テクニック]

前処理大全[データ分析のためのSQL/R/Python実践テクニック]

 

 サンプリング

業務でデータを扱って分析などを行う際,データサイズが膨大でそのままではメモリに乗らないということがある.

そんな際に膨大なデータの一部分だけを抽出することをサンプリングという.

結論:分析対象データの単位とサンプリング単位は揃えよう

そうしないと,サンプリングによってデータを破壊してしまう

実際に検証してみる

検証に使うデータ reserve_tb

f:id:agry:20190907131713p:plain

データについて

ホテルの予約レコード.1行に1つの予約が格納されてる.

列(カラム)は予約id,ホテルid,顧客id,日時,予約人数などの予約に関する情報

比較する分析対象について

 分析対象1:予約人数別の予約数について調べる

     例)予約全体のうち,4人で泊まる予約がされたのは何件あるのだろう?

 

分析対象2:年間の予約回数別の顧客数について調べる

     例)年間で5回予約してくれた顧客idは何種類あるのだろう?年間で1回しか予約しない顧客idは何種類あるのだろう?

サンプリング手法

#検証に使うデータreserve_tb
half_reserve_tb = reserve_tb.sample(frac=0.5)

分析対象1,2どちらについても,予約の50%を抽出するようにサンプリングする.

予約数が50%になるようにサンプリングするので,この場合サンプリングの単位は「予約数」

つまり分析対象1は分析対象とサンプリング手法の単位が揃っているが,分析対象2は単位が異なっている

分析対象1,2のサンプリング前後を比較してみた

 分析対象1(単位が揃ってる良い例)

サンプリング前(左),サンプリング後(右)

サンプリングの前後でデータの分布はほとんど同じ

f:id:agry:20190907140454p:plainf:id:agry:20190907140714p:plain

分析対象2(単位が異なっている悪い例)

サンプリング前(左),サンプリング後(右)

サンプリングの前後でデータの分布が異なる

f:id:agry:20190907141221p:plainf:id:agry:20190907141238p:plain

分析対象2の時の適切なサンプリング手法

以下の手順でサンプリングする必要がある

  1. 予約レコードの顧客IDに対してサンプリング
  2. サンプリングした顧客IDの予約レコードのみを抽出する
#予約レコードの顧客ID(ユニークなもの)に対してランダムサンプリング
#targetにサンプリングした顧客IDを格納
target = pd.Series(reserve_tb['customer_id'].unique()).sample(frac=0.5)
#targetに含まれる顧客IDのみ抽出
reserve_tb[reserve_tb['customer_id'].isin(target)]

分析対象2で単位を揃えたサンプリングを行った時の結果

サンプリング前(左),サンプリング後(右)

サンプリングの前後でデータの分布がほとんど同じ

f:id:agry:20190907142114p:plainf:id:agry:20190907142130p:plain

思ったこと

確かに分析対象とサンプリング単位が異なればサンプリングの前後でデータの割合が異なってしまう.

例えばこの場合だと,サンプリング前のデータでは,年間7回予約していた顧客が,50%サンプリングによって7回全ての予約データが取ってこられるとは限らない(期待値的に7回のうち3,4回しか取ってこられないだろう).したがって,予約回数が少ない顧客の割合が増加してしまい,サンプリングによってデータを破壊してしまっている.

サンプリングは分析対象のデータとサンプリング単位を揃えることが重要.