By v1.9.2, rbindlistэволюционировал совсем немного, реализовав множество функций, в том числе:
- Выбор самого высокого
SEXPTYPEстолбца при привязке - реализовано при v1.9.2закрытии FR # 2456 и Bug # 4981 .
factorПравильная обработка столбцов - сначала реализована в v1.8.10закрытии ошибки # 2650 и расширена для тщательного связывания упорядоченных факторов v1.9.2, закрывая FR # 4856 и ошибку № 5019 .
Кроме того, в v1.9.2, rbind.data.tableтакже появился fillаргумент, позволяющий выполнять привязку путем заполнения недостающих столбцов, реализованный в R.
Теперь v1.9.3есть еще больше улучшений в этих существующих функциях:
rbindlistполучает аргумент use.names, который по умолчанию предназначен FALSEдля обратной совместимости.
rbindlistтакже получает аргумент fill, который по умолчанию также FALSEдля обратной совместимости.
- Все эти функции реализованы на C и написаны тщательно, чтобы не снижать скорость при добавлении функций.
- Поскольку
rbindlistтеперь можно сопоставлять по именам и заполнять пропущенные столбцы, rbind.data.tableпросто звоните rbindlistсейчас. Единственное отличие состоит в том, что use.names=TRUEпо умолчанию rbind.data.tableдля обратной совместимости.
rbind.data.frameнемного замедляется, в основном из-за копий (что также указывает @mnel), которых можно было бы избежать (перейдя на C). Думаю, это не единственная причина. Реализация проверки / сопоставления имен столбцов rbind.data.frameтакже может замедлиться, если на data.frame много столбцов и есть много таких data.frames для привязки (как показано в тесте ниже).
Однако rbindlistотсутствие определенных функций (таких как проверка уровней факторов или сопоставление имен) имеет очень крошечный (или нулевой) вес для того, чтобы он работал быстрее, чем rbind.data.frame. Это потому, что они были тщательно реализованы в C, оптимизированы для скорости и памяти.
Вот тест , который подчеркивает эффективное связывание, подбирая по именам столбцов , а также с помощью rbindlist«s use.namesфункции из v1.9.3. Набор данных состоит из 10000 фреймов данных, каждый размером 10 * 500.
NB: этот тест был обновлен, чтобы включить сравнение dplyrсbind_rows
library(data.table) # 1.11.5, 2018-06-02 00:09:06 UTC
library(dplyr) # 0.7.5.9000, 2018-06-12 01:41:40 UTC
set.seed(1L)
names = paste0("V", 1:500)
cols = 500L
foo <- function() {
data = as.data.frame(setDT(lapply(1:cols, function(x) sample(10))))
setnames(data, sample(names))
}
n = 10e3L
ll = vector("list", n)
for (i in 1:n) {
.Call("Csetlistelt", ll, i, foo())
}
system.time(ans1 <- rbindlist(ll))
# user system elapsed
# 1.226 0.070 1.296
system.time(ans2 <- rbindlist(ll, use.names=TRUE))
# user system elapsed
# 2.635 0.129 2.772
system.time(ans3 <- do.call("rbind", ll))
# user system elapsed
# 36.932 1.628 38.594
system.time(ans4 <- bind_rows(ll))
# user system elapsed
# 48.754 0.384 49.224
identical(ans2, setDT(ans3))
# [1] TRUE
identical(ans2, setDT(ans4))
# [1] TRUE
Связывание столбцов как таковых без проверки имен заняло всего 1,3, тогда как проверка имен столбцов и связывания соответственно заняла всего 1,5 секунды. По сравнению с базовым решением, это в 14 раз быстрее и в 18 раз быстрее, чем в dplyrверсии.
attr<-,class<-и (я думаю)rownames<-все модифицируется на месте.