do.call(rbind, ) 换成 dplyr::bind_rows( ) 竟然提速千倍,R让人如此无语。
个人理解:
R给人的感觉是一切操作赋值都是“传值”。
list 是R的基本数据类型,本身是 C struct, 定义操作等使用了指针,传地址操作,list的函数,很多也是primitive函数,这些应该也是C 代码. 对list类型,mylist <- myfucntion(mylist)这种情况下,系统可以实现内存上原地修改数据,没必要先复制。list实际上存储的是每一个vector的地址,各个vector相互独立,而且vector和list支持越界赋值,一个length为5的vector x, 你可以直接给x[6]赋值,可以更改x[3]。
而data.frame也是list,并不是R的原生类型,而是list的扩展。data.frame的各个组件间存在制约关系,必须等长,相互并不独立,猜测这些制约关系相当于增加了引用次数,所以不能原地(in place)修改,其次data.frame不能越界赋值,也表明data.frame不支持原地修改。
R代码的默认传递方式是传值,这样的好处是安全,适合非计算机专业同学使用。
如果是函数是C代码(区别于纯R代码的函数),那么是可以支持传地址的,这取决于C代码怎么写的。
data.frame也并非那么不堪,如果只是更改data.frame里的某一列,实际上是只copy某一列。而rbind行操作相当于更改所有列**,每rbind一次就会在内存复制完全一次data.frame,所以真的会很慢。
大数据的do.call(rbind, )相当于不断复制合并后的data.frame,真的可以慢到无以复加。