Фильтрация вектора по условию - PullRequest
8 голосов
/ 07 июня 2019

Я пытаюсь отфильтровать вектор целых чисел.
Мое условие - расстояние между двумя последовательными элементами должно быть не менее 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 ]

6 голосов
/ 07 июня 2019
unique(Reduce(function(x,y)ifelse(y-x>=100,y,x),input,accumulate = T))
[1]  24 128 228 356 532 634 839 997
3 голосов
/ 07 июня 2019

Тщательно не проверено, но я верю, что это поможет вам.Я использую 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)] }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...