【发布时间】:2017-06-27 09:53:47
【问题描述】:
使用 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 确实足够了。
我想出了这个,但我确定有更好的方法,特别是因为这仅适用于 cuplicated 值的第一个实例:
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
【问题讨论】:
-
@akrun 这里的主要问题是找到连续值。过滤 5 个或更多并不是真正的问题。我本来打算发
as.vector(unlist(sapply(split(x, cumsum(c(1, diff(x) != 0))), function(i) replace(i, length(i) >= 5, NA)))),但发现了骗子,所以我没有 -
@AF7 所以你不能从骗子那里推断出你的问题的答案?您可以在我没有发布的 cmets 中看到我的建议,因为我发现它与 1 个骗子相同(减去替换部分)。如果您不这么认为,我将删除欺骗并添加答案
-
@Sotos,我做不到,也许是因为我的智力有限 :) 无论如何我添加了基准,它们非常有趣。