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

发布于 2024-09-25 14:17:10 字数 812 浏览 5 评论 0原文

我怎样才能把这一切写在一行中?

mydata 是一个 "zoo" 系列,limit 是一个相同大小的数值向量

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 从每天开始计算。

如果 limit 是一个数字而不是一个向量(具有不同的可能数字),我可以这样写:

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

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

How can I write this all in one line?

mydata is a "zoo" series, limit is a numeric vector of the same size

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))

I've tried to use two vectors as argument to ave(...) but it seems to accept just one even if I join them into a matrix.

This is just an example, but any other function could be use.

Here I need to compare the value of cummax(mydata)-mydata with a numeric vector and
once it surpasses it I'll keep zeros till the end of the day. The cummax is calculated from the beginning of each day.

If limit were a single number instead of a vector (with different possible numbers) I could write it:

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

But I can't introduce there a vector longer than x (it should have the same length than each day) and I don't know how to introduce it as another argument in ave().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

反话 2024-10-02 14:17:10

似乎这个例程根据最大回撤施加日内止损。因此,我假设您希望能够将变量 limit 作为第二个参数传递给聚合函数,由于 ave 的工作方式,该函数目前仅需要 1 个函数。

如果将所有这些放在一行中并不是绝对必须的,我可以共享一个我编写的函数,该函数通过“剪切变量”来概括聚合。代码如下:

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”函数的内部结构,就会发现关键组件是“split”和“mapply”。这些函数足够快(我认为 split 是用 C 实现的)。

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

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

Seems like this routine imposes intraday stoploss based on maxdrawdown. So I assume you want to be able to pass in variable limit as a second argument to your aggregation function which only currently only takes 1 function due to the way ave works.

If putting all this in one line is not an absolute must, I can share a function I've written that generalizes aggregation via "cut variables". Here's the code:

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);
}

And you can use it like this:

# 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

Notice that the "def" variable is a list containing the following items:

  • computed column name
  • vector arg function name as a string
  • name of the variable in the input data.frame that are inputs into the function

If you look at the guts of "mtapplylist2" function, the key components would be "split" and "mapply". These functions are sufficiently fast (I think split is implemented in C).

This works with functions requiring multiple arguments, and also for functions returning vector of the same size or aggregated value.

Try it out and let me know if this solves your problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文