代码之家  ›  专栏  ›  技术社区  ›  MichaelE

从xts对象中删除连续重复行

xts r
  •  2
  • MichaelE  · 技术社区  · 7 年前

    假设我有以下包含买卖数据的XTS对象:

       Time     Bid    Ask
       00:01    10     11
       00:02    10     11
       00:03    11     12
       00:04    12     13
       00:05    10     11
       00:06    10     11
       00:07    10     11
    
       00:08    9      12
       00:09    2      10
       00:10    4      5
    

       Time     Bid    Ask
       00:01    10     11
       00:03    11     12
       00:04    12     13
       00:05    10     11
    
       00:08    9      12
       00:09    2      10
       00:10    4      5
    

    只有当行与上一个条目相同时,才应删除行。如果有出价或要价变更,则不会删除任何内容,因此简单地删除重复项将不起作用。

    更新: 我在初始数据和预期输出中添加了一些额外的条目。

    我使用了matrixStats包中的rowProds函数,该函数可以工作,但在我的最后两行中显然失败了。此外,我的示例第1列中的值小于第2列中的值。虽然这是有道理的,但它不是必须的,因此如果Ask小于Bid,则该函数应该可以工作,因为行和和和和和和和和和与行Prod都会失败。 有没有更好的行函数,如果有什么不同的结果,比如行散列,它总是会给出不同的结果?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Joshua Ulrich    7 年前

    您可以使用 rle() 关于每行的总和。

    x <- structure(
      c(10L, 10L, 11L, 12L, 10L, 10L, 10L, 11L, 11L, 12L, 13L, 11L, 11L, 11L),
      .Dim = c(7L, 2L), .Dimnames = list(NULL, c("Bid", "Ask")),
      index = structure(1:7, tzone = "", tclass = c("POSIXct", "POSIXt")),
      .indexCLASS = c("POSIXct", "POSIXt"), .indexTZ = "",
      tclass = c("POSIXct", "POSIXt"), tzone = "", class = c("xts", "zoo"))
    r <- rle(rowSums(x))
    

    如果你想要每组中的最后一个观察结果,你可以使用 cumsum(r$lengths)

    R> x[cumsum(r$lengths),]
                        Bid Ask
    1969-12-31 18:00:02  10  11
    1969-12-31 18:00:03  11  12
    1969-12-31 18:00:04  12  13
    1969-12-31 18:00:07  10  11
    

    由于您希望对每组进行第一次观察,因此需要预先准备 r$lengths 1 (您总是需要第一次观察),然后删除 r$长度 . 然后打电话 cumsum() 关于结果。

    R> x[cumsum(c(1, head(r$lengths, -1))),]
                        Bid Ask
    1969-12-31 18:00:01  10  11
    1969-12-31 18:00:03  11  12
    1969-12-31 18:00:04  12  13
    1969-12-31 18:00:05  10  11
    

    很好地抓住了 rowSums() . 稳健的解决方案是 diff() bids和ASK并选择其中一行不为零的行。

    d <- diff(x) != 0           # rows with price changes
    d[1,] <- TRUE               # always select first observation
    g <- cumsum(d$Bid | d$Ask)  # groups of repeats
    r <- rle(as.numeric(g))     # run length encoding on groups
    
    # now use the solution above
    x[cumsum(c(1, head(r$lengths, -1))),]