2017-11-11 14 views
2

Rに関数fを作成したいと思います。これには、個人と個人(例えばA2と呼ばれる)の間のエッジのdata.frameが入ります。 A2の "祖先"と "子ども"だけでなく、祖先と子どもの子孫の祖先も持つ別のdata.frame!私の複雑な問題が説明するためにネットワーク内の祖先と子孫を返すRの関数

:1つの "A" sのネットワークと "B" の持つ別:この例では

library(visNetwork) 
nodes <- data.frame(id = c(paste0("A",1:5),paste0("B",1:3)), 
       label = c(paste0("A",1:5),paste0("B",1:3))) 
edges <- data.frame(from = c("A1","A1","A2","A3","A4","B1","B2"), 
       to = c("A2","A3","A4","A4","A5","B3","B3")) 
visNetwork(nodes, edges) %>% 
    visNodes(font = list(size=45)) %>% 
    visHierarchicalLayout(direction = "LR", levelSeparation = 500) 

enter image description here

を、data.frameは、2つの異なる独立したネットワークが含まれています。

"A"のネットワークに関するすべてのdata.frame edgeを含むdata.frameを返す関数f(data = edges、indiv = "A2")を実装したいと考えています。

F(エッジ、「A2」)はdata.frameエッジのこのエキスを返します

head(f(edges,"A2")) 
# from to 
#1 A1 A2 
#2 A1 A3 
#3 A2 A4 
#4 A3 A4 
#5 A4 A5 

私はあなたが私を助けすることは十分に明らかであると思います。

ありがとうございます!

+0

何を試しましたか?あなたが実装しようとしているアルゴリズムは何ですか? –

+0

あなたが望むものを正確に理解しているわけではありませんが、実際には、祖先、児童、子供の子供、祖先の祖先であることを目標にしています。そして、それをコードするために時間を費やす前に(確かに数時間)、私はそれができることを知ったかったのです。ネットワークで作業する。しかし、インターネット上で満足できるものはまだ見つけられませんでした(樹木のみ)ので、もっと専門家に聞いてみたかったです!ありがとう – antuki

+0

私はグラフのアナリストではありませんが、おそらくこれが助けになるでしょう: – romles

答えて

1

私は個人にリンクされているすべての家族を見つけるための簡単なアルゴリズムを書いています(改善できると確信しています)。 @romlesのように、igraphのようないくつかのRパッケージで同じことをすることができます。しかし、この場合、私の関数はigraphオプションよりも少し性能が良いようです。

edges <- data.frame(from = c("A1","A1","A2","A3","A4","B1","B2"), 
        to = c("A2","A3","A4","A4","A5","B3","B3"), 
        stringsAsFactors = FALSE) 
f <- function(data, indiv){ 
    children_ancestors <- function(indiv){ 
     # Find children and ancestors of an indiv 
     c(data[data[,"from"]==indiv,"to"],data[data[,"to"]==indiv,"from"]) 
    } 
    family <- indiv 
    new_people <- children_ancestors(indiv) # New people to inspect 
    while(length(diff_new_p <- setdiff(new_people,family)) > 0){ 
     # if the new people aren't yet in the family : 
     family <- c(family, diff_new_p) 
     new_people <- unlist(sapply(diff_new_p, children_ancestors)) 
     new_people <- unique(new_people) 
    } 
    data[(data[,1] %in% family) | (data[,2] %in% family),] 
} 

f(edges, "A2")となる。 igraph関数との比較:

library(igraph) 
library(microbenchmark) 
edges2 <- graph_from_data_frame(edges, directed = FALSE) 
microbenchmark(simple_function = f(edges,"A2"), 
       igraph_option = as_data_frame(subgraph.edges(edges2, subcomponent(edges2, 'A2', 'in'))) 
       ) 
#Unit: microseconds 
#   expr  min  lq  mean median  uq  max neval 
# simple_function 874.411 968.323 1206.037 1123.515 1325.075 2957.931 100 
# igraph_option 1239.896 1451.364 1802.341 1721.227 1984.380 3907.089 100 
+0

私は必要なアルゴリズムとigraphパッケージを理解するのに非常に役立ちます。私はあなたが提供したすべてのソリューションを理解する時間がかかります! – antuki

1

これは私の作品:

library(igraph) 
g <- graph_from_literal(A1--A2, A1--A3, A2--A4, A3--A4, A4--A5, B1--B3, B2--B3) 
sg_a2 <- subcomponent(g, 'A2', 'in') 
as_data_frame(subgraph.edges(g, sg_a2)) 

それが与える:

# from to 
#1 A1 A2 
#2 A1 A3 
#3 A2 A4 
#4 A3 A4 
#5 A4 A5 
+0

あなたの答えは3人ありがとう、アルゴリズムを理解するのに非常に便利です私はigraphパッケージが必要です。私はあなたが提供したすべてのソリューションを理解する時間がかかります! – antuki

2

をあなたはA2に接続されているノードだけを試してみて、フィルタリングすることができ(すなわち、距離がInf

と等しくありません
library(tidygraph) 
edges <- data.frame(from = c("A1","A1","A2","A3","A4","B1","B2"), 
        to = c("A2","A3","A4","A4","A5","B3","B3")) 
as_tbl_graph(edges) %>% 
    filter(is.finite(node_distance_to(name=="A2", mode="all"))) 

# A tbl_graph: 5 nodes and 5 edges 
# 
# A directed acyclic simple graph with 1 component 
# 
# Node Data: 5 x 1 (active) 
    name 
    <chr> 
1 A1 
2 A2 
3 A3 
4 A4 
5 A5 
# 
# Edge Data: 5 x 2 
    from to 
    <int> <int> 
1  1  2 
2  1  3 
3  2  4 
# ... with 2 more rows 
+0

私が必要とするアルゴリズムとigraphパッケージを理解するのに非常に役立ちます。私はあなたが提供したすべてのソリューションを理解する時間がかかります! – antuki

関連する問題