使用多个输入简化ave()或aggregate()

时间:2010-09-29 16:40:29

标签: r aggregate time-series simplify

如何将这一切写在一行?

mydata"zoo"系列,限制是相同大小的数字向量

tmp <- ave(coredata(mydata), as.Date(index(mydata)),
           FUN = function(x) cummax(x)-x)
tmp <- (tmp < limit)
final <- ave(tmp, as.Date(index(mydata)),
             FUN = function(x) cumprod(x))

我尝试使用两个向量作为ave(...)的参数,但即使我将它们加入矩阵,它似乎只接受一个。

这只是一个例子,但可以使用任何其他功能。

这里我需要将cummax(mydata)-mydata的值与数字向量进行比较 一旦它超过它我将保持零直到一天结束。 cummax从每天开始计算。

如果限制是单个数字而不是矢量(具有不同的可能数字),我可以写它:

ave(coredata(mydata), as.Date(index(mydata)),
    FUN = function(x) cumprod((cummax(x) - x) < limit))

但是我不能在那里引入一个长于x的向量(它应该具有与每天相同的长度)并且我不知道如何将它作为ave()中的另一个参数引入。

1 个答案:

答案 0 :(得分:1)

似乎这个例程基于maxdrawdown强加了日内止损。所以我假设你希望能够将变量限制作为第二个参数传递给聚合函数,由于ave的工作方式,目前只需要1个函数。

如果将所有这些放在一行中并不是绝对必须的,我可以共享一个我写过的函数,它通过“cut variables”来推广聚合。这是代码:

mtapplylist2 <- function(t, IDX, DEF, MoreArgs=NULL, ...)
{
  if(mode(DEF) != "list")
  {
    cat("Definition must be list type\n");
    return(NULL);
  }

  a        <- c();
  colnames <- names(DEF);
  for ( i in 1:length(DEF) )
  {
    def  <- DEF[[i]];
    func <- def[1];
    if(mode(func) == "character") { func <- get(func); }
    cols <- def[-1];

    # build the argument to be called
    arglist      <- list();
    arglist[[1]] <- func;
    for( j in 1:length(cols) )
    {
      col <- cols[j];
      grp <- split(t[,col], IDX);
      arglist[[1+j]] <- grp;
    }
    arglist[["MoreArgs"]] <- MoreArgs;
    v <- do.call("mapply", arglist);
    # print(class(v)); print(v);
    if(class(v) == "matrix")
    {
      a <- cbind(a, as.vector(v));
    } else {
      a <- cbind(a, v);
    }
  }
  colnames(a) <- colnames;
  return(a);
}

你可以像这样使用它:

# assuming you have the data in the data.frame
df  <- data.frame(date=rep(1:10,10), ret=rnorm(100), limit=rep(c(0.25,0.50),50))

dfunc <- function(x, ...) { return(cummax(x)-x ) }
pfunc <- function(x,y, ...) { return((cummax(x)-x) < y) }

# assumes you have the function declared in the same namespace
def <- list(
 "drawdown"    = c("dfunc", "ret"),
 "hasdrawdown" = c("pfunc", "ret", "limit")
);

# from R console
> def <- list("drawdown" = c("dfunc", "ret"),"happened" = c("pfunc","ret","limit"))
> dim( mtapplylist2(df, df$date, def) )
[1] 100   2

请注意,“def”变量是包含以下项目的列表:

  • 计算列名
  • 将arg函数名称作为字符串
  • 输入data.frame中输入到函数
  • 的变量的名称

如果你看一下“mtapplylist2”函数的内容,关键组件将是“拆分”和“mapply”。这些功能足够快(我认为拆分是用C实现的)。

这适用于需要多个参数的函数,也适用于返回相同大小或聚合值的向量的函数。

尝试一下,让我知道这是否能解决您的问题。