2017-11-29 25 views
4

は私が大規模なデータが

df <- data.frame(group= c("a","a","b","b","b","c"), 
      person = c("Tom","Jerry","Tom","Anna","Sam","Nic"), stringsAsFactors = FALSE) 

df 
    group person 
1  a Tom 
2  a Jerry 
3  b Tom 
4  b Anna 
5  b Sam 
6  c Nic 

のような大規模なデータフレームを持っており、結果として取得したいと思いセットに共通の第3の検索

df.output 
    pers1 pers2 person_in_common 
1 Anna Jerry    Tom 
2 Jerry Sam    Tom 
3 Sam Tom    Anna 
4 Anna Tom    Sam 
6 Anna Sam    Tom 

結果データフレームは基本的に人物のすべてのペアを持つテーブルを与えます誰が共通しているのか。私はSQLでそれを行う方法を見つけましたが、かなり長い時間がかかりますので、効率的な方法があるのだろうかと思います。

答えて

2

ここではigraphパッケージを使用しています。基本的な考え方は、グラフを作成し、各ノードの2つの隣接ノードを抽出することです。

library(igraph) 
X1 = split(df$person, df$group) 
X2 = X1[lengths(X1) >= 2] 
dat = data.frame(do.call(rbind, unlist(lapply(X2, function(x) 
      combn(x, 2, sort, FALSE)), recursive = FALSE))) 
g = graph.data.frame(dat, directed = FALSE) 
mydf = data.frame(as.matrix(get.adjacency(g))) 
mydf = mydf[colSums(mydf) > 1] 
ANS = sapply(mydf, function(x) t(combn(row.names(mydf)[which(x == 1)], 2))) 
do.call(rbind, lapply(names(ANS), function(nm) data.frame(ANS[[nm]], nm))) 
#  X1 X2 nm 
#1 Sam Tom Anna 
#2 Anna Tom Sam 
#3 Jerry Anna Tom 
#4 Jerry Sam Tom 
#5 Anna Sam Tom 

OR

mynames = unique(do.call(c, X2)) 
do.call(rbind, 
     lapply(mynames, function(x){ 
      L = V(g)$name[unlist(adjacent_vertices(graph = g, v = x))] 
      if(length(L) >= 2){ 
       setNames(data.frame(t(combn(L, 2)), x), c("P1", "P2", "P3")) 
      }else{ 
       setNames(data.frame(NA, NA, x), c("P1", "P2", "P3")) 
      } 
     })) 
#  P1 P2 P3 
#1 Jerry Anna Tom 
#2 Jerry Sam Tom 
#3 Anna Sam Tom 
#4 <NA> <NA> Jerry 
#5 Sam Tom Anna 
#6 Anna Tom Sam 
+0

これは、設定された通常サイズのデータ​​に適していますが、私は 'mydf'隣接行列を設定しようとすると、私は私の実際のデータとメモリの問題に実行する(' G'がほとんどです1GBのサイズ)。 – user6617454

+1

私はそれを試みたが、私は行列が大きすぎると思う。まばらな行列で周辺をうろついていたが、それを理解できなかった。私はもう少しお試しいただき、それから一般的な問題を解決するあなたの答えを受け入れます。 – user6617454

+0

第2版@ d.bでクラッシュせず、まだ実行中です。私はあなたにそれがどのように行くのかを知らせます – user6617454

関連する問題