У меня есть код, который в одном месте заканчивается списком фреймов данных, которые я действительно хочу преобразовать в один большой фрейм данных.
Я получил несколько советов из предыдущего вопроса, который пытался сделать что-то похожее, но более сложное.
Вот пример того, с чего я начинаю (это сильно упрощено для иллюстрации):
listOfDataFrames <- vector(mode = "list", length = 100)
for (i in 1:100) {
listOfDataFrames[[i]] <- data.frame(a=sample(letters, 500, rep=T),
b=rnorm(500), c=rnorm(500))
}
Я в настоящее время использую это:
df <- do.call("rbind", listOfDataFrames)
do.call("rbind", list)
Идиома , что я использовал до того, как хорошо. Зачем вам нужно начальноеunlist
?Ответы:
Используйте bind_rows () из пакета dplyr:
источник
.id = "column_label"
добавляет уникальные имена строк на основе имен элементов списка.dplyr
он быстрый и надежный инструмент, я изменил его на принятый ответ. Годы летят!Еще один вариант - использовать функцию plyr:
Это немного медленнее, чем оригинал:
Я предполагаю, что использование
do.call("rbind", ...)
будет самым быстрым подходом, который вы найдете, если только вы не можете сделать что-то вроде: (а) использовать матрицы вместо data.frames и (б) предварительно выделить конечную матрицу и присвоить ей, а не увеличивать ее ,Изменить 1 :
Основываясь на комментарии Хэдли, вот последняя версия
rbind.fill
CRAN:Это проще, чем rbind, и незначительно быстрее (эти временные интервалы сохраняются в течение нескольких прогонов). И, насколько я понимаю, версия
plyr
на github еще быстрее, чем эта.источник
I()
может заменитьdata.frame
в вашемldply
призывеmelt.list
в форме (2)do.call(function(...) rbind(..., make.row.names=F), df)
полезно, если вы не хотите автоматически генерируемые уникальные имена строк.В целях полноты я думал, что ответы на этот вопрос требуют обновления. «Я предполагаю, что использование
do.call("rbind", ...)
будет самым быстрым подходом, который вы найдете ...» Это, вероятно, было верно для мая 2010 года и некоторое время спустя, но примерно в сентябре 2011 годаrbindlist
вdata.table
пакете версии 1.8.2 была введена новая функция. , с замечанием, что «Это так же, какdo.call("rbind",l)
, но гораздо быстрее». Насколько быстрее?источник
ldply
связки длинных расплавленных кадров данных. В любом случае, я получил невероятное ускорение благодаря вашемуrbindlist
предложению.dplyr::rbind_all(listOfDataFrames)
добьется цели.rbindlist
но который добавляет кадры данных по столбцам? что-то вроде cbindlist?do.call()
что 18 часов работал со списком фреймов данных, и все еще не закончил, спасибо !!!Код:
сессия:
ОБНОВЛЕНИЕ : Rerun 31-Jan-2018. Бежал на одном компьютере. Новые версии пакетов. Добавлено семя для любителей семян.
ОБНОВЛЕНИЕ : Rerun 06-Aug-2019.
источник
set.seed
), но видел некоторые различия в производительности в худшем случае.rbindlist
на самом деле у меня был лучший наихудший случай, а также лучший типичный случай в моих результатахСуществует также
bind_rows(x, ...)
вdplyr
.источник
Вот еще один способ сделать это (просто добавив его в ответы, потому что
reduce
это очень эффективный функциональный инструмент, который часто упускают из виду как замену циклов. В данном конкретном случае, ни один из них не является значительно более быстрым, чем do.call)используя базу R:
или, используя Tidyverse:
источник
Как это сделать в тидиверсе:
источник
map
еслиbind_rows
можно взять список данных?Обновленный визуальный материал для тех, кто хочет сравнить некоторые из недавних ответов (я хотел сравнить решение purrr и dplyr). В основном я объединил ответы от @TheVTM и @rmf.
Код:
Информация о сессии:
Версии пакета:
источник
Единственное что решения с
data.table
не хватает - это столбец идентификатора, чтобы узнать, с какого кадра данных в списке поступают данные.Что-то вроде этого:
idcol
Параметр добавляет столбец (.id
) , идентифицирующий происхождение dataframe , содержащейся в списке. Результат будет выглядеть примерно так:источник