计算连胜的大小

时间:2011-01-20 08:49:53

标签: function r

我正在尝试计算连胜的大小,这个问题是我在尝试计算长度时的earlier question的后续行动。连胜。

这就是我的数据:

> subRes
   Instrument TradeResult.Currency.
1         JPM                    -3
2         JPM                   264
3         JPM                   284
4         JPM                    69
5         JPM                   283
6         JPM                  -219
7         JPM                   -91
8         JPM                   165
9         JPM                   -35
10        JPM                  -294
11        KFT                    -8
12        KFT                   -48
13        KFT                   125
14        KFT                  -150
15        KFT                  -206
16        KFT                   107
17        KFT                   107
18        KFT                    56
19        KFT                   -26
20        KFT                   189
> dput(subRes)
structure(list(Instrument = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("JPM", 
"KFT"), class = "factor"), TradeResult.Currency. = c(-3, 264, 
284, 69, 283, -219, -91, 165, -35, -294, -8, -48, 125, -150, 
-206, 107, 107, 56, -26, 189)), .Names = c("Instrument", "TradeResult.Currency."
), class = "data.frame", row.names = c(NA, 20L))

我的目标: 我想计算每种乐器最长连胜的大小。因此,对于JPM,这将是上述数据中的行2,3,4和5,它给出以下TradeResult.Currency.值:264 + 284 + 69 +283,总计900 JPM最长连跌的大小将是第9行和第10行,总结果为-329(-35 + -294)。对于KFT,最长连胜的大小是270(107 + 107 + 56,行16到18),最长连续的大小是-356(-150 + -206,第14行和第14行) ; 15)。

以下函数给出了连胜的正确大小......

WinStreakSize <- function(x){
    df.rle <- ifelse(x > 0, 1, 0)
    df.rle <- rle(df.rle)
    wh <- which(df.rle$lengths == max(df.rle$lengths))
    mx <- df.rle$lengths[wh]
    suma <- df.rle$lengths[1:wh]
    out <- x[(sum(suma) - (suma[length(suma)] - 1)):sum(suma)]
    return(sum(out))
}

..导致:

> with(subRes, tapply(TradeResult.Currency., Instrument, WinStreakSize)
+ )
JPM KFT 
900 270

然而,我似乎不能熟练地使用这个函数来显示最长连续条纹的大小(因此它会为JPM输出-329而对于KFT输出-356),这听起来多么愚蠢。我尝试以多种方式更改功能,剥离它并重建它,我找不到它的原因。

这就是我的意思(从调试函数输出,其中x值是分割subRes后JPM的值):

Browse[2]>  ifelse(x > 0, 1, 0)
 [1] 0 1 1 1 1 0 0 1 0 0
Browse[2]>  ifelse(x < 0, 1, 0)
 [1] 1 0 0 0 0 1 1 0 1 1
Browse[2]> rle( ifelse(x > 0, 1, 0))
Run Length Encoding
  lengths: int [1:5] 1 4 2 1 2
  values : num [1:5] 0 1 0 1 0
Browse[2]> rle( ifelse(x < 0, 1, 0))
Run Length Encoding
  lengths: int [1:5] 1 4 2 1 2
  values : num [1:5] 1 0 1 0 1
Browse[2]> inverse.rle( ifelse(x > 0, 1, 0))
Error in x$lengths : $ operator is invalid for atomic vectors
Browse[2]> rle( !ifelse(x < 0, 1, 0))
Run Length Encoding
  lengths: int [1:5] 1 4 2 1 2
  values : logi [1:5] FALSE TRUE FALSE TRUE FALSE

因此,更改此函数中的条件对函数的输出没有影响。这表明我正在寻找解决方案的函数的错误部分,但ifelse语句是函数的第一个。换句话说,从第1行开始,尽管改变了条件,该函数仍使用不正确的输入。

我错过了什么明显的观点?

1 个答案:

答案 0 :(得分:5)

rle(ifelse(x>0,1,0))主要与rle(ifelse(x<0,1,0))rle(x>0)rle(x<0)相同,但不同之处在于运行的值不同。但是你从不使用函数中的运行值,所以这并不重要。当你选择长度而不是数值时,很明显你每次都会得到相同的结果。

让我简化一下。通过底层函数,我演示了运行长度和总计的计算。考虑到您在问题中的解决方案并不准确:JPM有2个最长的负面运行。我选择只返回绝对值最大的那个。

MaxStreakSize <- function(x){
    # Get the run lengths and values
    df.rle <- rle(x>0)
    ngroups <- length(df.rle$lengths)
    ll <- df.rle$lengths
    val <- df.rle$values

    # calculate the sums
    id <- rep(1:ngroups,ll)
    sums <- tapply(x,id,sum)

    # find the largest runs for positive (val) and negative (!val)
    rmax <- which(ll==max(ll[val]) & val )
    rmin <- which(ll==max(ll[!val]) & !val )

    out <- list(
            "Lose"=c("length"=max(ll[rmin]),
                      "sum"=min(sums[rmin])),
            "Win"=c("length"=max(ll[rmax]),
                    "sum"=max(sums[rmax]))
            )
    return(out)
}

在这些问题中,根据组的数量和运行的长度来获得某种索引是非常好的。这让生活变得更加容易。这允许我用简单的tapply计算总和,均值等。在我构造了三个相同长度的向量(llsumsval)之后,我可以轻松地将长度,值和运行总和链接在一起并选择我想要的任何内容离开。

使用rle(x> 0)的一个优点是您可以将值用作索引,这极大地简化了事情。