【问题标题】:Calculating the size of an winning and losing streak计算连续输赢的大小
【发布时间】:2011-06-12 07:35:07
【问题描述】:

我正在尝试计算连续输赢的大小,这个问题是我在尝试计算连续长度时遇到的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 和 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 行开始,尽管条件发生了变化,该函数仍使用了错误的输入。

我遗漏了什么明显的观点?

【问题讨论】:

  • 我还不够好,无法发布答案,但我的猜测是,您的 WinStreakSize 函数确实返回最长的连胜记录(获胜或失败)。在您的示例中,最长的连胜恰好是连胜。
  • @Henrik 你不是我。哇!我有点烦。
  • 顺便说一句:如果你看看rle 做了什么,我的另一个自我似乎是对的......
  • 有 29 个名为 Henrik 的用户。这个名字比我想象的更常见。

标签: function r


【解决方案1】:

rle(ifelse(x&gt;0,1,0))rle(ifelse(x&lt;0,1,0))rle(x&gt;0)rle(x&lt;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 计算总和、平均值等。在我构造了三个相同长度的向量(llsumsval)之后,我可以轻松地将长度、值和运行的总和链接在一起,然后选择我想要的任何内容。

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

【讨论】:

  • 感谢 Joris 的回答,这是一个非常优雅的解决方案(更少的代码导致更多的输出)。返回具有最大值的运行是完美的!我是否正确地指出代码中的ll 变量给出了索引,与val 结合使用可以访问特定点的值?在那种情况下,ll 的值不应该是唯一的以让 R 区分它们吗? (现在 JPM 是 1,4,2,1,2)。 (顺便说一句,这不是批评,解决方案是完美的。我只是想进一步了解您在解决这个问题时使用的想法。:))
  • @Jura25 Jori 的回答涵盖了我要说的内容 - 本质上,您在上一个 Q 中采用了其他答案之一,在我注意到如果连续下跌是比连胜更长的时间会选择那个。我在那里更新了我的答案,以展示如何获得连胜和连败,@Joris 的答案很好地结合了所有这些想法 (+1)
  • @Jura25 ll 是运行的长度,val 是这些运行的值(TRUE 或 FALSE),id 是要在原始向量 x 上使用的索引。 ngroups 是数量或运行。如果将 browser() 添加为函数的第一行,则可以检查它们的内部外观。另见?browser
  • 感谢 Joris 的进一步解释。 :)
  • @Gavin:你说得对,我仍然在我的脚本中使用“条纹长度”功能。 :) 顺便说一句,恭喜通过了 6.000 分的 Reputation。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 1970-01-01
  • 2019-05-11
  • 2023-04-10
  • 1970-01-01
  • 2018-11-09
相关资源
最近更新 更多