data.frame的do.call(rbind,)為什么這么慢

do.call(rbind, ) 換成 dplyr::bind_rows( ) 竟然提速千倍,R讓人如此無語。
個人理解:
R給人的感覺是一切操作賦值都是“傳值”。
list 是R的基本數(shù)據(jù)類型,本身是 C struct, 定義操作等使用了指針,傳地址操作,list的函數(shù),很多也是primitive函數(shù),這些應(yīng)該也是C 代碼. 對list類型,mylist <- myfucntion(mylist)這種情況下,系統(tǒng)可以實現(xiàn)內(nèi)存上原地修改數(shù)據(jù),沒必要先復(fù)制。list實際上存儲的是每一個vector的地址,各個vector相互獨立,而且vector和list支持越界賦值,一個length為5的vector x, 你可以直接給x[6]賦值,可以更改x[3]。
而data.frame也是list,并不是R的原生類型,而是list的擴展。data.frame的各個組件間存在制約關(guān)系,必須等長,相互并不獨立,猜測這些制約關(guān)系相當(dāng)于增加了引用次數(shù),所以不能原地(in place)修改,其次data.frame不能越界賦值,也表明data.frame不支持原地修改。

R代碼的默認傳遞方式是傳值,這樣的好處是安全,適合非計算機專業(yè)同學(xué)使用。
如果是函數(shù)是C代碼(區(qū)別于純R代碼的函數(shù)),那么是可以支持傳地址的,這取決于C代碼怎么寫的。

data.frame也并非那么不堪,如果只是更改data.frame里的某一列,實際上是只copy某一列。而rbind行操作相當(dāng)于更改所有列**,每rbind一次就會在內(nèi)存復(fù)制完全一次data.frame,所以真的會很慢。
大數(shù)據(jù)的do.call(rbind, )相當(dāng)于不斷復(fù)制合并后的data.frame,真的可以慢到無以復(fù)加。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容