0

I am trying to create an array out of a list with different numbers of outputs for each value that I obtained from a function.

This is the code I am using:

list_i1 = sapply(implicit$image_1_id, num, simplify = 'array')

And these are the outputs.

> list_i1[[1]] [1] 86 101

> list_i1[[2]] [1] 35 61 112

> list_i1[[3]] [1] 10 15

Due to the fact that some of the values have more 2 output numbers whereas some have 3, I am unable to create an array from the following list. Ideally, I would like to have a zero in the slot that isn't filled by a third output within the array so as to look like this:

1 86 35 10 2 101 61 15 3 0 112 0

E. Sas
  • 45
  • 5
  • You get more answers if you provide sample data eg with dput. Try something like cbind(list_i1) or wrap the sapply in a cbind – Andrew Lavers Aug 07 '18 at 18:42

2 Answers2

2

I came up with a very similar solution to @Fernandes, using tips from here and here

Recreate your example:

lst <- list(c(86, 101), c(35, 61, 112), c(10, 15))
# [[1]]
# [1]  86 101
# 
# [[2]]
# [1]  35  61 112
# 
# [[3]]
# [1] 10 15

Figure out the number of rows needed, and then extend each of the vectors to that length:

num_row <- max(sapply(lst, length))
for (i in seq_along(lst)) {
  length(lst[[i]]) <- num_row
} 
# [[1]]
# [1]  86 101  NA
# 
# [[2]]
# [1]  35  61 112
# 
# [[3]]
# [1] 10 15 NA

Column bind all the now-equal-length-vectors together into a matrix:

m <- sapply(lst, cbind)
#      [,1] [,2] [,3]
# [1,]   86   35   10
# [2,]  101   61   15
# [3,]   NA  112   NA

Replace all the NA's with the desired 0's:

m[is.na(m)] <- 0
#      [,1] [,2] [,3]
# [1,]   86   35   10
# [2,]  101   61   15
# [3,]    0  112    0

I really wanted to replace the for loop with with some kind of 'apply', but couldn't figure it out. If anyone knows how to not use the for loop, I'd like to see it!

jhchou
  • 196
  • 1
  • 12
  • 1
    Just do `sapply(lst, 'length<-', max(lengths(lst)))`\ – akrun Aug 07 '18 at 20:08
  • Oh very nice! So the solution boils down to `m <- sapply(lst, 'length<-', max(lengths(lst)))` followed by `m[is.na(m)] <- 0`. Or can you compress it down to a one-liner? – jhchou Aug 07 '18 at 20:25
  • If you want one liner, then `sapply(lst, function(x) c(x, rep(0, max(lengths(lst)) - length(x))))` – akrun Aug 07 '18 at 20:29
0
a = c(86, 101)
b = c(35, 61, 112)
c = c(10, 15)

list_i1 = list(a, b, c)

n = max(length(list_i1[[1]]),
        length(list_i1[[2]]),
        length(list_i1[[3]]))

length(list_i1[[1]]) = n
length(list_i1[[2]]) = n
length(list_i1[[3]]) = n

x = cbind(list_i1[[1]], list_i1[[2]], list_i1[[3]]) 
x[is.na(x)] = 0

x
#     [,1] [,2] [,3]
#[1,]   86   35   10
#[2,]  101   61   15
#[3,]    0  112    0
Thiago Fernandes
  • 273
  • 2
  • 12