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