使用Reduce调用功能列表

时间:2018-11-26 14:42:21

标签: r filter

我想在向量上使用过滤器列表。我的问题是,在此示例中,如何使用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 :(得分:6)

这里有一些替代方法。全部仅使用基数R。(2)使用Reduce。 (4)是具有最短代码。 (3)似乎特别简单。

1)外部,您实际上不需要Reduce。如果应用于outer的第j个元素的ith函数为TRUE,则使用my_vec创建第ith行第j列为TRUE的逻辑矩阵,然后使用apply创建一个逻辑矩阵。如果第j列中的所有元素都为TRUE,并且第一个下标为my_vec,则其jth元素为TRUE的向量。

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_listReduce中的每个函数进行“与”运算并取结果。然后使用Filter提取my_vec的那些元素,该函数的应用为其提供TRUE。

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

3)全部实际上,我们可以使用Reduce和几乎相同的代码来消除(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)双重申请:此人使用了上述想法,但在使用双重sapply时更加对称:

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

答案 1 :(得分:4)

使用Reduce的一种方法是:

my_vec[Reduce('&',lapply(filter_list,
                     function(f) {f(my_vec)}))]

答案 2 :(得分:2)

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"

答案 3 :(得分:1)

另一个版本,尽管感觉像是G. Grothendieck的第一个答案:

library(magrittr)

sapply(filter_list, mapply, my_vec) %>% apply(., 1, all) %>% my_vec[.]

答案 4 :(得分:1)

一些选项:

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"