Если вы посмотрите на код, вы увидите общую структуру функции:
function (.data, .variables, .fun = NULL, ..., .progress = "none",
.drop = TRUE, .parallel = FALSE)
{
.variables <- as.quoted(.variables)
pieces <- splitter_d(.data, .variables, drop = .drop)
ldply(.data = pieces, .fun = .fun, ..., .progress = .progress,
.parallel = .parallel)
}
<environment: namespace:plyr>
, поэтому она в основном перестраивает переменные в более удобный для использования формат, а затем разбивает данные на части., а затем используйте ldply для этих частей.Эти фрагменты генерируются функцией splitter_d.Pieces на самом деле немного сложнее, чем список - это указатель на исходные данные и список индексов.Всякий раз, когда вы запрашиваете часть списка, он ищет соответствующие индексы и извлекает соответствующие данные.Это позволяет избежать нескольких копий данных.Вы можете увидеть, как это работает, используя getAnywhere("splitter_d")
или plyr:::splitter_d
.
ldply проходит один раз для каждого фрагмента данных.После этого он объединяет все обратно в массив данных.На самом деле, в файлах справки ldply написано:
Все функции plyr используют одну и ту же стратегию split-apply-Объединить: они разбивают ввод на более простые части, применяют .fun к каждой части, а затемобъединить части в единую структуру данных.Эта функция разбивает списки по элементам и объединяет результат в кадр данных.Если результатов нет, то эта функция вернет фрейм данных с нулевыми строками и столбцами (data.frame ()).
Я сам не мог бы сказать это лучше.И чудо, первое предложение также можно найти на странице справки для ddply.