在R中的连续列表元素对上应用函数而不使用循环
我试图找到一种高效(即避免使用循环)的方法来应用一个函数,该函数迭代地将列表中的当前和以前(或下一个)元素作为参数,并返回结果列表(其长度必须短1个元素)。 作为具体的例子, 我有一个顶点列表,在一些图中定义了一条路径在R中的连续列表元素对上应用函数而不使用循环,r,vectorization,igraph,R,Vectorization,Igraph,我试图找到一种高效(即避免使用循环)的方法来应用一个函数,该函数迭代地将列表中的当前和以前(或下一个)元素作为参数,并返回结果列表(其长度必须短1个元素)。 作为具体的例子, 我有一个顶点列表,在一些图中定义了一条路径 vlist <- c(1,2,7,12,17) vlist 7,7-->12,12-->17 使用for循环很简单 findEids <- function(G,vlist) { outlist=c() for (i in 1
vlist <- c(1,2,7,12,17)
vlist 7,7-->12,12-->17
使用for循环很简单
findEids <- function(G,vlist) {
outlist=c()
for (i in 1:(length(vlist)-1) {
outlist=append(outlist,get.edge.ids(G,c(vlist[i],vlist[i+1])))
}
return(outlist)
}
findEids这可能适合您:
library(zoo)
findEids <- function(gr, v.list) {
rollapply(v.list, width=2, FUN=function(x) {
get.edge.ids(gr, x)
})
}
findEids(G, vlist)
## [1] 1 4 13 22
图书馆(动物园)
findEids虽然这不是对主题中问题的直接回答,但更具体地针对您的要求
如果您查看函数get.edge.ids
中参数vp
的描述,您将发现
vp
指示顶点,以顶点ID或符号顶点的形式给出
名字。它们是成对解释的,即第一个和第二个是
用于第一条边,第三条和第四条用于第二条边,等等
所以在这种情况下,您只需要从vlist
创建一个新的向量,这样除了第一个和最后一个元素外,所有元素都会重复两次。您可以使用vlist[c(1,rep(2:(length(vlist)-1),each=2),length(vlist))]
我使用mappy
来实现这一点。比如说
a<-1:1000
mapply(function(x,y)x-y,a[-1000],a[-1])
afg系统时间(
+对于(1:1000中的i){
+mapply(f,a[-1000],a[-1])
+ }
+ )
用户系统运行时间
2.344 0.000 2.345
>系统时间(对于(i in 1:1000)g())
用户系统运行时间
3.399 0.000 3.425
实际上,对于这个特定的问题,您可以使用
as.vector(E(G, path=vlist))
# [1] 1 4 13 22
这是非常可读的,似乎比任何其他解决方案都要快,尽管速度可能只在路径较长时才重要
v2 <- c(1,2,7,12,17,12,7,2)
vlist <- rep(v2, 100000)
system.time(get.edge.ids(G, vlist[c(1, rep(2:(length(vlist) - 1), each = 2),
length(vlist))]))
# user system elapsed
# 0.218 0.014 0.232
system.time(as.vector(E(G, path=vlist)))
# user system elapsed
# 0.028 0.007 0.035
v2我最近学会了使用dplyr,它可以通过变异/转化和粘贴来解决这个问题:
data.frame(x=vlist) %>%
mutate(y=lead(x)) %>%
transmute(edge=paste(x,y,sep="-->")
产生
edge
1 1-->2
2 2-->7
3 7-->12
4 12-->17
5 17-->NA
如果您想要一个列表,sapply
和lapply
可能会起作用lappy
将始终返回一个列表,而使用sapply
则取决于输入。有趣。这看起来很有希望。如果我需要修改它以跳过常规间隔(而不是连续的对),我会将“each=2”修改为“each=interval”吗?如果是这样的话,那么这应该是完美的!
v2 <- c(1,2,7,12,17,12,7,2)
vlist <- rep(v2, 100000)
system.time(get.edge.ids(G, vlist[c(1, rep(2:(length(vlist) - 1), each = 2),
length(vlist))]))
# user system elapsed
# 0.218 0.014 0.232
system.time(as.vector(E(G, path=vlist)))
# user system elapsed
# 0.028 0.007 0.035
data.frame(x=vlist) %>%
mutate(y=lead(x)) %>%
transmute(edge=paste(x,y,sep="-->")
edge
1 1-->2
2 2-->7
3 7-->12
4 12-->17
5 17-->NA