Используйте Reduce для вызова списка функций - PullRequest
0 голосов
/ 26 ноября 2018

Я хотел бы использовать список фильтров для вектора.Мой вопрос состоит в том, как я могу использовать Reduce (или другую базовую стандартную функцию R), чтобы делать то, что делает рекурсивная функция (= применение всех функций в filter_list и логических-И-соединениях) в этом примере:

my_vec <- c("AAffff1", "AAafszx223", "AAasfe2XX", "uuse3", "AA232fiserf", "ffse1211", "766", "AA33")

filter_list <- list(
  f_1 = function(x) {substr(x, 1, 2) == "AA"},
  f_2 = function(x) {grepl("\\d{3,}", x)},
  f_3 = function(x) {nchar(x) >= 5})

my_call <- function(fun_list, x) {
  if (length(fun_list) == 1) {
    fun_list[[1]](x) 
  } else {
    my_call(fun_list[-length(fun_list)], x) & fun_list[[length(fun_list)]](x)
  }
}
my_vec[my_call(filter_list, my_vec)]
# [1] "AAafszx223"  "AA232fiserf" --> ok

my_vec[Reduce(function(f, ...) f(...), filter_list, my_vec, right = TRUE)]
# character(0) --> wrong

Ответы [ 5 ]

0 голосов
/ 04 декабря 2018

Несколько вариантов:

library(purrr)
my_vec[reduce(map(filter_list, ~.(my_vec)), `&`)]
# [1] "AAafszx223"  "AA232fiserf"

my_vec[reduce(filter_list, ~ .x & .y(my_vec), .init = TRUE)]
# [1] "AAafszx223"  "AA232fiserf"

my_vec[apply(map_dfr(filter_list, ~.(my_vec)),1,all)]
# [1] "AAafszx223"  "AA232fiserf"
0 голосов
/ 26 ноября 2018

Другая версия, хотя она выглядит как производная от Г. Гротендика 1-й ответ:

library(magrittr)

sapply(filter_list, mapply, my_vec) %>% apply(., 1, all) %>% my_vec[.]
0 голосов
/ 26 ноября 2018

Один из способов использования Reduce будет:

my_vec[Reduce('&',lapply(filter_list,
                     function(f) {f(my_vec)}))]
0 голосов
/ 26 ноября 2018

purrr вариант.

  • invoke_map принимает список функций в качестве первого аргумента и сопоставляет эти функции с аргументами в ....

  • reduce('&') возвращает вектор, который равен TRUE, если все соответствующие записи в векторах списка LHS равны TRUE (аналогично Reduce('&').

  • keep(.x = vec, .p = logical_vec) совпадает с vec[logical_vec].

-

library(purrr)

invoke_map(filter_list, x = my_vec) %>%
  reduce(`&`) %>% 
  keep(.x = my_vec)

# [1] "AAafszx223"  "AA232fiserf"
0 голосов
/ 26 ноября 2018

Вот несколько альтернатив.Все используют только базу R. (2) использует Reduce.(4) имеет самый короткий код.(3) кажется особенно простым.

1) внешний Вам на самом деле не нужно Reduce для этого.Используйте outer для создания логической матрицы, чья i-я строка и j-й столбец равны TRUE, если i-я функция, примененная к j-му элементу my_vec, равна TRUE, а затем из этого используйте apply, чтобы создать логический вектор, чей j-й элемент равен TRUE.если все элементы в j-м столбце имеют значение ИСТИНА и, наконец, индекс my_vec тем самым.

call_fun <- function(fun, x) fun(x)
my_vec[ apply(outer(filter_list, my_vec, Vectorize(call_fun)), 2, all) ]
## "AAafszx223"  "AA232fiserf"

2) Уменьшить С другой стороны, мы, безусловно, можем использовать Reduce.Создайте функцию, которая принимает символьную строку и вызывает для нее каждую функцию в filter_list, используя Reduce для AND результатов.Затем используйте Filter для извлечения тех элементов my_vec, для которых применение этой функции дает TRUE.

Filter(function(x) Reduce(`&`, lapply(filter_list, do.call, list(x))), my_vec)
## [1] "AAafszx223"  "AA232fiserf"

3) all На самом деле мы могли бы исключить Reduce in (2) с использованием all и почти идентичного кода.

Filter(function(x) all(sapply(filter_list, do.call, list(x))), my_vec)
## [1] "AAafszx223"  "AA232fiserf"

4) Другой вариант заключается в следующем.sapply создает матрицу, аналогичную, но транспонированную из матрицы в (1), и затем мы применяем all к ее строкам и индексу.

my_vec[ apply(sapply(filter_list, do.call, list(my_vec)), 1, all) ]
[1] "AAafszx223"  "AA232fiserf"

5) double sapply This oneиспользует идеи из вышеизложенного, но немного более симметричен в использовании двойного sapply:

my_vec[ sapply(my_vec, function(x) all(sapply(filter_list, do.call, list(x)))) ]
## [1] "AAafszx223"  "AA232fiserf"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...