我正在尝试计算连胜的大小,这个问题是我在尝试计算长度时的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行开始,尽管改变了条件,该函数仍使用不正确的输入。
我错过了什么明显的观点?
答案 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
计算总和,均值等。在我构造了三个相同长度的向量(ll
,sums
和val
)之后,我可以轻松地将长度,值和运行总和链接在一起并选择我想要的任何内容离开。
使用rle(x> 0)的一个优点是您可以将值用作索引,这极大地简化了事情。