我试图计算一个连胜的大小,这个问题是我在尝试计算条纹长度时的早期问题的后续跟进.
这就是我的数据:
> 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))
Run Code Online (Sandbox Code Playgroud)
我的目标:
我想计算每种乐器最长连胜的大小.因此,对于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和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))
}
Run Code Online (Sandbox Code Playgroud)
.. 导致:
> with(subRes, tapply(TradeResult.Currency., Instrument, WinStreakSize)
+ )
JPM KFT
900 270
Run Code Online (Sandbox Code Playgroud)
但是,我似乎不能熟练地使用这个函数来显示最长连续条纹的大小(因此它会为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
Run Code Online (Sandbox Code Playgroud)
因此,更改此函数中的条件对函数的输出没有影响.这表明我正在寻找解决方案函数的错误部分,但ifelse
声明是函数的第一部分.换句话说,从第1行开始,尽管改变了条件,该函数仍使用不正确的输入.
我错过了什么明显的观点?
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)
}
Run Code Online (Sandbox Code Playgroud)
在这些问题中,基于组的数量和运行的长度来获得某种索引是非常好的.这让生活变得更加容易.这允许我用简单的方法计算总和,均值等tapply
.我建成后的长度相同的三个矢量(ll
,sums
和val
),我可以链接长度,价值和运行容易一起的总和,并选择任何我想要脱身.
使用rle(x> 0)的一个优点是可以将值用作索引,这大大简化了事情.