Why do rbind() and do.call(rbind, ) return different results?

eclo.qh picture eclo.qh · Jan 29, 2016 · Viewed 16.3k times · Source

I want to convert a list to a data frame, with the following code:

ls<-list(a=c(1:4),b=c(3:6))
do.call("rbind",ls)

The result obtained by adding do.call is as shown below. It returns a data.frame object as desired.

 do.call("rbind",ls)
  [,1] [,2] [,3] [,4]
a    1    2    3    4
b    3    4    5    6

However if I directly use rbind, it returns a list.

Why does rbind behave differently in these two situations?

my.df<-rbind(ls)
str(ls)


 my.df
   a         b        
ls Integer,4 Integer,4

 str(ls)
List of 2
 $ a: int [1:4] 1 2 3 4
 $ b: int [1:4] 3 4 5 6

Answer

AdamO picture AdamO · Jan 29, 2016

do.call(rbind, ls) gives you the same output as Reduce(rbind, ls). The later is less efficient, but it serves to show how you are iterating over the objects in ls rather than manipulating ls (which is a concatenated list of 2 lists) directly.

They both operate by "unlisting" each element of the list, which has class numeric. When you rbind numeric arguments, the resulting class is a matrix with typeof being integer. If you just rbind the list, each element of the list is considered a single object. So the returned object is a matrix object with 1 row and 2 columns and entries of type list. That it has 1 row should make it apparent it's treating the object ls as one thing, and not two things. Typing rbind(ls, ls, ls) will give 3 rows and 2 columns.