James Griffin
James Griffin

Reputation: 23

Trying to output a list of lists from a loop in r

I am trying to do something that I am sure should be quite simple: I am trying to make a function which turns a list of number pairs (pairedList) and a vector (botList) into a series of vectors (one for each pair) of length(botlist) where the numbers in those vectors are all equal to zero except for those corresponding to the index points identified by the pair which will be 1.

#generating mock data to simulate my application:
  pair1 <- c(2,4)
  pair2 <- c(1,3)
  pair3 <- c(5,6)
  pairedList <- c(pair1, pair2, pair3)
  botList <- c(1:length(pairedList))

Here is what the output should ultimately look like:

[1] 0 1 0 1 0 0
[1] 1 0 1 0 0 0
[1] 0 0 0 0 1 1

The code below allows me to print the vectors in the right manner (by replacing the line in the if loop with print(prob) and commenting out the final print statement):

library(gtools)
test <- function() {


#initialising empty list
  output <- list()

  for (i in botList) {
    x <- rep(0, length(pairedList))
    ind <- pairedList[i:(i+1)]
    ind.inv <- sort(ind, decreasing=T)
    val <- rep(1,length(ind))
    new.x <- vector(mode="numeric",length(x)+length(val))
    new.x <- new.x[-ind]
    new.x[ind] <- val
    prob <- new.x

    if (odd(i)) {
      output[i] <- prob
    }
    print(output)
  }
}

However I need to return this list of vectors from my function rather than printing it and when I do so, I get the following output and am met with an error and a number of warnings:

[[1]]
[1] 0

[[1]]
[1] 0

[[1]]
[1] 0

[[2]]
NULL

[[3]]
[1] 1

[[1]]
[1] 0

[[2]]
NULL

[[3]]
[1] 1

[[1]]
[1] 0

[[2]]
NULL

[[3]]
[1] 1

[[4]]
NULL

[[5]]
[1] 0

Error in new.x[-ind] : only 0's may be mixed with negative subscripts
In addition: Warning messages:
1: In output[i] <- prob :
  number of items to replace is not a multiple of replacement length
2: In output[i] <- prob :
  number of items to replace is not a multiple of replacement length
3: In output[i] <- prob :
  number of items to replace is not a multiple of replacement length

My question is: How can I change my code to output what I need from this function? I thought this was going to be a five minute job, and after hours on this one little thing I am stuck!

Thanks in advance

Upvotes: 0

Views: 2078

Answers (3)

GarAust89
GarAust89

Reputation: 457

James, the following should work. I've just tested it.

pair1 <- c(2,4)
pair2 <- c(1,3)
pair3 <- c(5,6)
pairedList <- c(pair1, pair2, pair3)
botList <- c(1:(length(pairedList)/2)



library(gtools)
test <- function(pairedList, botList) {


 #initialising empty list
 output <- list()

  for (i in botList) {
   x <- rep(0, length(pairedList))
   ind <- pairedList[i:(i+1)]
   ind.inv <- sort(ind, decreasing=T)
   val <- rep(1,length(ind))
   new.x <- vector(mode="numeric",length(x)+length(val))
   new.x <- new.x[-ind]
   new.x[ind] <- val
   prob <- new.x

   output[[i]] <- prob
   print(prob)

 }
 return(output)
}

The reason for the strange error is that botList was being created as length 6 rather than length 3. Also if you want to assign a value to a list within a function you need to use double [[]] rather than []

Once you've removed them from the function rbind them all together as follows:

output <- test(pairedList, botList)
result <- do.call(rbind,output)

Upvotes: 0

akrun
akrun

Reputation: 887511

You could use row/col indexing

 m1 <- matrix(0, ncol=max(pairedList), nrow=3)
 m1[cbind(rep(1:nrow(m1),each=2), pairedList)] <- 1
 m1
 #    [,1] [,2] [,3] [,4] [,5] [,6]
 #[1,]    0    1    0    1    0    0
 #[2,]    1    0    1    0    0    0
 #[3,]    0    0    0    0    1    1

Upvotes: 1

Cath
Cath

Reputation: 24074

Something you can try, although there must be nicer ways:

# create a list with all the "pair1", "pair2", ... objects
l_pairs <- mget(ls(pattern="^pair\\d+")) 
# compute maximum number among the values of pair., it determines the number of columns of the results
n_max <- max(unlist(l_pairs)) 

# finally, create for each pair. a vector of 0s and put 1s at the positions specified in pair.    
res <- t(sapply(l_pairs, function(x){y <- rep(0, n_max); y[x]<-1; y})) 

res
#      [,1] [,2] [,3] [,4] [,5] [,6]
#pair1    0    1    0    1    0    0
#pair2    1    0    1    0    0    0
#pair3    0    0    0    0    1    1

Upvotes: 1

Related Questions