バスケットデータを作成する
Text Update: 09/02, 2019 (JST)

本ページでは、Tidy Dataをデータフレーム型のバスケットデータへ変換する方法を紹介しています。
 

Packages and Datasets

本ページではR version 3.6.1 (2019-07-05)の標準パッケージ以外に以下の追加パッケージを用いています。
 

Package Version Description
purrr 0.3.2 Functional Programming Tools
tidyverse 1.2.1 Easily Install and Load the ‘Tidyverse’

 

バスケットデータとは

『Rによる機械学習』P234にある販売実績記録表のようなデータをここでは、便宜上、バスケットデータ(買い物かごデータ)と呼んでいます。トランザクションデータと呼ばれることもあります。
 

販売番号 販売商品
1 A, B, C
2 A, C, D, E
3 A, B, C. D, F
4 B, D, E
5 B, F

 

データ(tidy data)

元データであるtidy dataは データ分析勉強会 の第3.5回で用いた以下のチュートリアルデータです。このデータはゲーム『ハリー・ポッター 魔法同盟』に出てくる魔法薬のレシピをtidy data形式でまとめたものです。なお、一部を省略して表示しています。
 

recipe
portion material quantity
奮起薬 ビタールート 1
奮起薬 リーエムの血 1
奮起薬 ユキノハナ 1
奮起薬 グレニアンの毛 1
強い奮起薬 ビタールート 3
NA NA
強烈な奮起薬 ユニコーンのたてがみ 1
頭冴え薬 根生姜 4
頭冴え薬 イモリの脾臓 3
頭冴え薬 タマオシコガネの粉末 1
頭冴え薬 アルマジロの胆汁 1

 

バスケットデータへの変換

上記の材料(material)を魔法薬(portion)単位で一つにまとめたバスケットデータを作成するにはpasete関数を用いて長さ1のベクトルデータとしてまとめます。ポイントはpasete関数にcollapseオプションを指定することです。
collapseオプションを指定しないと長さが1を超えるベクトルなった場合にデータフレーム型にまとめることができません。
 

paste(c(1:5))                    # 長さが5のベクトル
## [1] "1" "2" "3" "4" "5"
paste(c(1:5), collapse = ", ")   # 長さが1のベクトル
## [1] "1, 2, 3, 4, 5"

 
魔法薬(portion)単位にまとめるにはdplyr::gropu_by関数を用います。
 

recipe %>% 
  dplyr::group_by(portion) %>% 
  dplyr::summarise(basket = paste(material, collapse = ", "))
portion basket
だらけ薬 カノコソウの根, 催眠豆, バタースコッチ, ヤドカリの殻
バルッフィオの脳活性秘薬 飛び跳ね毒キノコ, カエルの脳みそ, ルーンスプールの卵, ドラゴンの爪の粉末
強い強化薬 ハニーウォーター, クマツヅラの抽出液, トモシリソウ, オオバナノコギリソウ
強い奮起薬 ビタールート, ユキノハナ, リーエムの血, アブラクサンの毛
強化薬 ハニーウォーター, クマツヅラの抽出液, トモシリソウ, ラビッジ
強烈な奮起薬 ビタールート, ユキノハナ, リーエムの血, ユニコーンのたてがみ
治癒薬 ニガヨモギ, 腫れ草の膿, ハナハッカ, ドラゴンの肝
頭冴え薬 根生姜, イモリの脾臓, タマオシコガネの粉末, アルマジロの胆汁
奮起薬 ビタールート, リーエムの血, ユキノハナ, グレニアンの毛

 
以上でバスケットデータの完成です。
 

応用例

元データには材料の必要量(quantity)のデータもありますので、バスケットの中身を

\[材料名 \times 必要量\]

の形にしてみます。
 

