使用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
和/或制作比下面的函数更快的额外奖励积分!
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
答案 0 :(得分:2)
我们可以创建一个逻辑索引来对values
和lengths
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
答案 1 :(得分:2)
这是另一种方法,
do.call(c, lapply(split(x, cumsum(c(1, diff(x) != 0))), function(i)
replace(i, length(i) >= 5, NA)))
# 11 12 2 3 4 51 52 6 71 72 73 74 75 76 77 78 79 8 91 92 10 11 12
# 1 1 2 1 3 -99 -99 3 NA NA NA NA NA NA NA NA NA 1 2 2 0 1 -99