根据条件过滤向量

时间:2019-06-07 18:01:03

标签: r vector filter

我正在尝试过滤整数向量。
我的条件是连续两个元素之间的距离至少应为100;如果不是,请删除该元素并查看下一个候选元素。
这是一个示例:

set.seed(42)
input <- sort(sample(1:1000, 20))
head(input, 20)


[1] 24  49  74 128 146 153 165 228 303 321 356 410 532 561 601 622 634 839 882 997

如果我从第一个元素24开始,我想保持与第一个元素的距离至少为100。
在这种情况下,它将是128

然后,从128,重复相同的过程。
结果应该是:

24 128 228 356 532 634 839 997

我设法创建了一个快速且肮脏的循环,该循环给出了正确的结果,但是我可以猜到,对于很大的向量来说,效率不是很高...

result <- integer(length(input))
result[1] <- input[1]
for(i in seq_along(input)[-1]) {
  if(is.na(input[2])) break

  if(input[2] - input[1] < 100) {
    input <- input[-2]
  } else {
    result[i] <- input[2]
    input <- input[-1]
  }
}

result <- result[result != 0]

获得预期结果的有效方法是什么?可以使用向量化吗?

2 个答案:

答案 0 :(得分:6)

unique(Reduce(function(x,y)ifelse(y-x>=100,y,x),input,accumulate = T))
[1]  24 128 228 356 532 634 839 997

答案 1 :(得分:3)

没有经过全面测试,但是我相信这可以帮助您实现目标。我正在使用purrr::accumulate。这是一个非常巧妙的问题:-)希望看到其他解决方案/方法,所以也许让它保持开放状态(未回答)...

library(purrr)

input <- c(24, 49, 74, 128, 146, 153, 165, 228, 303, 321, 356, 410, 532, 561, 601, 622, 634, 839, 882, 997)
idx <- which(accumulate(diff(input), ~ ifelse(.x >= 100, .y, .x + .y)) >= 100)
input[c(1, idx + 1)]
#> [1]  24 128 228 356 532 634 839 997

为了使它读得更多purrr,我想我们可以这样做:

accumulate(diff(input), ~ if_else(.x >= 100, .y, .x + .y)) %>%
  map_lgl(~ . >= 100) %>%
  which %>%
  { input[c(1, . + 1)] }