recipe
portion material quantity
奮起薬 ビタールート 1
奮起薬 リーエムの血 1
奮起薬 ユキノハナ 1
奮起薬 グレニアンの毛 1
強い奮起薬 ビタールート 3
NA NA
強烈な奮起薬 ユニコーンのたてがみ 1
頭冴え薬 根生姜 4
頭冴え薬 イモリの脾臓 3
頭冴え薬 タマオシコガネの粉末 1
頭冴え薬 アルマジロの胆汁 1

 
dplyrパッケージはフィーチャー間(列間)のベクトル処理は得意ですが、インスタンス単位(行単位)での処理はあまり得意ではありません(分かりにくいです)。そこで、材料(material)と必要量(quantity)をインスタンス単位で結合処理するためにpurrrパッケージを用います。
 

recipe %>% 
  with(., purrr::map2_chr(.x = material, .y = quantity,
                          .f = ~ paste(.x, .y, collapse = "", sep = " x")))
##  [1] "ビタールート x1"         "リーエムの血 x1"        
##  [3] "ユキノハナ x1"           "グレニアンの毛 x1"      
##  [5] "ビタールート x3"         "ユキノハナ x4"          
##  [7] "リーエムの血 x1"         "アブラクサンの毛 x1"    
##  [9] "カノコソウの根 x2"       "催眠豆 x1"              
## [11] "バタースコッチ x1"       "ヤドカリの殻 x1"        
## [13] "飛び跳ね毒キノコ x2"     "カエルの脳みそ x1"      
## [15] "ルーンスプールの卵 x1"   "ドラゴンの爪の粉末 x1"  
## [17] "ハニーウォーター x1"     "クマツヅラの抽出液 x1"  
## [19] "トモシリソウ x1"         "ラビッジ x2"            
## [21] "ハニーウォーター x1"     "クマツヅラの抽出液 x1"  
## [23] "トモシリソウ x1"         "オオバナノコギリソウ x2"
## [25] "ニガヨモギ x1"           "腫れ草の膿 x3"          
## [27] "ハナハッカ x2"           "ドラゴンの肝 x1"        
## [29] "ビタールート x4"         "ユキノハナ x6"          
## [31] "リーエムの血 x2"         "ユニコーンのたてがみ x1"
## [33] "根生姜 x4"               "イモリの脾臓 x3"        
## [35] "タマオシコガネの粉末 x1" "アルマジロの胆汁 x1"

purrr::map2_chr関数は上記のように二つのベクトル変数に対して任意の関数(ここではpaste関数)を適用し、処理結果を文字型ベクトルで返す関数です。
 

recipe %>% 
  dplyr::mutate(recipe = purrr::map2_chr(.x = material, .y = quantity,
                                         .f = ~ paste(.x, .y, collapse = "", sep = " x"))) %>% 
  dplyr::group_by(portion) %>% 
  dplyr::summarise(basket = paste(recipe, collapse = ", "))
portion basket
だらけ薬 カノコソウの根 x2, 催眠豆 x1, バタースコッチ x1, ヤドカリの殻 x1
バルッフィオの脳活性秘薬 飛び跳ね毒キノコ x2, カエルの脳みそ x1, ルーンスプールの卵 x1, ドラゴンの爪の粉末 x1
強い強化薬 ハニーウォーター x1, クマツヅラの抽出液 x1, トモシリソウ x1, オオバナノコギリソウ x2
強い奮起薬 ビタールート x3, ユキノハナ x4, リーエムの血 x1, アブラクサンの毛 x1
強化薬 ハニーウォーター x1, クマツヅラの抽出液 x1, トモシリソウ x1, ラビッジ x2
強烈な奮起薬 ビタールート x4, ユキノハナ x6, リーエムの血 x2, ユニコーンのたてがみ x1
治癒薬 ニガヨモギ x1, 腫れ草の膿 x3, ハナハッカ x2, ドラゴンの肝 x1
頭冴え薬 根生姜 x4, イモリの脾臓 x3, タマオシコガネの粉末 x1, アルマジロの胆汁 x1
奮起薬 ビタールート x1, リーエムの血 x1, ユキノハナ x1, グレニアンの毛 x1

 

Enjoy!  

本blogに対するアドバイス、ご指摘等は データ分析勉強会 または GitHub まで。

CC BY-NC-SA 4.0 , Sampo Suzuki