我正在尝试改进一个基于一些节点属性计算得分的网络构建函数。该函数试图从图中找到最佳子网络,使节点属性的乘积最大化。
该函数从一个随机节点开始,并在第一个邻居中开始搜索。如果有一些邻居的节点得分满足阈值,则将邻居添加到第一个节点,并继续此过程,直到无法再添加(添加邻居不会产生所需的得分增量)。如果第一个邻居中没有可以产生得分增量的节点,则函数查看二级邻居。在这种情况下,连接节点的路径可能有几条,对于这种情况,选择的路径将是权重最高的最短路径(其中之一节点具有最高权重)。
我可以对代码进行并行化,但我不知道如何在这种类型的函数中实现它。
以下是该函数的代码:
该函数从一个随机节点开始,并在第一个邻居中开始搜索。如果有一些邻居的节点得分满足阈值,则将邻居添加到第一个节点,并继续此过程,直到无法再添加(添加邻居不会产生所需的得分增量)。如果第一个邻居中没有可以产生得分增量的节点,则函数查看二级邻居。在这种情况下,连接节点的路径可能有几条,对于这种情况,选择的路径将是权重最高的最短路径(其中之一节点具有最高权重)。
我可以对代码进行并行化,但我不知道如何在这种类型的函数中实现它。
以下是该函数的代码:
build_network <-
function (G, seed, d= 2){
net <- G
d <- d
score.fun<-function(g){
Za <- sum(V(g)$weight*V(g)$RWRNodeweight)/sqrt(sum(V(g)$RWRNodeweight^2))
k <- vcount(g)
tmp <- genesets.length.null.stat[[as.character(k)]] # genesets.length.null.stat is a list with the median of Za and sd of Za calculated for 1000 replicates of networks of size k
Sa <- (Za-tmp[1])/tmp[2]
}
best.fun<-function(in.nodes,out.nodes) {
score<-(-Inf); best<-character()
for(node in out.nodes){
subG.update<-induced.subgraph(net, c(in.nodes,node))
if( score.fun(subG.update) > score ){
score<-score.fun(subG.update)
best<-node
}
}
list("node"=best,"score"=score)
}
subG <- induced.subgraph(net, seed)
if (!is.connected(subG)) { #the seed must be connected
stop("Input seeds are disjoint")
}
while (TRUE) {
in.nodes <- V(subG)$name
node_num <- vcount(subG)
subsum <- score.fun(subG)
#subx <- V(subG)$name
for (rad in 1:d) {
tmp.neigh <- unlist(neighborhood(net, order = rad, nodes = V(subG)$name))
pot.nodes <- V(net)[tmp.neigh]$name
out.nodes <- setdiff(pot.nodes, in.nodes)
if (length(out.nodes) == 0) break
best_node<-best.fun(in.nodes, out.nodes)
new_score<-best_node$score
best_node<-best_node$node
if (new_score > subsum + 0.01) {
tmp <- unlist(lapply(best_node, function(x) node2treePath(net,V(subG)$name, x))) # node2treePath is a function to retrieve the shortest path with the highest node weights
in.nodes <- c(tmp, V(subG)$name)
subG <- induced.subgraph(net, in.nodes)
break
}
}
if (node_num == vcount(subG)) break
}
return(subG)
}
我正在尝试将此函数应用于大约10,000个节点的图。以下是运行该函数的代码近似:
### generate some example data
library(igraph)
my_graph <- erdos.renyi.game(10000, 0.0003)
V(my_graph)$name <- 1:vcount(my_graph)
V(my_graph)$weight <- rnorm(10000)
V(my_graph)$RWRNodeweight <- runif(10000, min=0, max=0.05)
### Run the function
sublist = list()
for (node in V(G)$name) {
subnet <- build_network(G, node, d)
sublist[[node]] <- subnet }
编辑:这是head(genesets.length.null.stat)
的dput
structure(list(`1` = c(1.01397367504035, 1.18858228819048), `2` = c(1.61970348041337, 1.30189433386605), `3` = c(2.11767222957028, 1.36222065695878), `4` = c(2.47710421934929, 1.36968129959296), `5` = c(2.776011866622, 1.36318885187196), `6` = c(3.16885126246671, 1.42577861995897)), .Names = c("1", "2", "3", "4", "5", "6"))
这是node2treePath
函数:
node2treePath <- function (G, Tnodes, node){
tmp.path <- get.all.shortest.paths(G, node, Tnodes)$res
tmp.l <- unlist(lapply(tmp.path, length))
index <- which(tmp.l == min(tmp.l))
tmp.path = tmp.path[index]
tmp.sum <- unlist(lapply(tmp.path, function(x)return(sum(V(G)[x]$weight))))
index <- which(tmp.sum == max(tmp.sum))
selected.path = tmp.path[index]
collect <- unlist(lapply(selected.path, function(x)return(V(G)[x]$name)))
return(collect)
}
genesets.length.null.stat
不存在。 - Jack Waseygenesets.length.null.stat
是一个包含 500 个元素的列表,每个元素都存储了两个值(均值和标准差)。 - user2380782genesets.length.null.stat
的例子吗?例如:dput(head(genesets.length.null.stat))
,或者一些生成随机genesets.length.null.stat
对象的代码? - joslibergenesets.length.null.stat
只是在运行你之前的帖子https://dev59.com/9FwY5IYBdhLWcg3wCUA7中的`josilber.rcpp`函数后得到的列表,例如`genesets.length.null.stat <- lapply(1:500, function(x)josilber.rcpp(x,1000,my_graph),然后计算列表每个组件的平均值和标准差。我已经按照你的建议添加了
dput`。非常感谢,如果你需要其他任何东西,请告诉我。 - user2380782node2treePath
。此外,best_fun
应该是best.fun
。即使是赏金问题,你仍然需要编写可重现的示例,以便人们可以实际运行代码来解决你所述的特定问题。你可以提供一个等效的虚拟函数或者真实的函数。 - Jack Waseynode2treePath
函数,代码可以工作但显然不是最快的,感谢您的帮助,对于没有以更好的方式发布而感到抱歉。 - user2380782