実践で学ぶネットワーク分析

32,213 views

Published on

第32回R勉強会@東京(#TokyoR)で発表した資料です。

Published in: Technology

実践で学ぶネットワーク分析

  1. 1. 実践で学ぶネットワーク分析 第32回R勉強会@東京(#TokyoR) 2013/7/20 @sato_mitsunori マーケティング分析担当者のお仕事から mitsunori.sato@gmail.com 佐藤 満紀
  2. 2. 2013.07.20 第32回R勉強会@東京(#TokyoR) 2 自己紹介 名前 :佐藤 満紀(@sato_mitsunori) 出身 :山形県 酒田市 仕事 :花王株式会社 趣味 :スキー それまでは 情報システム部門で社内SE (10数年経験) デジタル ビジネス マネジメント室 (現職 ※もうすぐ10年) マーケティング部門でデータ解析を担当しています
  3. 3. 2013.07.20 第32回R勉強会@東京(#TokyoR) 3 コトラーさん10年ぶりの来日公演 http://markezine.jp/article/detail/17989 コトラーさんは低迷する日本を語った。とのこと 「いいものをつくれば勝てるという考えは間違っている。 顧客を知ることも大切です」 引用: この人がコトラーさん 現代マーケティングの 第一人者 STP理論や4Pなどが 有名です 6/17
  4. 4. 2013.07.20 第32回R勉強会@東京(#TokyoR) 4 マーケティングの分析 因子分析 コレスポンデンス分析 クラスター分析 : http://www.slideshare.net/yokkuns/r-22276096 Rで学ぶマーケティング分析 競争ポジショニング戦略 TokyoR#31で@yokkunsさんも発表してます マーケティングの分野で実践しているネットワーク分析をご紹介 本日のお話し ・ネットワーク分析に興味関心が出てくるかも... ・事業の成長に貢献できるかもしれない分析をしてみたくなるかも... 嗜好が多様化した現在、基本的な属性では意味ある グループが出来なくなってきている
  5. 5. 2013.07.20 第32回R勉強会@東京(#TokyoR) 5 ネットワーク分析って何? 人間関係、企業間の関係、生物間の関係、遺伝子間の関係、コンピュータネットワークなど、 さまざまな分野で活用されてます。グラフ理論をベースとした分析手法です。 http://www.tokyometro.jp/station/index.html引用:  いくつに分類できそう  重要そうな場所ってどこ などなど ・・・コミュニティ抽出 ・・・中心性指標  なんといってもわかりやすい!
  6. 6. 2013.07.20 第32回R勉強会@東京(#TokyoR) 6 ネットワーク分析の資料たくさんあります TokyoR主催者 @yokkunsさんのブログ CodeIQの中の人 @millionsmileさんの資料 http://geocities.yahoo.co.jp/gl/snatool Rで学ぶデータサイエンス8 ネットワーク分析の著者 鈴木務氏のブログ Cytoscape開発メンバー 大野圭一朗氏の資料 TokyoWebmining#10 http://www.slideshare.net/hirokoonari http://codeiq.hatenablog.com/entry/2013/06/25/182324 http://d.hatena.ne.jp/yokkuns/20120819/1345380060 九州工業大学 竹本先生の資料と補足情報 http://www.slideshare.net/kztakemoto/r-seminar-on-igraph https://sites.google.com/site/kztakemoto/r-seminar-on-igraph---supplementary-information 私のブログ http://deta.hateblo.jp/entry/2013/05/01/053426 http://deta.hateblo.jp/entry/2013/05/08/053707 他にもありますよ http://www.slideshare.net/keiono/cytoscape CodeIQ竹本先生出題問題の解説記事
  7. 7. 2013.07.20 第32回R勉強会@東京(#TokyoR) 7 ネットワーク図とデータ 1 2 3 4 1 0 1 1 1 2 1 0 1 0 3 1 1 0 0 4 1 0 0 0 1 3 4 2 ネットワーク図 隣接行列 adjacency matrix 辺リスト graph edge list i j 無向グラフ 重みなし 辺 edge link 頂点 node vertex i j 1 2 1 3 1 4 2 3 ※対象行列なので 重複分は省略
  8. 8. 2013.07.20 第32回R勉強会@東京(#TokyoR) 8 ネットワーク図とデータ 1 2 3 4 1 0 1 0 1 2 0 0 0 0 3 1 1 0 0 4 0 0 0 0 1 3 4 2 ネットワーク図 隣接行列 adjacency matrix 辺リスト graph edge list i j 有向グラフ 重みなし i j 1 2 1 4 3 1 3 2
  9. 9. 2013.07.20 第32回R勉強会@東京(#TokyoR) 9 ネットワーク図とデータ 1 2 3 4 1 0 1 0 5 2 0 0 0 0 3 3 1 0 0 4 0 0 0 0 1 3 4 2 i j weight 1 2 1 1 4 5 3 1 3 3 2 1 ネットワーク図 隣接行列 adjacency matrix 辺リスト graph edge list i j 有向グラフ 重み付き
  10. 10. 2013.07.20 第32回R勉強会@東京(#TokyoR) 10 ここからのお話し ネットワーク図とデータの関係が分かりましたね。 1. 既に2変数の関係が分かっている場合 2つの関係が連なるデータがあればネットワーク分析は始められます。 2. 2変数の関係が分からない場合
  11. 11. 2013.07.20 第32回R勉強会@東京(#TokyoR) 11 こんなデータも使えそうです この商品を買った人は こんな商品も買っています ハイネケン 世界170ヶ国以上で親 しまれている欧州最大 のビールメーカー コロナ・エキストラ 世界160ヵ国で販売さ れている世界で最も飲 まれているプレミアム メキシカンビール オランジブーン オランダ王室・オラニ エ家が認めた最高品質 の本場ドイツのプレミ アムラガービール オリオンドラフト 爽快な喉ごし、マイル ドな味わい」沖縄生ま れの爽やか生ビール」 有向グラフが 描けそう...
  12. 12. 2013.07.20 第32回R勉強会@東京(#TokyoR) 12 たくさん収集するとこんなネットワーク図が描けます
  13. 13. 2013.07.20 第32回R勉強会@東京(#TokyoR) 13 どうやって収集するの? 1.コピペ 2.クローラーを作る 3.APIを使う 少しだけ Ruby+APIによるデータ収集について お話しします。 + アマゾンさんのデータ
  14. 14. 2013.07.20 第32回R勉強会@東京(#TokyoR) 14 Amazon Product Advertising API 開発者ガイド https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html いろいろありますが、私がよく使うのは3つ SimilarityLookup ・・・ 関連商品を返す ItemSearch ・・・ 商品検索結果を返す BrowseNodeLookup ・・・ 画面の階層を返す ※商品検索に指定するパラメータを確認時に使用
  15. 15. 2013.07.20 第32回R勉強会@東京(#TokyoR) 15 使用するには登録が必要 1.Amazonアソシエイト・プログラムへの参加 2.Product Advertising APIアカウントの作成 詳しくは Amazon API 利用 検索 https://affiliate.amazon.co.jp/ 3.Access Key ID と Secret Access Keyの取得
  16. 16. 2013.07.20 第32回R勉強会@東京(#TokyoR) 16 Rubyで実行する場合 ruby-aaws ライブラリを使いました amazon-ecs というのもあります ruby-aaws をインストールする 下記サイトで最新版をダウンロードしてローカルファイルからインストール http://www.caliban.org/ruby/ruby-aws/ > gem install ruby-aaws-0.8.1 --local コーディング時のおまじない ENV['AMAZONRCDIR'] = 'd:/ruby' ENV['AMAZONRCFILE'] = 'amazonrc‘ require 'rubygems' require 'amazon/aws/search' require 'kconv' include Amazon::AWS include Amazon::AWS::Search [global] key_id = ‘xxxxxxxxxx' secret_key_id = ‘yyyyyyyyyy' Associate = ‘zzzzzzzzzz' cache = false locale = 'jp' encoding = 'utf-8' d:/ruby/amazonrc アクセスに必要な情報 を準備したファイルを 環境変数として指定し ます。 私の環境は win7 32bit ruby 1.8.7
  17. 17. 2013.07.20 第32回R勉強会@東京(#TokyoR) 17 商品を検索する ENV['AMAZONRCDIR'] = 'd:/ruby' ENV['AMAZONRCFILE'] = 'amazonrc' require 'rubygems' require 'amazon/aws/search' require 'kconv' include Amazon::AWS include Amazon::AWS::Search # ItemSearch is = ItemSearch.new('Grocery', {'BrowseNode' => 71588051', 'Sort' => 'salesrank', 'ItemPage' => 1}) request = Request.new is.response_group = ResponseGroup.new(:SalesRank, :ItemAttributes) result = request.search(is) items = result.item_search_response.items.item items.each do |item| asinCd = item.asin.to_s.kconv(Kconv::SJIS, Kconv::UTF8) salesRank = item.sales_rank.to_s.kconv(Kconv::SJIS, Kconv::UTF8) title = item.item_attributes.title.to_s.kconv(Kconv::SJIS, Kconv::UTF8) puts asinCd + "¥t" + salesRank + "¥t" + title end 食品&飲料 > お酒 売れている順番 1ページ目 1ページには 最大10個の商品 出力したい要素のグループ ItemSearch D:¥>ruby ItemSearch.rb B00C2HNT70 アサヒ ウィルキンソン タンサン B00CE5OCOE サントリー オールフリー ノンアルコールテイスト飲料 B00C2HNXIA アサヒ ウィルキンソン タンサン レモン B0055ZF0G4 97 アサヒ ウィルキンソン 炭酸水 500ペット 48本セット(24本×2) B0058GJCPA 181 アサヒ スーパードライ 350ml×24本 B007MM6SL4 124 アサヒ ウィルキンソン 炭酸水 500ペット 48本セット(24本×2) B007JSMAKE 172 発泡清酒 すず音 300ml×3本セット ※詳細は開発者ガイドをお読みください 親コードの考え方があります。 親は子をバリエーションとして もってます。 バリエーションを知るには ResponseGroupでVariationsな どを追加指定する必要があります。
  18. 18. 2013.07.20 第32回R勉強会@東京(#TokyoR) 18 関連商品を得る # SimilarityLookup sl = SimilarityLookup.new(‘B0058GJCPA') request = Request.new sl.response_group = ResponseGroup.new(:ItemIds) result = request.search(sl) items = result.similarity_lookup_response.items.item items.each do |item| puts item.asin.to_s.kconv(Kconv::SJIS, Kconv::UTF8) end ENV['AMAZONRCDIR'] = 'd:/ruby' ENV['AMAZONRCFILE'] = 'amazonrc' require 'rubygems' require 'amazon/aws/search' require 'kconv' include Amazon::AWS include Amazon::AWS::Search SimilarityLookup D:¥>ruby SimilarityLookup.rb B001TZ8T2G B0058GGD0C B0058GJCAU B007JGLC8C B007JGLDE0 B001TZ8SYK B0045TIEXC B001TZ5QMM B001TZAQCW アサヒ スーパードライ 350ml×24本 ※カンマ区切りで最大10個の商品を指定可能 出力したい要素のグループ 1つの商品につき最大10個の商品を得られる 親コードに関連商品はありません。 子コードを与える必要があります。
  19. 19. 2013.07.20 第32回R勉強会@東京(#TokyoR) 19 こんなデータを取得 :2013/7/11 21:30 ~ 2013/7/16 06:30期間 :3時間 ※36回観測取得間隔 対象商品 :食品&飲料 > お酒 SearchIndex = ‘Grocery’ BrowseNode = ‘71588051’ :1.ItemSerchで上位100商品を検索 2.得られた100品を対象にSimilarityLookup で関連商品を取得 3.得られたランキングと関連商品を蓄積 処理概要
  20. 20. 2013.07.20 第32回R勉強会@東京(#TokyoR) 20 AsinCd SimAsinCd Freq B000TKDCII B000TKDD3M 18 B000TKDCII B001U9RROW 18 B000TKDCII B004725OLM 18 B000TKDCII B004MXP90C 18 B000TKDCII B004VCYOIC 18 B000TKDCII B007XO5IZ8 18 B000TKDCII B00889VRQQ 18 B000TKDCII B00B7W783W 18 B000TKDCII B00BMMQWIE 18 B000TKDCII B00CLPRH5S 18 B001TZ3XC2 B001TZ42VS 6 B001TZ3XC2 B0029Z8ZS8 6 B001TZ3XC2 B0034XUQO0 6 B001TZ3XC2 B0034XZQ6S 6 B001TZ3XC2 B003V3RPWY 6 B001TZ3XC2 B005C28GES 6 B001TZ3XC2 B005VB4IGA 6 B001TZ3XC2 B005VZXQCI 6 B001TZ3XC2 B0061JPA4K 6 B001TZ3XC2 B00DAMON8U 6 B001TZ40YC B0029ZEGX6 36 B001TZ40YC B002LI64FE 36 DateTime AsinCd SEQ SimAsinCd 20130711213001 B001TZ40YC 1 B0045TGOW0 20130711213001 B001TZ40YC 2 B002LI64FE 20130711213001 B001TZ40YC 3 B0045TESKU 20130711213001 B001TZ40YC 4 B00CGZ3DEW 20130711213001 B001TZ40YC 5 B0029ZEGX6 20130711213001 B001TZ40YC 6 B0058GGRP8 20130711213001 B001TZ40YC 7 B00BMFYO86 20130711213001 B001TZ40YC 8 B0058GJCPA 20130711213001 B001TZ40YC 9 B004N5GYMG 20130711213001 B001TZ40YC 10 B00B54N9D0 20130711213001 B001TZ7EWC 1 B005BBCDBM 20130711213001 B001TZ7EWC 2 B004SEUR16 20130711213001 B001TZ7EWC 3 B00739WJ28 20130711213001 B001TZ7EWC 4 B0054HKMGQ 20130711213001 B001TZ7EWC 5 B0058GGLHC 20130711213001 B001TZ7EWC 6 B0029Z4QN6 20130711213001 B001TZ7EWC 7 B0045TMJUQ 20130711213001 B001TZ7EWC 8 B004N5GYMG 20130711213001 B001TZ7EWC 9 B005BBCHMW 20130711213001 B001TZ7EWC 10 B004R9NV1K 20130711213001 B001TZ8SLI 1 B0034W35MQ 20130711213001 B001TZ8SLI 2 B0049DUQ4Y 実際のデータ 蓄積したデータ 集計結果(エッジリスト.txt) + igraph : : 観測日時 この商品を 買った人は こんな商品も 買ってます この商品を 買った人は こんな商品も 買ってます 出現 頻度 35,562件 1,488件 集計
  21. 21. 2013.07.20 第32回R勉強会@東京(#TokyoR) 21 Rで出現頻度の確認 d <- read.table("エッジリスト.txt", header=T) # データフレームで読込み hist(d$Freq, breaks=seq(1, 40, 1)) #ヒストグラム この分布は... 今回は毎回出現してい るレコメンドの構造を 分析してみよう ここ ↓
  22. 22. 2013.07.20 第32回R勉強会@東京(#TokyoR) 22 igraphでデータ読み込みと描画 library(igraph) d <- subset(d, Freq>=36) # 条件抽出(出現頻度36以上を対象にする) g <- graph.data.frame(d[,1:2], directed = TRUE) # データフレームからグラフに変換 plot.igraph(g, #ネットワーク図を描画 vertex.size=3, #ノードの大きさ vertex.label.cex=0.2, #ノードラベルの文字サイズ edge.width=1, #エッジの太さ edge.arrow.size=0.1, #エッジの矢印サイズ layout=layout.fruchterman.reingold) #ネットワークのレイアウト手法 他ファイル形式の読み込みなど g <- graph.adjacency(“隣接行列データ名”, weighted=, mode= ) # 隣接行列からグラフ変換 g <- read.graph(“各種グラフ形式データ名”, format=, directed=T) # 他のグラフ形式からの読み込み g <- simplify(g, remove.multiple = TRUE, remove.loops = TRUE) # 多重エッジや自己ループの削除 E(g)$weight <- d[,3] # エッジの重み設定をする場合 graphml、gml など複数の形式に対応
  23. 23. 2013.07.20 第32回R勉強会@東京(#TokyoR) 23 でたぁっ 毎回出現したレコメンドの構造 plot.igraphで描画した結果 tkplot関数だと別画面 ※この画面ではマウスを使いノードを動かせます
  24. 24. 2013.07.20 第32回R勉強会@東京(#TokyoR) 24 でたぁっ 毎回出現したレコメンドの構造 plot.igraphで描画した結果 tkplot関数だと別画面 ※マウスでノードを動かせます 1.重要そうな商品(ノード)がありそう ⇒ 中心性指標 2.比較的密に連結した部分構造がありそう ⇒ コミュニティ抽出 3.igraphは描画が苦手? ⇒ 綺麗に描画できるソフトを使おう
  25. 25. 2013.07.20 第32回R勉強会@東京(#TokyoR) 25 中心性指標の算出 igraphに実装されている中心性指標 degree(g) # 次数中心性 closeness(g) # 近接中心性 evcent(g)$vector # 固有ベクトル中心性 page.rank(g, directed=FALSE)$vector # ページランク betweenness(g) # 媒介中心性 bonpow(g, exponent = 0.2) # ボナチッチのパワー中心性 先ほどのデータで媒介中心性を算出しファイル出力するコード bw.df <- as.data.frame(betweenness(g, directed=TRUE, weights=NULL)) # 媒介中心性 bw.df <- cbind(rownames(bw.df), bw.df) #行タイトルになるノード名をデータフレームに追加 colnames(bw.df) <- c("AsinCd", "betweenness") # 列名変更 write.table(bw.df, "媒介中心性.txt", row.name=F, col.names=T, sep="¥t", quote=F, append=F) # ファイル出力 媒介中心性.txt のイメージ AsinCd betweenness B001TZ40YC 269.84 B001TZ8SYK 570.53 B001TZ8T2G 185.47 B0022ZVGYU 21.00 媒介中心性はネットワークにおける媒介や伝達に着目した指標 ブリッジになるようなノードを評価してくれます 私はよく使います
  26. 26. 2013.07.20 第32回R勉強会@東京(#TokyoR) 26 コミュニティ抽出 コミュニティ検出の基礎 igraphに実装されているコミュニティ抽出手法 edge.betweenness.community(g) # 辺媒介性を用いた手法 walktrap.community(g) # ランダムウォーク fastgreedy.community(g) # 貪欲法に基づく手法 leading.eigenvector.community(g) # 固有ベクトルに基づく手法 multilevel.community(g) # 多段階最適アルゴリズム spinglass.community(g) # 焼きなまし法 optimal.community(g) # 全探索 先ほどのデータで焼きなまし法を実行 > sp <- spinglass.community(g) # 焼きなまし法 分割を探す 以下にエラー spinglass.community(g) : At clustertool.cpp:285 : Cannot work with unconnected graph, Invalid value グラフが連結していない場合、エラーが出ることがあります 計算時間では貪欲法が最短 検出精度では焼きなまし法が最高 とのこと  ji ij ji ij cc E kk A E Q , 22 1         右式のように定義されるQ値(Clauset et al. 2004)が最大となるよう なメンバーシップを見つける問題 http://codeiq.hatenablog.com/entry/2013/06/25/182324引用: コミュニティ内のエッジ密度が偶 然に得られるそれと比較してどの 程度大きいか」を表す指標
  27. 27. 2013.07.20 第32回R勉強会@東京(#TokyoR) 27 でたぁっ 毎回出現したレコメンドの構造 plot.igraphで描画した結果 tkplot関数だと別画面 ① ② ③ ④ ⑤ ⑥ ⑦⑧ ⑨ そういえば9個の ネットワークがあった ※この画面ではマウスを使いノードを動かせます
  28. 28. 2013.07.20 第32回R勉強会@東京(#TokyoR) 28 グラフの連結成分を確認 > g.cl <- clusters(g) #連結成分を確認 > g.cl$no # 連結成分の数 [1] 9 > g.cl$csize # 連結成分のサイズ [1] 265 17 12 11 18 11 8 17 10 > g.cl$membership # 連結成分 [1] 1 1 1 1 1 1 1 2 3 3 1 1 1 1 4 5 6 1 1 1 1 1 1 1 2 7 1 8 5 1 1 1 1 1 1 1 1 [38] 1 1 1 9 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1 1 1 9 1 1 1 [75] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 [112] 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 1 1 1 1 1 [149] 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 [186] 6 6 6 6 6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 7 7 7 7 7 7 7 [223] 1 1 8 8 8 8 8 8 8 8 8 8 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 [260] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9 9 9 9 9 9 9 1 1 1 1 1 1 1 1 1 [297] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 [334] 1 1 1 1 1 1 1 1 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9 1 1 1 1 1 1 1 1 9個のネットワークの存在を確認 各ネットワークのノード数 該当する連結成分 cluster関数 連結成分ごとに コミュニティ抽出しなく ちゃいけないのか... どうしよう...
  29. 29. 2013.07.20 第32回R勉強会@東京(#TokyoR) 29 連結成分でグラフデータを分割 > dcg <- decompose.graph(g) # 連結成分でグラフを分割する > length(dcg) # グラフの連結数 [1] 9 > dcg # 分割されたグラフ [[1]] IGRAPH DN-- 265 532 -- + attr: name (v/c) [[2]] IGRAPH DN-- 17 19 -- + attr: name (v/c) (中略) [[9]] IGRAPH DN-- 10 16 -- + attr: name (v/c) > igraphのマニュアル、 約300ページもある しかも英語... でも必要なときは読むもんだ... よかった... decompose.graph関数は 連結成分ごとにグラフを分割 してくれます! ありました便利な関数!
  30. 30. 2013.07.20 第32回R勉強会@東京(#TokyoR) 30 連結成分ごとにコミュニティ抽出 dcg <- decompose.graph(g) # 連結成分でグラフを分割する # 連結ネットワーク単位にコミュニティと中心性を計算する sp.df.all <- c() # コミュニティ抽出結果用データフレーム for (i in 1:length(dcg)){ set.seed(1) # シードを固定 sp <- spinglass.community(dcg[[i]]) # 焼きなまし法 sp.df <- cbind(i, as.data.frame(sp$names), as.data.frame(sp$membership)) # DF形式に変換 sp.df.all <- rbind(sp.df.all, sp.df) # コミュニティー抽出結果を追加 } colnames(sp.df.all) <- c("i", "AsinCd", "community") # 列名変更 write.table(sp.df.all, "コミュニティ.txt", row.name=F, col.names=T, sep="¥t", quote=F, append=F) # ファイル出力 i AsinCd community 1 B001TZ40YC 9 1 B001TZ8SYK 5 1 B001TZ8T2G 5 1 B0022ZVGYU 7 コミュニティ.txt のイメージ これでどの商品がどのコミュニティに属する か分析できました。 ※iは連結成分の単位
  31. 31. 2013.07.20 第32回R勉強会@東京(#TokyoR) 31 ネットワーク図の描画ソフト 綺麗に描きたいなら下記2つがおすすめ 他にもあるようです Pajek、Graphviz、ZoomGraph、UCINET、Agna、 NodeXL(Excel)、NetworkX(Python) http://www.cytoscape.org/ https://gephi.org/
  32. 32. 2013.07.20 第32回R勉強会@東京(#TokyoR) 32 Cytoscapeでファイルを読込む ① ② ver2.8.3 読込むエッジリスト ファイルを指定します ノード属性を使い、色や大 きさ、形を変えたい場合に 該当ファイルを指定します。 ・中心性指標 ・コミュニティー など、いくつでも可 ※操作方法の詳細は割愛させて頂きます Exportで ファイル出力 ができます
  33. 33. 2013.07.20 第32回R勉強会@東京(#TokyoR) 33 読込んだグラフを配置する ver2.8.3 配置レイアウトを指定します Organicをよく使います 自分で動かすことも可能です マウスのホイールで拡大縮小で きます 見ているグラフの範囲 移動させる時はこの画面上 で動かします
  34. 34. 2013.07.20 第32回R勉強会@東京(#TokyoR) 34 綺麗にカスタマイズする ver2.8.3 ノードやエッジを選択したいときなどに Filtersタグを使います 変更したい要素をダブルクリックします ダブルクリックされた要素は上段に移動し カスタマイズ可能になります 上段にある要素はカスタマイズ可能です カスタマイズにはいくつかの指定方法があります 条件によらず、色・大きさ・形などを 共通で設定することができます
  35. 35. 諸般の事情により商品名と商品画像は非公開
  36. 36. 2013.07.20 第32回R勉強会@東京(#TokyoR) 36 お酒のレコメンドネットワーク by Amazon
  37. 37. 2013.07.20 第32回R勉強会@東京(#TokyoR) 37 お酒のレコメンドネットワーク by Amazon 媒介中心性で ノード色を変更
  38. 38. 2013.07.20 第32回R勉強会@東京(#TokyoR) 38 お酒のレコメンドネットワーク by Amazon コミュニティで ノード色を変更 ※焼きなまし法
  39. 39. 2013.07.20 第32回R勉強会@東京(#TokyoR) 39 お酒のレコメンドネットワーク by Amazon コミュニティで ノード色を変更 ※焼きなまし法 ビール ビールギフト 某炭酸飲料 某ミネラル ウォーターノンアルコール 飲料
  40. 40. 2013.07.20 第32回R勉強会@東京(#TokyoR) 40 紹介できなかった分析 ネットワークの比較(演算) オーバーラッピング手法によるコミュニティ抽出 graph.union.by.name(g1, g2) # 和 graph.intersection.by.name(g1, g2) # 積 graph.difference.by.name(g1, g2) # 差 igraphパッケージ ※向きは無効です。2つのグラフの比較が容易に行えます。 本日ご紹介したコミュニティ抽出は全てノンオーバーラッピング手法です。 ノードをいづれかのコミュニティに分類する手法です。 オーバーラッピング手法は、ノードが複数のコミュニティに属することを許す 分類手法です。(私はエッジを分類していると理解していま) linkcomパッケージでは下記2つの手法が実装されております。 ・Link communities ・Overlapping cluster generator
  41. 41. 2013.07.20 第32回R勉強会@東京(#TokyoR) 41 ここからのお話し ネットワーク図とデータの関係が分かりましたね。 1. 既に2変数の関係が分かっている場合 2つの関係が連なるデータがあればネットワーク分析は始められます。 2. 2変数の関係が分からない場合
  42. 42. 2013.07.20 第32回R勉強会@東京(#TokyoR) 42 実際には... 2変数の関係が分かっているデータが ないこともよくあります 2変数の関係を測る分析が必要です
  43. 43. 2013.07.20 第32回R勉強会@東京(#TokyoR) 43 2変数の関係を測る指標 様々な2変数の関係を測る指標があります Jaccard係数、Cosine係数、・・・ Rで学ぶデータサイエンス2 多次元データ解析法 第11章 クラスター分析法 11.2 近さを表す測度 に、量的・質的データの距離、類似度の定義が たくさん掲載されております。
  44. 44. 2013.07.20 第32回R勉強会@東京(#TokyoR) 44 購買履歴データを使った分析に挑戦! 1.購買履歴データ 2.よく買われる商品 3.ネットワーク分析・描画 アソシエーション分析などがよく 知られています おむつを買う人はビールをよく買 う法則(都市伝説?)を発見したと言 われている分析 顧客ID 商品コード 個数 ある期間の購買履歴を集計 件数=72,931件 顧客数=17,894人 商品数=56品
  45. 45. 2013.07.20 第32回R勉強会@東京(#TokyoR) 45 アソシエーション分析 購買履歴データから、何と何がよく買われているかを発見するデータマイニングの分析手法の1つ Albertさんのページ、TokyoR#22で発表された@bob3bob3さんの資料がよく解ります http://www.albert2005.co.jp/technology/mining/method2.html http://www.slideshare.net/bob3/tokyo-r22 支持度 (support、同時確率) リフト値 (lift、改善率) 確信度 (confidence、条件付き確率) ビール(Y) 非購入 購入 合計 おむつ (X) 非購入 2 2 4 購入 0 6 6 合計 2 8 10 条件部(X) 結論部(Y) 結論部前提確率 支持度 確信度 リフト値 おむつ ビール 8÷10=0.8 6÷10=0.6 6÷6=1.00 1.00÷0.8=1.25 ビール おむつ 6÷10=0.6 6÷10=0.6 6÷8=0.75 0.75÷0.6=1.25 全体の中でXとYを両方含むトランザクションタの比率 Xを含むトランザクションのうちYを含む比率 確信度を前提確率で割ったもの 前提確率 全体の中でYを含むトランザクションの比率 リフト値の1.25って... 有意判定とかできないの?
  46. 46. 2013.07.20 第32回R勉強会@東京(#TokyoR) 46 統計的手法なら... ビール(Y) 非購入 購入 合計 おむつ (X) 非購入 2 2 4 購入 0 6 6 合計 2 8 10 おむつとビールを購入する人の 期待値は、6×8÷10=4.8人 観測値は6人だから 期待値より1.2人多いようです 調整残差=               nn 行計列計 期待値 期待値観測値 11 期待値=列計×行計÷全体 調整残差は1.936となります 5%水準では有意とはいえません 有意水準1% 有意水準5% : 2.58以上 : 1.96以上 調整残差(調整済み残差) クロス集計表のあるセルの観測値が期待値に比べ有意な差があるか検定する手法 Rだとカイ2乗検定を行うchisq.test関数があります chisq.test(クロス集計データ)$stdresで統計量を得ることができます ええっー! そうなの?
  47. 47. 2013.07.20 第32回R勉強会@東京(#TokyoR) 47 統計的手法なら... おむつとビールを購入する人の 期待値は、60×80÷100=48人 観測値は60人だから 期待値より12人多いようです 調整残差=               nn 行計列計 期待値 期待値観測値 11 期待値=列計×行計÷全体 調整残差は6.124となります 0.1%水準でも有意! 有意水準1% 有意水準5% : 2.58以上 : 1.96以上 nが大きくなると統計量は大きくな り有意判定は出やすくなります。 今回は、統計量を特徴の大小を測 る指標として使ってみます。 各セルの人数を10倍にしてみました 調整残差(調整済み残差) クロス集計表のあるセルの観測値が期待値に比べ有意な差があるか検定する手法 Rだとカイ2乗検定を行うchisq.test関数があります chisq.test(クロス集計データ)$stdresで統計量を得ることができます ビール(Y) 非購入 購入 合計 おむつ (X) 非購入 20 20 40 購入 0 60 60 合計 20 80 100
  48. 48. 2013.07.20 第32回R勉強会@東京(#TokyoR) 48 購買履歴データを使った分析に挑戦! 1.購買履歴データ 2.よく買われる商品 3.ネットワーク分析・描画 今回は、 統計量(調整残差)で 併買の特徴度合いを評価 してみます 顧客ID 商品コード 個数 ある期間の購買履歴を集計 件数=72,931件 顧客数=17,894人 商品数=56品
  49. 49. 2013.07.20 第32回R勉強会@東京(#TokyoR) 49 購買履歴から全商品の調整残差を求める 顧客ID 商品コード 個数 顧客1 商品1 1 顧客1 商品4 3 顧客2 商品5 2 : : : 顧客17894 商品1 1 商品1 商品2 ・・・ 商品56 顧客1 顧客1 顧客2 : 顧客17894 商品1 商品2 ・・・ 商品56 商品1 商品2 : 商品56 購買履歴 顧客×商品 行列 調整残差行列商品数は56品 1,540通りの組合せ どうやって全組み合わせの 調整残差を求めよう 72,931件 1,540件 ※対角成分のみ
  50. 50. 2013.07.20 第32回R勉強会@東京(#TokyoR) 50 購買履歴から全商品の調整残差を求める 顧客ID 商品コード 個数 顧客1 商品1 1 顧客1 商品4 3 顧客2 商品5 2 : : : 顧客17894 商品1 1 購買履歴 72,931件 商品X 商品Y 調整残差 顧客1 商品2 顧客1 商品3 顧客1 商品4 : : 顧客55 商品56 1,540件 慣れているSQLなら一発計算 できるのに... Rにはデータフレームに対し SQLを実行できるsqldfパッケージ があった。 計算したエッジリストなら igraphでネットワーク分析も 出来るぞ 辺リスト
  51. 51. 2013.07.20 第32回R勉強会@東京(#TokyoR) 51 sqldfパッケージで全商品の組合せの調整残差計算 library(sqldf) d <- read.table("購買履歴データ.txt", header=T) # データフレームで読込み 1列目:CustID、2列目:ItemID、3列目:Qty ※Qtyは未使用 res <- sqldf(" select T1.ItemX as ItemX, T1.ItemY as ItemY, coalesce(T2.CustCount, 0) as BuyX, coalesce(T3.CustCount, 0) as BuyY, coalesce(T4.CustCount, 0) as BuyXY from ( --商品の組合せ n(n-1)/2 通り select T1.ItemId as ItemX, T2.ItemId as ItemY from (select ItemID from d group by ItemID) as T1 inner join (select ItemID from d group by ItemID) as T2 on T1.ItemId < T2.ItemId ) as T1 --商品Xの購買者数 left outer join (select T1.ItemId as ItemX, count(T1.CustID) as CustCount from d as T1 group by T1.ItemId) as T2 on T1.ItemX = T2.ItemX --商品Yの購買者数 left outer join (select T1.ItemId as ItemY, count(T1.CustID) as CustCount from d as T1 group by T1.ItemId) as T3 on T1.ItemY = T3.ItemY --商品XYの購買者数 left outer join ( select T1.ItemId as ItemX, T2.ItemId as ItemY, count(T1.CustID) as CustCount from d as T1 inner join d as T2 on T1.CustID = T2.CustID and T1.ItemId < T2.ItemId group by T1.ItemId, T2.ItemId ) as T4 on T1.ItemX = T4.ItemX and T1.ItemY = T4.ItemY ") res$n <- as.numeric(sqldf("select count(CustID) as n from (select CustID from d group by CustID)")) # ユニークモニターID res$BuyXY.est <- res$BuyX * res$BuyY / res$n # 併買者の期待数 res$BuyXY.stdres <- (res$BuyXY - res$BuyXY.est) / sqrt(res$BuyXY.est * (1 - res$BuyX / res$n) * (1 - res$BuyY / res$n)) # 調整残差 res$support <- res$BuyXY / res$n # アソシエーション分析の指示度 res$lift <- (res$BuyXY * res$n) / (res$BuyX * res$BuyY) # アソシエーション分析のリフト 1~2秒で終わります
  52. 52. 2013.07.20 第32回R勉強会@東京(#TokyoR) 52 sqldfパッケージで全商品の組合せの調整残差計算 library(sqldf) d <- read.table("購買履歴データ.txt", header=T) # データフレームで読込み 1列目:CustID、2列目:ItemID、3列目:Qty ※Qtyは未使用 res <- sqldf(" select T1.ItemX as ItemX, T1.ItemY as ItemY, coalesce(T2.CustCount, 0) as BuyX, coalesce(T3.CustCount, 0) as BuyY, coalesce(T4.CustCount, 0) as BuyXY from ( --商品の組合せ n(n-1)/2 通り select T1.ItemId as ItemX, T2.ItemId as ItemY from (select ItemID from d group by ItemID) as T1 inner join (select ItemID from d group by ItemID) as T2 on T1.ItemId < T2.ItemId ) as T1 --商品Xの購買者数 left outer join (select T1.ItemId as ItemX, count(T1.CustID) as CustCount from d as T1 group by T1.ItemId) as T2 on T1.ItemX = T2.ItemX --商品Yの購買者数 left outer join (select T1.ItemId as ItemY, count(T1.CustID) as CustCount from d as T1 group by T1.ItemId) as T3 on T1.ItemY = T3.ItemY --商品XYの購買者数 left outer join ( select T1.ItemId as ItemX, T2.ItemId as ItemY, count(T1.CustID) as CustCount from d as T1 inner join d as T2 on T1.CustID = T2.CustID and T1.ItemId < T2.ItemId group by T1.ItemId, T2.ItemId ) as T4 on T1.ItemX = T4.ItemX and T1.ItemY = T4.ItemY ") res$n <- as.numeric(sqldf("select count(CustID) as n from (select CustID from d group by CustID)")) # ユニークモニターID res$BuyXY.est <- res$BuyX * res$BuyY / res$n # 併買者の期待数 res$BuyXY.stdres <- (res$BuyXY - res$BuyXY.est) / sqrt(res$BuyXY.est * (1 - res$BuyX / res$n) * (1 - res$BuyY / res$n)) # 調整残差 res$support <- res$BuyXY / res$n # アソシエーション分析の指示度 res$lift <- (res$BuyXY * res$n) / (res$BuyX * res$BuyY) # アソシエーション分析のリフト 商品の組み合わせ 各商品の購買者数 併買者数 調整残差、アソシエーション分析の指標を計算
  53. 53. 2013.07.20 第32回R勉強会@東京(#TokyoR) 53 ItemX ItemY BuyX BuyY BuyXY n BuyXY.est BuyXY.stdres support lift 25 221 736 404 253 17,894 16.6 59.899 0.0141 15.23 5 14 3,362 2,592 1,338 17,894 487.0 46.274 0.0748 2.75 3 13 2,349 1,753 841 17,894 230.1 45.491 0.0470 3.65 7 8 1,955 2,013 738 17,894 219.9 39.290 0.0412 3.36 1 2 652 405 152 17,894 14.8 36.815 0.0085 10.30 202 203 537 765 186 17,894 23.0 35.313 0.0104 8.10 3 4 2,349 1,025 493 17,894 134.6 34.146 0.0276 3.66 3 22 2,349 1,714 644 17,894 225.0 31.517 0.0360 2.86 4 22 1,025 1,714 374 17,894 98.2 30.150 0.0209 3.81 3 11 2,349 1,138 472 17,894 149.4 29.265 0.0264 3.16 16 17 2,291 1,794 597 17,894 229.7 27.362 0.0334 2.60 214 215 2,012 253 156 17,894 28.4 25.566 0.0087 5.48 3 20 2,349 1,184 437 17,894 155.4 25.076 0.0244 2.81 実際の計算結果 観測値 期待値 調整残差 特徴的な組み合わせは、大きな値になります。 商品25 と 商品221 は、この分析の結果で見れば、 よく買われているペアであることが分かります。 : : 2変数の関係を測る分析が出来ました。 さあ、ネットワーク分析を始めましょう。
  54. 54. 2013.07.20 第32回R勉強会@東京(#TokyoR) 54 まとめ  ネットワーク図とデータ 隣接行列、エッジリストをイメージしましょう。 ※グラフ専用のデータフォーマットもあります。  2変数の関係が分かっていれば分析はすぐに始められます igraphを使うと 様々なデータフォーマットを読込むことが出来ます。 中心性指標計算やコミュニティ抽出が出来ます。 ※igraphには他にも様々な分析を行うことが出来る関数が実装されています。  2変数の関係が分かってなくても大丈夫! 様々な2変数の関係を測る指標があります。 課題に応じた分析、アルゴリズムを使用して特徴検出に挑戦しよう。 アンケート結果も可視化してみると結果の理解が深まりますよ。  ネットワーク分析の醍醐味は可視化? ネットワーク図は非常に優れたアウトプットです。 分析結果を生かす為の情報共有に非常に役立ちます。この図1枚でOK 路線図もそうですよね。
  55. 55. ご清聴どうもありがとうございました Thank you very much for your attention

×