#r #plyr
#r #plyr
Вопрос:
Я использую ddply, чтобы избежать избыточных вычислений.
Я часто имею дело со значениями, которые сохраняются в разделенных подмножествах, и выполняю неагрегатный анализ. Итак, чтобы избежать этого (игрушечный пример):
ddply(baseball,.(id,year),function(x){paste(x$id,x$year,sep="_")})
Error in list_to_dataframe(res, attr(.data, "split_labels")) :
Results do not have equal lengths
Я должен взять первую строку каждого мини-фрейма данных.
ddply(baseball,function(x){paste(x$id[1],x$year[1],sep="_")})
Есть ли другой подход или помощник, который я должен использовать? Этот синтаксис кажется неудобным.
—
Примечание: вставка в моем примере сделана просто для галочки — не воспринимайте это слишком буквально. Представьте, что это реальная функция:
ddply(baseball,function(x){the_slowest_function_ever(x$id[1],x$year[1])})
Комментарии:
1. я удивлен, что нет способа получить доступ к .variables изнутри функции
2. возникшая проблема: github.com/hadley/plyr/issues/68
Ответ №1:
В этом случае вы можете найти data.table немного проще и быстрее. Эквивалентом .()
переменных является by=
:
DT[, { paste(id,year,sep="_") }, by=list(id,year) ]
или
DT[, { do.call("paste",.BY) }, by=list(id,year) ]
Я показал {}
, чтобы проиллюстрировать, что вы можете поместить любое (многострочное) анонимное тело в j
(а не функцию), но в этих простых примерах вам не нужно {}
.
Группирующие переменные имеют длину 1 внутри области видимости каждой группы (похоже, это то, о чем вы спрашиваете), для скорости и удобства. .BY
также содержит группирующие переменные в одном объекте списка для общего доступа, когда by
критерии определяются программно на лету; т. Е. Когда вы не знаете by
переменные заранее.
Ответ №2:
Вы могли бы использовать:
ddply(baseball, .(id, year), function(x){data.frame(paste(x$id,x$year,sep="_"))})
Когда вы возвращаете вектор, объединение его обратно в data.frame превращает каждую запись в столбец. Но существуют разные длины, поэтому не все они имеют одинаковое количество столбцов. Заключая ее в data.frame()
, вы убедитесь, что ваша функция возвращает data.frame
столбец, который вы хотите, вместо того, чтобы полагаться на неявное (и в данном случае неправильное) преобразование. Кроме того, вы можете легко присвоить имя новому столбцу в этой конструкции.
Обновить:
Учитывая, что вы хотите оценить функцию только один раз (что разумно), вы можете просто извлечь первую строку самостоятельно и работать с ней.
ddply(baseball, .(id, year), function(x) {
x <- x[1,]
paste(x$id, x$year, sep="_")
})
Это будет (само по себе) иметь только одну строку для каждой комбинации id / year. Если вы хотите, чтобы в нем было столько же строк, сколько в оригинале, то вы можете объединить это с предыдущей идеей.
ddply(baseball, .(id, year), function(x) {
firstrow <- x[1,]
data.frame(label=rep(paste(firstrow$id, firstrow$year, sep="_"), nrow(x)))
})