2011-01-20 30 views
4

我在计算大小的一个连胜,这个问题是我在试图计算长度的时候的一个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行)。

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

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值是JPM的价值观分裂subRes后):

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行开始,功能使用不正确的输入,尽管改变条件。

我缺少什么明显的观点?

+2

我没有足够好的答案,但我的猜测是,你的WinStreakSize函数真正返回最长的连胜(获胜或失败)。在你的例子中,最长的条纹恰好是连胜。 – Henrik 2011-01-20 09:05:38

+0

@亨利克你不是我。哇!我有点恼火。 – Henrik 2011-01-20 09:16:15

回答

5

rle(ifelse(x>0,1,0))主要与rle(ifelse(x<0,1,0))rle(x>0)rle(x<0)相同,但区别在于运行值不同。但是你永远不会使用函数中的运行值,所以这并不重要。当你选择长度而不是数值时,显然你会再次得到相同的结果。

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

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来计算总和,等等。在我构建了三个相同长度的向量(ll,sumsval)之后,我可以很容易地将长度,值和运行总和链接起来,然后选择我想要出来的任何东西。

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