Home > Software engineering >  Understanding output of rbind function when a list is passed as argument
Understanding output of rbind function when a list is passed as argument

Time:12-26

I was practicing basics of matrices questions in R ending up knowing a solution for one of the question as follows:

l <- list()

for (i in 1:5) l[[i]] <- c(i, 1:4)

mat_list <- do.call(rbind, l)

Although, I have understood how do.call works, I directly tried to create a matrix using rbind and the output was follows:

rbind(l)
#   [,1]      [,2]      [,3]      [,4]      [,5]     
# l integer,5 integer,5 integer,5 integer,5 integer,5

I tried to understand the output on google, but, none of them were satisfactory. Please help in understanding the output.

CodePudding user response:

It becomes more apparent when you look at the generated objects a bit closer. Generally speaking, do.call gives each list element to rbind one by one. Using rbind manually on one object like a list looks at the whole list. See below.

Note:

‘do.call’ constructs and executes a function call from a name or a function and a list of arguments to be passed to it.

The function call with do.call generates a matrix from each vector of the list as rows.

lis
[[1]]
[1] 1 1 2 3 4

[[2]]
[1] 2 1 2 3 4

[[3]]
[1] 3 1 2 3 4

[[4]]
[1] 4 1 2 3 4

[[5]]
[1] 5 1 2 3 4

do.call(rbind,lis)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    2    3    4
[2,]    2    1    2    3    4
[3,]    3    1    2    3    4
[4,]    4    1    2    3    4
[5,]    5    1    2    3    4

This is the same as doing it manually from each vector like so

rbind( c(1, 1:4), c(2, 1:4) )
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    2    3    4
[2,]    2    1    2    3    4
# etc...

The manual use of the function rbind on a list is a different operation. It doesn't deconstruct the list and does not look at each vector element.

rbind(lis)
    [,1]      [,2]      [,3]      [,4]      [,5]     
lis Integer,5 Integer,5 Integer,5 Integer,5 Integer,5

# put in a data.frame to see the vectors
data.frame(rbind(lis))
               X1            X2            X3            X4            X5
lis 1, 1, 2, 3, 4 2, 1, 2, 3, 4 3, 1, 2, 3, 4 4, 1, 2, 3, 4 5, 1, 2, 3, 4

# compare with cbind used this way
data.frame(cbind(lis))
            lis
1 1, 1, 2, 3, 4
2 2, 1, 2, 3, 4
3 3, 1, 2, 3, 4
4 4, 1, 2, 3, 4
5 5, 1, 2, 3, 4

You can use these distinct behaviors to your advantage in your workflows if you want to work on single elements of objects, aka evaluate each element separately.

CodePudding user response:

rbind is actually designed for row-wise binding vectors to a matrix. If we have two vectors of length 5, the result is a matrix having two rows and five columns.

rbind(0:4, 5:9)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    1    2    3    4
# [2,]    5    6    7    8    9

If be bind a list of say the same two integer vectors, we only have one list and thus only one row.

rbind(list(0:4, 5:9))
#           [,1]      [,2]     
# [1,] integer,5 integer,5

If we attempt to rbind two lists, we get two rows.

rbind(list(0:4, 5:9), list(0:4, 5:9))
#           [,1]      [,2]     
# [1,] integer,5 integer,5
# [2,] integer,5 integer,5

The first integer vector of length 5 hides in the first column, second in the second, etc.

rbind(list(0:4, 5:9))[1, 1][[1]]
# [1] 0 1 2 3 4
  • Related