rbindlist
оптимизированная версия do.call(rbind, list(...))
, которая известна своей медлительностью при использованииrbind.data.frame
Где это действительно превосходно
Некоторые вопросы, которые показывают, где rbindlist
светит
Быстрое векторизованное слияние списка data.frames по строкам
Проблема с преобразованием длинного списка data.frames (~ 1 миллион) в один data.frame с помощью do.call и ldply
У них есть тесты, которые показывают, насколько быстро это может быть.
rbind.data.frame медленный, по причине
rbind.data.frame
делает много проверок, и будет соответствовать по имени. (т.е. rbind.data.frame будет учитывать тот факт, что столбцы могут быть в разном порядке и совпадать по имени), rbindlist
не выполняет такую проверку и будет соединяться по позиции
например
do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
## a b
## 1 1 2
## 2 2 3
## 3 2 1
## 4 3 2
rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
## a b
## 1: 1 2
## 2: 2 3
## 3: 1 2
## 4: 2 3
Некоторые другие ограничения rbindlist
Он используется для борьбы , чтобы иметь дело с factors
, из - за ошибки , которая с тех пор было зафиксировано:
rbindlist два data.tables, где у одного есть фактор, а у другого тип символа для столбца ( Ошибка # 2650 )
Проблемы с повторяющимися именами столбцов
см.
Предупреждающее сообщение: в rbindlist (allargs): NA введены по принуждению: возможная ошибка в data.table? ( Ошибка № 2384 )
Имена строк в rbind.data.frame могут быть неприятными
rbindlist
может обрабатывать lists
data.frames
и data.tables
, и вернет data.table без имен строк
Вы можете получить в кучу имен строк, используя do.call(rbind, list(...))
см.
Как избежать переименования строк при использовании rbind внутри do.call?
Эффективность памяти
С точки зрения памяти rbindlist
реализована C
, поэтому она эффективна для памяти, она использует setattr
для установки атрибутов по ссылке
rbind.data.frame
реализован R
, он выполняет множество назначений и использует attr<-
( class<-
и rownames<-
все это (внутренне) создает копии созданного data.frame.
attr<-
,class<-
и (я думаю)rownames<-
все модифицируется на месте.DF = data.frame(a=1:3); .Internal(inspect(DF)); tracemem(DF); attr(DF,"test") <- "hello"; .Internal(inspect(DF))
.rbind.data.frame
имеет специальную логику "угона" - когда его первый аргумент - adata.table
, он вызывает.rbind.data.table
вместо этого, что делает небольшую проверку, а затем вызываетrbindlist
внутри. Так что, если у вас уже естьdata.table
объекты для привязки, вероятно, разница между производительностьюrbind
иrbindlist
.rbindlist
он может соответствовать по names (use.names=TRUE
), а также заполнить отсутствующие столбцы (fill=TRUE
). Я обновил этот , этот и этот пост. Вы не против отредактировать это или все в порядке, если я это сделаю? В любом случае меня устраивает.dplyr::rbind_list
тоже очень похожеBy
v1.9.2
,rbindlist
эволюционировал совсем немного, реализовав множество функций, в том числе:Кроме того, в
v1.9.2
,rbind.data.table
также появилсяfill
аргумент, позволяющий выполнять привязку путем заполнения недостающих столбцов, реализованный в R.Теперь
v1.9.3
есть еще больше улучшений в этих существующих функциях:rbind.data.frame
немного замедляется, в основном из-за копий (что также указывает @mnel), которых можно было бы избежать (перейдя на C). Думаю, это не единственная причина. Реализация проверки / сопоставления имен столбцовrbind.data.frame
также может замедлиться, если на data.frame много столбцов и есть много таких data.frames для привязки (как показано в тесте ниже).Однако
rbindlist
отсутствие определенных функций (таких как проверка уровней факторов или сопоставление имен) имеет очень крошечный (или нулевой) вес для того, чтобы он работал быстрее, чемrbind.data.frame
. Это потому, что они были тщательно реализованы в C, оптимизированы для скорости и памяти.Вот тест , который подчеркивает эффективное связывание, подбирая по именам столбцов , а также с помощью
rbindlist
«suse.names
функции изv1.9.3
. Набор данных состоит из 10000 фреймов данных, каждый размером 10 * 500.NB: этот тест был обновлен, чтобы включить сравнение
dplyr
сbind_rows
Связывание столбцов как таковых без проверки имен заняло всего 1,3, тогда как проверка имен столбцов и связывания соответственно заняла всего 1,5 секунды. По сравнению с базовым решением, это в 14 раз быстрее и в 18 раз быстрее, чем в
dplyr
версии.источник