RのtransitionPlot関数を用いた遷移図の作成
こちらの記事で紹介されているRのtransitionPlotを用いた図がとても綺麗でしたので、試しにこれを使って遷移図を作図してみました。
パッケージインストール
transitionPlotはGmiscパッケージに含まれていますがcranサーバから取得できないので、以下のようにリポジトリを指定してソースからインストールする必要があります。
reps = c("http://ftp.sunet.se/pub/lang/CRAN","http://cran.gforge.se") install.packages("Gmisc", repos=reps, dependencies=TRUE, type="source") library(Gmisc)
transitionPlotの使い方
transitionPlot関数
transitionPlot(transition_flow, type_of_arrow = c("grid", "simple", "gradient"), box_txt = rownames(transition_flow), tot_spacing = 0.2, box_width = 1/4, fill_start_box = "darkgreen", txt_start_clr = "white", fill_end_box = "steelblue", txt_end_clr = "white", cex = 2, min_lwd = 1, max_lwd = 6, lwd_prop_total = TRUE, arrow_clr = "#000000", abs_arrow_width = FALSE, overlap_bg_clr = "#FFFFFF", overlap_order = 1:nrow(transition_flow), overlap_add_width = 1.5, box_prop = NULL)
引数
transition_flow N×Nの状態数の遷移行列(Nは状態数)。行が前の状態で列が後の状態。前と後で状態数が異なる(正方行列でない)場合エラー。 type_of_arrow 矢印のタイプ。"grid","simple","gradient"のいずれかをテキストで指定。"grid"以外は他のパラメータの指定が必要。デフォルトはgrid。 box_txt ボックスに表示されるテキスト。文字列ベクトルを渡す。 tot_spacing ボックス間の縦の間隔。数値を渡す。 box_width ボックスの横幅。画面に占める割合を指定する。デフォルトは1/4。 fill_start_box 始点側のボックスの色。ボックスごとに色を変えたい場合、それぞれに対応するベクトルを渡す。 txt_start_clr 始点側のテキストの色。ボックスごとに色を変えたい場合、それぞれに対応するベクトルを渡す。 fill_end_box 終点側のボックスの色。ボックスごとに色を変えたい場合、それぞれに対応するベクトルを渡す。 txt_end_clr 終点側のテキストの色。ボックスごとに色を変えたい場合、それぞれに対応するベクトルを渡す。 cex フォントサイズ(倍率)。 min_lwd 矢印の線幅の最小サイズ。 max_lwd 矢印の線幅の最大サイズ。 lwd_prop_total 矢印の線幅をボックスに依存させるか否か。TRUE or FALSEで指定。デフォルトはTRUE。 arrow_clr 矢印の色。矢印の色を個別に変えたい場合、ベクトルで指定する。(詳細はヘルプ参照) abs_arrow_width 矢印の先端サイズを固定するか否か(線幅に依存させない)。TRUE or FALSEで指定。デフォルトはFALSE。 overlap_bg_clr 矢印の背景色。 overlap_order 線の上下関係。ベクトルで指定。 overlap_add_width 交差点における矢印の外枠の幅。数値で指定。 box_prop ボックスを割合表示させる場合に指定。N×2の行列で指定。(詳細はヘルプ参照)
作図サンプル
パッケージmlogitに含まれるKetchupデータのブランド遷移を試しに描画してみます。Ketchupデータはケチャップに関する購入トランザクションのデータで、"heintz"、"hunts"、"delmonte"、"stb"という4種類のブランドのどれを買ったかというデータです。まずこのデータをRで読み込みます。
library(mlogit) data(Ketchup) head(Ketchup,10)
出力
Ketchup.hid Ketchup.id Ketchup.choice price.heinz price.hunts price.delmonte price.stb 1 1 1 heinz 1.19 1.39 1.49 0.89 2 1 2 heinz 0.99 1.36 1.39 0.95 3 1 3 hunts 1.46 1.43 1.49 0.99 4 1 4 hunts 1.46 1.43 1.45 0.99 5 1 5 stb 1.46 1.36 1.39 0.95 6 2 1 heinz 0.99 1.36 1.47 0.95 7 2 2 heinz 1.19 1.44 1.47 0.95 8 2 3 heinz 1.19 1.53 1.47 0.95 9 3 1 stb 1.47 1.43 1.45 0.99 10 4 1 heinz 0.79 1.43 1.45 0.99
Ketchup.hidが顧客番号、Ketchup.idが購入回数になっており、Ketchup.choiceが選択したブランド、price...がその時点の価格になっています。
今回はtransitionPlotの作図として、初回購入ブランドと2回目購入ブランドの遷移を可視化してみたいと思います。作図にあたり以下のコードで遷移行列を作成しまた。
tmp <- Ketchup # 結合用データを作成 tmp[,2] <- Ketchup[,2] - 1 # 結合に使うKetchup.idを一つずらす dat <- merge(Ketchup,tmp,by=c("Ketchup.hid","Ketchup.id")) # 元データを結合と購入回数を一つずらしたテーブルを結合 dat <- dat[dat$Ketchup.id == 1,] # 初回購入を選択 dat2 <- data.frame(choice1 = dat$Ketchup.choice.x, choice2 = dat$Ketchup.choice.y) # 初回購入と2回目購入のブランド列を選択 trans_mat <- table(dat2) # 遷移行列の作成
データの結合にmergeを利用する際、結合させるidを一つずらして結合させることで、前の購入と後の購入の列を作成しています。それから初回購入と2回目購入の行を選択し、遷移行列を作成しています。
transitionPlotによる作図は以下のコマンドで実行できます。
transitionPlot(trans_mat)
流石にこれでは不格好なので、オプションを用いて整形したのが以下になります。
transitionPlot(trans_mat, overlap_add_width=1.2,type_of_arrow="gradient", min_lwd = unit(2, "mm"), max_lwd = unit(15, "mm"),cex=1.5)
delmonteがちょっと切れてますが、悪くないのではないでしょうか。
オプションによって個々のボックスの色や矢印の色などかなり自由に変更できるので、頑張ればもっと綺麗な図が描けると思います。(色の選択や割合表示については元のページ参照)
ブランド選択を可視化したことで、初回購入はheintzの割合が多いけれど、2回目購入ではheintzからhuntsやstbに遷移する顧客が多いことがわかります。また、初回でstbを購入した顧客はブランド遷移せず、stbを使い続けるようです。もし2回目以降の遷移においても同様の傾向が続くなら、購入回数が多くなればなるほどstbを購入する顧客が増えるといったことがこの図から予測できます。
データ分析的にはこれだけだと微妙ですが、例えば、stb購入者のLTV(Life Time Value)が高いといったことが別の分析でわかれば、heintzを購入した人にstbを購入するようなキャンペーンを打ちましょうとか、初回にstbをもっと買わせましょう、といったアクションの提案があり得るのではないでしょうか。
感想
データの可視化はマーケティングを行う上で非常に重要なので、ブランドやカテゴリの遷移を簡単に図示できるのは魅力的だと思います。状態遷移に興味がある場合、使ってみるのはありなのではないでしょうか。
ただ試してみた限りまだ使いにくい所もあって、主に以下の様な点を残念に感じました。
1. 始点と終点のみの2点間の遷移しか扱えない。
2. 始点と終点の状態数が同じものしか扱えない。
3. 文字のサイズを一律にしか変えられない。
1と2の理由のため、有限オートマトンのような前と後の状態が固定された状況でしか使えません。そのためマルコフ状態遷移の1ステップの可視化などには有用ですが、Webサイトにおけるトップページを起点としたページ推移の把握やCVに至るまでの初回・中間・ラストの接触広告を追うといった分析には使えなさそうです。
また、3の理由のため上の図のdelmonteだけ小さくするといったことができないので、ここを直そうとするならbox_txtによってテキストを消して別の画像処理ツール(ペイントやパワポ)で追記するといった対応が必要でしょう。
これらの点に関しては、今後のアップデートに期待ですね。