通过 R 中的普通朋友连接节点
Connecting nodes by common friends in R
我正在使用 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), name = "name", 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)
显示
我正在使用 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), name = "name", 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)
显示