在R中的连续列表元素对上应用函数而不使用循环

在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

我试图找到一种高效(即避免使用循环)的方法来应用一个函数,该函数迭代地将列表中的当前和以前(或下一个)元素作为参数,并返回结果列表(其长度必须短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