2011-01-20 36 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)的一個優點是您可以將值用作索引,這大大簡化了事情。