user8003788
user8003788

Reputation: 253

Store vectors with different length as a list in R

For the code below, I want to store the (a*b) for each edge in a vector op1 and after that to store all vectors in a list opp1. According to the given data: I should have 5 vectors op1each one with a different length (for example: length(op1[1]=3) while the rest of vectors of length 2 like length(op1[2]=2)) and I will have one list opp1 contain the vectors of different lengths.

Storing the values in the vectors is OK but my problem is when storing these vectors, the resulted list contain the vectors but with the same length, i.e opp1list consist of all op1 vectors with length 3 so there is a strange value added from no where.

library(igraph)
graph<-matrix(c(4,3,4,1,4,2,3,2,3,1),ncol=2,byrow=TRUE)
g<-graph.data.frame(d = graph, directed = FALSE)
v1<-c()
v2<-c()
n1<-list()
n2<-list()
op1<-c()
opp1<-list()
for (edge in 1:length(E(g))){
  v1[edge] <- ends(graph = g, es = edge)[1]
  v2[edge] <- ends(graph = g, es = edge)[2]
  n1[[edge]] <- names(neighbors(g, v1[edge], mode = "all"))
  n2[[edge]] <- names(neighbors(g, v2[edge], mode = "all"))
for (neighbor in 1:length(n2[[edge]])){
a<-as.numeric(v2[edge])
b<-as.numeric(n2[[edge]][neighbor])
c<-(a*b)
op1[neighbor]<-c
}
opp1[[edge]]<-op1
}

The list opp1 is:

 opp1
[[1]]
[1] 12  3  6

[[2]]
[1] 4 3 6

[[3]]
[1] 8 6 6

[[4]]
[1] 8 6 6

[[5]]
[1] 4 3 6

while it should be:

 opp1
[[1]]
[1] 12  3  6

[[2]]
[1] 4 3 

[[3]]
[1] 8 6 

[[4]]
[1] 8 6

[[5]]
[1] 4 3 

Is there any advice how to fix the code, also is there another way to do the same work in a different way especially to save time and memory when working on big data. Thanks in advance.

Upvotes: 1

Views: 3177

Answers (1)

Terru_theTerror
Terru_theTerror

Reputation: 5017

You have to initialize op1 inside the first for loop in the way to have a clean op1 in each cycle, like this:

 for (edge in 1:length(E(g))){
   op1<-c()
   v1[edge] <- ends(graph = g, es = edge)[1]
   v2[edge] <- ends(graph = g, es = edge)[2]
   n1[[edge]] <- names(neighbors(g, v1[edge], mode = "all"))
   n2[[edge]] <- names(neighbors(g, v2[edge], mode = "all"))
   for (neighbor in 1:length(n2[[edge]])){
     a<-as.numeric(v2[edge])
     b<-as.numeric(n2[[edge]][neighbor])
     c<-(a*b)
     op1[neighbor]<-c
   }
   opp1[[edge]]<-op1

 }

Your output:

opp1
[[1]]
[1] 12  3  6

[[2]]
[1] 4 3

[[3]]
[1] 8 6

[[4]]
[1] 8 6

[[5]]
[1] 4 3

Without for loop is better and faster:

 n<-length(E(g))

 v1x<-unlist(lapply(lapply(c(1:n),ends,graph=g),"[[",1))
 v2x<-unlist(lapply(lapply(c(1:n),ends,graph=g),"[[",2))

 n1x<-lapply(lapply(v1x,neighbors,graph=g,mode="all"),names)
 b<-Map(as.numeric,lapply(lapply(v2x,neighbors,graph=g,mode="all"),names))

 a<-mapply(rep, as.numeric(v2x), lapply(n2x,length))

 opp1<-Map('*',a,b)
opp1
[[1]]
[1] 12  3  6

[[2]]
[1] 4 3

[[3]]
[1] 8 6

[[4]]
[1] 8 6

[[5]]
[1] 4 3

Upvotes: 2

Related Questions