使用 R,我有以下向量:
x <- c(1,1,2,1,3,-99,-99,3,rep(-99,9),1,2,2,0,1,-99)
x
[1] 1 1 2 1 3 -99 -99 3 -99 -99 -99 -99 -99 -99 -99 -99 -99 1 2 2 0 1 -99
我想删除连续值,但前提是连续值大于阈值,例如 5。所以在这种情况下,输出结果应该是:
[1] 1 1 2 1 3 -99 -99 3 1 2 2 0 1 -99
我知道我必须使用rle
,也许diff
来做到这一点,但我不知道如何有效地做到这一点。
我不认为建议的重复问题实际上是重复的,因为在这种情况下,仅查找和删除值的子集是问题的主要部分。如果不是这种情况,使用 rle
和 duplicates
确实就足够了。
我已经想出了这个,但我确信有更好的方法,特别是因为这仅适用于杯子复制值的第一个实例:
r <- rle(x)
toRemove <- which(r$lengths > 5)
startdupl <- sum(r$lengths[1:(toRemove-1)])+1
x[-(startdupl:(startdupl+r$lengths[toRemove]-1))]
该过程当然应该适用于长度 >5 的多个重复项。
如果我可以用 NA 替换这些值而不是删除它们,那就奖励积分!
使用dplyr
和/或制作比下面的函数更快的东西可以获得额外奖励!
在提出了一些好的建议之后,以下是我正在考虑的一些选项以及 30000 个元素向量的小基准:
f1 <- function(x) { inverse.rle(within.list(rle(x), values[lengths>5] <- NA))}
f2 <- function(x) {
r <- rle(x)
r$values[which(r$lengths>5)] <- NA
with(r, rep(values, lengths))
}
f3 <- function(x) {as.vector(unlist(sapply(split(x, cumsum(c(1,
diff(x) != 0))), function(i) replace(i, length(i) >= 5, NA))))}
f4 <- function(x) {do.call(c, sapply(split(x, cumsum(c(1, diff(x) != 0))), function(i) replace(i, length(i) >= 5, NA)))}
结果:
library(microbenchmark)
microbenchmark(f1(x), f2(x), f3(x), f4(x))
Unit: microseconds
expr min lq mean median uq max neval
f1(x) 559.445 602.3215 770.5779 652.395 660.6705 13108.82 100
f2(x) 542.203 560.0705 882.0940 611.087 618.6395 14982.19 100
f3(x) 50513.630 55523.6960 59338.0722 57408.724 60003.0870 145707.49 100
f4(x) 52599.398 57648.0445 60722.3351 60098.227 62113.3655 124074.32 100
最佳答案
我们可以创建一个逻辑索引来对值
和长度
进行子集化
with(rle(x), rep(values[lengths<=5], lengths[lengths<=5]))
#[1] 1 1 2 1 3 -99 -99 3 1 2 2 0 1 -99
如果我们要将长度大于5的元素替换为NA
inverse.rle(within.list(rle(x), values[lengths>5] <- NA))
#[1] 1 1 2 1 3 -99 -99 3 NA NA NA NA NA NA NA NA NA 1 2 2 0 1 -99
关于仅当超过 5 个连续的重复项时,才从向量中删除连续的重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44777276/