I am trying to find an efficient (i.e. avoid using loops) way to apply a function that iteratively takes as arguments the current and previous (or next) elements of a list and returns a lists of the result (the length of which will necessarily be 1 element shorter). As a concrete example,
I have a list of vertices defining a path in some graph
vlist <- c(1,2,7,12,17)
which come from a lattice graph constructed using the igraph function "lattice"
G <- graph.lattice(c(5,7))
I want to apply the function "get.edge.ids" over vlist so that the list returned yields the ids of the edges connecting the consecutive elements in vlist. E.g. I want the ids of edges 1-->2, 2-->7, 7-->12, 12-->17
This is trivial using a for loop,
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)
}
but I would like to use a vectorized approach like apply() or reduce() to see if I can get it to work more quickly since I will need to call functions like this repeatedly from a script (for example, to compute the total stretch for a spanning tree of G).
I use mapply
for that. For example
a<-1:1000
mapply(function(x,y)x-y,a[-1000],a[-1])
It appears to be slightly faster than the for loop version:
> f <- function(x,y)x-y
> g <- function(){
o<-c();
for(i in a[-1000])o<-c(o,f(i,i+1))
> }
>
> system.time(
+ for(i in 1:1000){
+ mapply(f,a[-1000],a[-1])
+ }
+ )
user system elapsed
2.344 0.000 2.345
> system.time(for(i in 1:1000)g())
user system elapsed
3.399 0.000 3.425
This might work for you:
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
Well, actually, for this specific question, you can query the whole path at once with
as.vector(E(G, path=vlist))
# [1] 1 4 13 22
This is very readable, and seems to be faster than any other solution, although speed probably only matters if you have long paths.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With