2016-08-23 1 views
0

Rで、リストをハッシュテーブルに変換し、特定の基準に従って類似した要素をグループ化する方法を探しています。特定の比較基準に従ってリストをソートします。R

詳細は、以下で説明するように「グラフ理論」に特有ですが、答えはいくつかの特定の基準に基づいてハッシュする一般的な手順だと思います。

リストは、(igraphパッケージの)「グラフ」オブジェクトで構成されています。

library(igraph) 

#Creating the list of graphs 
edgeList <- data.frame(
    idA=c(008, 001, 001, 010, 047, 002, 005, 005), 
    idB=c(100, 010, 020, 030, 030, 001, 011, 111) 
) 
edgeList$idB= edgeList$idB+0.1 
g <- graph_from_data_frame(edgeList, directed = TRUE) 
g_list <- decompose(g, mode = "weak") 

#from the 8 edges we obtain 5 graphs (connected components of the original graph) 

類似性基準は、グラフは同型でなければならないということです。

isomorphic(g_list[[1]],g_list[[4]]) 

私はハッシュテーブルにg_list内の要素のインデックスをハッシュするにはどうすればよいですか?

この玩具例えば予想される結果は次のようになります

g_inded_hash 
[[1]] 
[1] 1 4 

[[2]] 
[1] 2 5 

[[3]] 
[1] 3 

(必ずしもリストが、いくつかのデータ構造グループグラフ(1,4)及び(2,5)に類似している)

実際には、私は同形にしたがってグループ化する必要がある4000万(小さな)のグラフを持っています。

検索の結果、答えがパッケージまたはenvironmentに関連している必要があることが判明しましたが、その解決策には対応できませんでした。

EDIT:directed = TRUEgraph_from_data_frame()に変更しました。

+0

私はigraph' 'に慣れていないよ(ので、いくつかの組み込みツールは、このタスクのために存在している場合があります)しかし、あなたはより一般的な何かについて言及するので、あなたは(1)(combn''ですべてのペアごとの比較を作ることができます2)前の結果から "dist"オブジェクトを作成し、(3)このオブジェクトと組み込みRツールを使用してクラスタを作成する。私。 'split(seq_along(g_list)、cutree(hclust(structure)' combn(g_list、2、function(x)isomorphic(x [[1])、x [[2]]))、class = "dist"、Size =長さ(g_list)))、h = 0.5)) ' –

+0

tks。私は〜40millionのグラフを持っているので、ペアワイズの比較はO(n^2)となるので質問から外れています(答えは討論を参照してください)。ハッシュテーブルの素敵な特性は、各新しい要素(グラフ)が各グループの1つの要素に対してのみ比較されるということです。より多くの要素がグループ化されるにつれ、残りの比較の数は速く減少します – LucasMation

答えて

1

同型性は推移的であるため、i < jのようなすべてのコンポーネントのペア(i、j)を見てから、ノードがコンポーネントであり、エッジが同形プロパティによって定義されるグラフを作成できます。この新しいグラフの接続されたコンポーネントからハッシュテーブルを抽出することができます。

# all pairs (i,j) such that i < j 
combinations <- unlist(sapply(seq_along(g_list), 
           function(j) lapply(seq_len(j-1), 
              function(i) c(i,j))), 
         recursive = FALSE) 
# filter the isomorphic pairs 
iso <- Filter(function(pair) isomorphic(g_list[[pair[1]]],g_list[[pair[2]]]), 
       combinations) 
# convert to data frame 
df <- data.frame(matrix(unlist(iso), ncol = 2, byrow = TRUE)) 
# build graph where the vertices are the components 
# and the edges indicate the isomorphic property 
g_iso <- graph_from_data_frame(df, directed = FALSE) 
# identify groups that share the same property 
groups <- clusters(g_iso)$membership 
# the names are the indices of g_list 
g_hash <- lapply(unique(groups), 
       function(i) as.integer(names(which(groups == i)))) 

結果:

> g_hash 
[[1]] 
[1] 2 3 5 

[[2]] 
[1] 1 4 

これが問題の予想される結果と一致していませんが、isomorphic(g_list[[2]],g_list[[3]])isomorphic(g_list[[3]],g_list[[5]])trueあります。

おそらくこれを行う最も簡単な方法ではありませんが、それは思い浮かぶものです。

+0

あなたの結果は実際には正しいです、 'graph_from_data_frame()'関数で 'directed = TRUE'を更新することを忘れてしまいました。上記を参照。 – LucasMation

+0

援助のためのTks。グラフの "directed"バージョンでコードを試してみましたが、新しいグループとして "3"を追加することはできませんでしたが、(2,5)グループとの結合にはなりませんでした。もう1つの問題は、依然として多くの比較を行っていることです。すべてのi LucasMation

+0

より複雑なisomorphicのn-aryバージョンがない限り、我々はペアワイズ比較とO(n^2)に固執しています。ペアの数を減らすために、同形グラフのプロパティを計算しやすいグラフに基づいてフィルタリングを試みることができます。例えば、度の分布のエッジの等しい数の頂点。あなたが持っているグラフのタイプによっては、例えばシングルトングラフがたくさんある場合など、O(n^2)を扱いやすくするかもしれません。 –

0

私は自分の問題の解決方法を書くことができました。それはおそらく非常に効率的ではない、非常に "リッシュ"ではない、すべてのループでは、私はそれが動作すると思います。これを行うより良い方法を教えてください。

gl_hash <- list() 
gl_hash[1] <- 1 
j <- 1 
for(i in 2:length(gl)) { 
    m <- 0 
    for(k in 1:j){ 
    if(isomorphic(gl[[ gl_hash[[k]][1] ]], gl[[i]])) { 
     gl_hash[[k]] <- c(gl_hash[[1]],i) 
     m <- 1 
     break 
    } 
    } 
    if(m==0) { 
    j <- j+ 1 
    gl_hash[j] <- i 
    } 
} 
関連する問題