从 xts 对象中删除连续的重复行
Remove sequential repeating rows from xts object
假设我有以下包含出价和要价数据的 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
仅当行与上一个条目相同时才应删除行。如果出价或要价发生变化,则不会删除任何内容,因此简单地删除重复项是行不通的。
这应该是相当简单的,因为我以前做过,但我就是不记得怎么做,也找不到。
更新:
我在我的初始数据和预期输出中添加了一些额外的条目。
Joshua 的 swearer 很聪明,但它依赖于 rowSums 等函数给出不同的结果,但它与 9 12 不符。
我使用了 matrixStats 包中的 rowProds 函数,该函数有效,但显然我的最后两行失败了。此外,我的示例中第一列中的值小于第二列中的值。虽然这是有道理的,但它不是必须的,因此如果 Ask 小于 Bid,则 rowSums 和 rowProds 都将失败时,该函数应该可以工作。
是否有更好的行函数,如果有任何不同,例如可能是行哈希,总是会给出不同的结果?
您可以通过对每行的总和使用 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
(你总是想要第一个观察值)然后删除 [= 的最后一个元素16=]。然后对结果调用 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()
出价和要价以及 select 两者都不为零的行。
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))),]
假设我有以下包含出价和要价数据的 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
仅当行与上一个条目相同时才应删除行。如果出价或要价发生变化,则不会删除任何内容,因此简单地删除重复项是行不通的。
这应该是相当简单的,因为我以前做过,但我就是不记得怎么做,也找不到。
更新: 我在我的初始数据和预期输出中添加了一些额外的条目。
Joshua 的 swearer 很聪明,但它依赖于 rowSums 等函数给出不同的结果,但它与 9 12 不符。 我使用了 matrixStats 包中的 rowProds 函数,该函数有效,但显然我的最后两行失败了。此外,我的示例中第一列中的值小于第二列中的值。虽然这是有道理的,但它不是必须的,因此如果 Ask 小于 Bid,则 rowSums 和 rowProds 都将失败时,该函数应该可以工作。 是否有更好的行函数,如果有任何不同,例如可能是行哈希,总是会给出不同的结果?
您可以通过对每行的总和使用 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
(你总是想要第一个观察值)然后删除 [= 的最后一个元素16=]。然后对结果调用 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()
出价和要价以及 select 两者都不为零的行。
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))),]