六本木で働くデータサイエンティストのブログ

元祖「銀座で働くデータサイエンティスト」です / 道玄坂→銀座→東京→六本木

前処理なしのトランザクションデータを{arules}パッケージで読み込む方法

実は僕は結構頻繁に{arules}パッケージを使うんですが*1、個人的には汎用性を考えて必ず素性ベクトルの形になるようにデータを前処理して読み込むようにしています。例えばこんな感じ。

ビール ソーセージ 牛肉 ...
1 0 1 ...
0 1 0 ...
1 1 1 ...
... ... ... ...


なのですが、場合によっては前処理なしでただベタっとアイテムリストが個々のトランザクションごとに並んでるだけのデータを扱わなきゃいけないことも多いと思います。つまり、こんな感じのデータです。

ビール, 牛肉
ソーセージ
ビール, ソーセージ, 牛肉
...


こういう場合、素性ベクトルの形に直そうとすると際限なくカラム方向に伸びていってしまうことが多く、前処理自体が非常に厄介になったりします。そこで、そういう時に出来る限り面倒な操作をせずに{arules}パッケージで扱える形に読み込む方法をサクッとご紹介します。


単にread.transactions()関数を使うだけ!


と言っても、めちゃくちゃ簡単です。実は『Rによるデータサイエンス』のアソシエーション分析の章でもちらっと触れられてますが、read.transactions()関数を使って適切なデリミタで区切られたテキスト形式のデータファイルを読み込む、ただそれだけです。


Rによるデータサイエンス - データ解析の基礎から最新手法まで

Rによるデータサイエンス - データ解析の基礎から最新手法まで


よく読むと「表17.2(b)のようなデータを、関数read.transactionsを用いて直接transaction形式に読み込むこともできる」(p.281)と書いてあるんですが、実は表17.2(a)のような、生のトランザクションがだだ書きされただけのデータでも読み込むことが出来ます。


とりあえずGitHub上に適当なデータを用意してみました。めっちゃくちゃいい加減なPOSデータもどきです。DLしたらRのワークスペースフォルダに置いておきましょう。

ビール, おむつ, ドレッシング, 生野菜
ビール, 柿ピー, ソーセージ
ソーダ, ポテトチップス, チョコレート, アイス
ビール, 柿ピー, ソーセージ
生野菜, 果物, 豆腐, 豚肉
生野菜, 果物, 豆腐, 牛肉, じゃがいも
根菜, 豆腐, 牛肉, こんにゃく
ワイン, ソーセージ, チーズ
ワイン, 牛肉, じゃがいも


という感じで、適当もいいところです*2。で、こいつを{arules}パッケージで読み込むのは非常に簡単で、以下のようにすれば良いだけです。

> d.tran<-read.transactions(file='ex_trans.txt',sep=',',format='basket')
# sepでデリミタを指定、format引数はbasketを指定すれば良い
> d.tran
transactions in sparse format with
 9 transactions (rows) and
 20 items (columns)


ちゃんと入ってますね。ちなみに大規模データなどで重複があると「duplicatesがあるぞこの野郎」みたいにread.transactions()から怒られることがあるので、そういう時はrm.duplicate=Tとすれば重複を削除して読み込んでくれます。


で、もちろんこのトランザクションデータからapriori()でassociation rulesを推定することもできます。

> d.ap<-apriori(d.tran)

parameter specification:
 confidence minval smax arem  aval originalSupport support minlen maxlen
        0.8    0.1    1 none FALSE            TRUE     0.1      1     10
 target   ext
  rules FALSE

algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Warning in apriori(d.tran) :
  You chose a very low absolute support count of 0. You might run out of memory! Increase minimum support.

apriori - find association rules with the apriori algorithm
version 4.21 (2004.05.09)        (c) 1996-2004   Christian Borgelt
set item appearances ...[0 item(s)] done [0.00s].
set transactions ...[20 item(s), 9 transaction(s)] done [0.00s].
sorting and recoding items ... [20 item(s)] done [0.00s].
creating transaction tree ... done [0.00s].
checking subsets of size 1 2 3 4 5 done [0.00s].
writing ... [143 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s].

> inspect(head(sort(d.ap,by="support"),n=10))
   lhs              rhs             support confidence lift
1  { 柿ピー}     => { ソーセージ} 0.2222222          1  3.0
2  { 柿ピー}     => {ビール}      0.2222222          1  3.0
3  { じゃがいも} => { 牛肉}       0.2222222          1  3.0
4  { 果物}       => {生野菜}      0.2222222          1  4.5
5  {生野菜}      => { 果物}       0.2222222          1  4.5
6  { 果物}       => { 豆腐}       0.2222222          1  3.0
7  {生野菜}      => { 豆腐}       0.2222222          1  3.0
8  { ソーセージ,                                           
     柿ピー}     => {ビール}      0.2222222          1  3.0
9  { 柿ピー,                                               
    ビール}      => { ソーセージ} 0.2222222          1  3.0
10 { ソーセージ,                                           
    ビール}      => { 柿ピー}     0.2222222          1  4.5


柿ピーとソーセージが何でこんなに強いんだ。。。そして生野菜と果物の関係性めちゃくちゃ強い(笑)。そりゃあ、どこのスーパーに行っても大体同じか隣の売り場に置いてるんだから当たり前だと思いますが。これっぱがしのトランザクション数でも、143通りもの相関ルールが算出されるっていうのが凄いですね。


ついでなので{arulesViz}で可視化してみる


これまためちゃくちゃ簡単です。以下のようにすれば、サクサクっと描けます。

> plot(d.ap,method='graph',control=list(type='items',layout=layout.fruchterman.reingold))
# plot.rulesではmethod引数に'graph'を与えると{igraph}を利用したグラフを描いてくれる
# control引数にリスト形式でtype='items'とするとアイテム間の相関ルールを描画し、
# layout=layout.fruchterman.reingoldとするとFruchterman-Reingold力学的アルゴリズムによって
# 最短経路長の順=関係性の強い順にノード間が近くなるように描画してくれる


f:id:TJO:20140320165123p:plain


うん、鍋やりたい人たちの買い物傾向と、子供向けに何か買ってあげてる人たちの買い物傾向とで、ブチッと断絶しているのがよく見て取れますね(笑)。こんな感じで、様々な組み合わせデータの分析が出来るので、興味のある方は是非お試しあれ。

*1:{arulsViz}との、というかさらにそのlayout.fruchterman.reingoldとの併用で無限に可能性が広がります

*2:でも頑張って「ビールとおむつ」入れたよ!