【问题标题】:Filtering a vector on condition根据条件过滤向量
【发布时间】:2019-10-23 06:02:07
【问题描述】:

我正在尝试过滤整数向量。
我的条件是 2 个连续元素之间的距离至少应为 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]

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

【问题讨论】:

标签: r vector filter


【解决方案1】:
unique(Reduce(function(x,y)ifelse(y-x>=100,y,x),input,accumulate = T))
[1]  24 128 228 356 532 634 839 997

【讨论】:

  • 朋友不要让朋友使用ifelse()进行标量比较,或者T用于TRUEunique(Reduce(function(x, y) if (y - x &gt;= 100) y else x, input, accumulate = TRUE))
  • @MartinMorgan 我同意。谢谢
【解决方案2】:

没有经过彻底测试,但我相信这可以帮助您。我正在使用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)] }

【讨论】:

    猜你喜欢
    • 2019-06-08
    • 1970-01-01
    • 2018-10-08
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多