计算数据中的连续条纹

Jur*_*ura 9 r

我正在尝试计算数据集中的最大输赢(即最大连续正值或负值).我在StackOverflow上找到了一个有点相关的问题,虽然这给了我一些很好的建议,但这个问题的角度是不同的,而且我还没有足够的经验来翻译并将这些信息应用到这个问题上.所以我希望你可以帮助我,即使一个建议会很棒.

我的数据集如下所示:

> 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
> split(subRes[,2],subRes[,1])
$JPM
 [1]   -3  264  284   69  283 -219  -91  165  -35 -294
$KFT
 [1]   -8  -48  125 -150 -206  107  107   56  -26  189
Run Code Online (Sandbox Code Playgroud)

在这种情况下,JPM的最大(获胜)条纹为4(即264,284,69和283连续阳性结果),对于KFT,该值为3(107,107,56).

我的目标是创建一个函数,该函数给出每个乐器的最大连胜条件(即JPM:4,KFT:3).为此:

R需要将当前结果与先前结果进行比较,如果它更高,则存在至少2个连续正结果的条纹.然后R需要查看下一个值,如果这个值也更高:在已经找到的值2上加1,如果这个值不高,R需要继续下一个值,同时记住2为中间最大值.

我已经尝试cumsumcummax按照条件求和(如cumsum(c(TRUE, diff(subRes[,2]) > 0))),但没有成功.也rle按照lapply(像lapply(rle(subRes$TradeResult.Currency.), function(x) diff(x) > 0))没有工作.

我怎样才能做到这一点?

编辑2011年1月19日

计算条纹的大小 除了条纹的长度,我还想在我的分析中加入条纹的大小.通过下面提供的答案,我以为我能够自己做到这一点,遗憾的是我错了并遇到以下问题:

使用以下数据框:

> 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
> lapply(split(subRes[,2], subRes[,1]), 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(out)
+         })
$JPM
[1] 264 284  69 283

$KFT
[1] 107 107  56
Run Code Online (Sandbox Code Playgroud)

这个结果是正确的,将最后一行改为return(sum(out))I可以得到条纹的总大小:

$JPM
[1] 900

$KFT
[1] 270
Run Code Online (Sandbox Code Playgroud)

但是,在更改ifelse条件时,该功能似乎不计算丢失条纹:

lapply(split(subRes[,2], subRes[,1]), 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(out)
        })
$JPM
[1] 264 284  69 283

$KFT
[1] 107 107  56
Run Code Online (Sandbox Code Playgroud)

我没有看到我需要改变这个功能,最终得出连败的总和.但是,我调整/更改功能,我得到相同的结果或错误.这个ifelse函数让我很困惑,因为它似乎是改变函数的明显部分,但不会导致任何改变.我错过了什么明显的观点?

Rei*_*son 11

这将有效:

FUN <- function(x, negate = FALSE, na.rm = FALSE) {
    rles <- rle(x > 0)
    if(negate) {
        max(rles$lengths[!rles$values], na.rm = na.rm)
    } else {
        max(rles$lengths[rles$values], na.rm = na.rm)
    }
}
wins <- lapply(split(subRes[,2],subRes[,1]), FUN)
loses <- lapply(split(subRes[,2],subRes[,1]), FUN, negate = TRUE)
Run Code Online (Sandbox Code Playgroud)

给这个:

> wins
$JPM
[1] 4

$KFT
[1] 3
> loses
$JPM
[1] 2

$KFT
[1] 2
Run Code Online (Sandbox Code Playgroud)

要么:

> sapply(split(subRes[,2],subRes[,1]), FUN)
JPM KFT 
  4   3
> sapply(split(subRes[,2],subRes[,1]), FUN, negate = TRUE)
JPM KFT 
  2   2 
Run Code Online (Sandbox Code Playgroud)

你很接近,但是你需要分别应用rle()列表中的每个元素,并且还要转换TradeResult.Currency.为逻辑向量,具体取决于0以上.我们的函数FUN只返回返回lengths的对象的组件rle,我们应用max()这个长度向量来找到最长的获胜运行.

请注意,这里split是没有必要的,你可以用其他的子集的因素和申请功能功能(tapply,aggregate,等),在这里:

> with(subRes, aggregate(`TradeResult.Currency.`, 
+                        by = list(Instrument = Instrument), FUN))
  Instrument x
1        JPM 4
2        KFT 3
> with(subRes, tapply(`TradeResult.Currency.`, Instrument, FUN))
JPM KFT 
  4   3
Run Code Online (Sandbox Code Playgroud)

早期版本不正确的原因是因为如果你有一系列的损失而不是胜利(更长的一系列负值),那么就会导致选择损失序列的长度.

修改后的函数添加了一个'negate'参数来交换测试的含义.如果我们想获胜,我们离开TRUE,并FALSE$values他们的.如果我们想要亏损,我们互换TRUEFALSE.然后,我们可以使用此$values组件仅选择与wins(negate = TRUE)对应的运行或与loss()对应的运行negate = FALSE.