问题描述
我正在使用 igraph 处理转推网络。我的网络是定向的,这意味着它将其他用户转发的人联系起来。
我的格式是一个边缘列表,其中箭头从转发者到转发用户,转发者之间没有联系(也就是说,所有转发者的内部度数为 0,因为他们不相互转发)。
我想连接普通朋友的转发者并简化网络。为此,我想通过普通转发用户连接用户:
考虑以下 repex:
edgelist <- read.table(text = "
A C
B C
D C")
g <- graph.data.frame(edgelist,directed = T)
在这种情况下,节点 A、B 和 E 是从节点 C 转发的,所以我想通过以下方式连接它们:
理想情况下,我还会根据他们从用户转发的次数获得权重,我希望将其合并到最终网络中,但这可能是另一个需要解决的不同问题。
我尝试了以下功能,它在小型玩具网络中确实有效,但是当我在我的(数千条边)中尝试时,它崩溃了:
connect_friends<-function(edgelist){
g <- graph.data.frame(edgelist,directed = T)
g <- delete_vertices( g,(!V(g) %in% c(V(g)[[degree(g,mode = "in")>=2]])) &
(!V(g) %in% c(V(g)[[degree(g,mode = "in")==0]])))
el <- as.data.frame(get.edgelist(g))
ids <- unique(c(el$V1,el$V2))
y <- lapply(ids,function(id) {
x <- el[which(el$V1 == id | el$V2 == id),]
alt_nodes <- setdiff(unique(c(x$V1,x$V2)),id)
})
if(length(y)==0) {
stop("No common friends found")
}
ne2=NULL
ne=NULL
for (i in 1:length(y)) {
new_edge <- y[[i]]
if (length(new_edge)>=2){
ne <- t(combn(new_edge,2))
}
ne2 <- rbind(ne,ne2)
}
g2 <<- graph.data.frame(ne2,directed = F)
}
有没有更有效的方法?
非常感谢!
解决方法
更新
通过更新的例子,我们可以得到
> gres
IGRAPH a824a46 UN-- 4 0 --
+ attr: name_1_1 (g/c),name_1_2 (g/c),name_2_1 (g/c),name_2_2 (g/c),| loops_1_1 (g/l),loops_1_2 (g/l),loops_2_1 (g/l),loops_2_2 (g/l),| name (v/c)
+ edges from a824a46 (vertex names):
和plot(gres)
节目
你可以像下面这样使用 disjoint_union
+ split
+ make_full_graph
gres <- do.call(
graph.union,lapply(
names(V(g))[degree(g,mode = "out") == 0],function(x) {
nbs <- names(V(g))[distances(g,v = x,mode = "in") == 1]
disjoint_union(
set_vertex_attr(make_full_graph(length(nbs)),name = "name",value = nbs),set_vertex_attr(make_full_graph(1),value = x)
)
}
)
)
给出
> gres
IGRAPH cb11da8 UN-- 4 3 --
+ attr: name_1 (g/c),name_2 (g/c),loops_1 (g/l),loops_2 (g/l),name
| (v/c)
+ edges from cb11da8 (vertex names):
[1] A--B A--D B--D
和plot(gres)
节目