Применение скользящего среднего по группе в R

Я новичок в R, и у меня много проблем с чем-то, что, вероятно, очень просто. У меня есть большой набор данных, разбитый на группы по коду страны, и я хочу взять 3-месячный скользящий средний индекс цен по странам, а затем поместить его в новый столбец, соответствующий соответствующему месяцу. Я пытаюсь использовать rollmean как это без успеха (коды и сообщения об ошибках ниже):

> leader$last3<-tapply(leader, leader$ccode, 
    function(x) rollmean(leader$GI_delta, 3, na.pad=T))
Error in tapply(leader, leader$ccode, function(x) rollmean(leader$GI_delta,  : 
  arguments must have same length

> leader$last3<-ddply(leader, .(ccode), 
    rollmean(GI_delta, 3, na.pad=T))

Error in llply(.data = .data, .fun = .fun, ..., .progress = .progress,  : 
  .fun is not a function.

Любая помощь будет очень признательна!

Ответ 1

Если вы хотите создать новый столбец, попробуйте использовать ave. Он напоминает tapply, но возвращает вектор той же длины, что и его первый аргумент. Мой опыт в том, что он намного быстрее, чем ddply:

require(zoo)
leader$last3<-ave(leader$GI_delta, leader$ccode, 
                         FUN= function(x) rollmean(x, k=3, na.pad=T) )

Ответ 2

В вашей первой попытке ваша функция не использует свой аргумент x и всегда возвращает одно и то же (вектор с неправильным размером). Кроме того, первым аргументом должен быть вектор. Наконец, tapply возвращает список векторов: вы не можете поместить результат непосредственно в файл data.frame.

library(zoo)
n <- 10
leader <- data.frame(
  ccode = rep(LETTERS[1:3],each=n),
  GI_delta = rnorm(3*n)
)
tapply(
  leader$GI_delta, 
  leader$ccode, 
  function(x) rollmean(x, 3, na.pad=TRUE)
)

В вашем втором примере третий аргумент plyr должна быть функцией, а не выражением. Если вы хотите использовать выражение, вы можете использовать summarize или transform как функция (summarize возвращает 1-строчный data.frame для каждого значения ccode, тогда как transform сохраняет количество строк без изменений), и поместите выражения в качестве дополнительных аргументов.

library(plyr)
ddply(
  leader, "ccode",
  transform,
  last3 = rollmean( GI_delta, 3, align="right", na.pad=TRUE )
)