如何在R中向量化子集功能?

时间:2019-04-08 08:35:54

标签: r dplyr

我对某些函数进行了矢量化处理,这对清除代码,避免循环和提高速度非常有用。

但是,我无法根据该函数的输入对任何将数据帧子集化的函数进行矢量化处理

示例

例如该函数在接收元素时效果很好

test_funct <- function(sep_wid, sep_len) {
    iris %>% filter(Sepal.Width > sep_wid & Sepal.Length < sep_len) %>% .$Petal.Width %>% sum
}

test_funct(4, 6)

# [1] 0.7 # This works nicely

但是在尝试提供向量作为此函数的输入时:

sep_wid_vector <- c(4, 3.5, 3)
sep_len_vector <- c(6, 6, 6.5)


test_funct(sep_wid_vector, sep_len_vector)

[1] 9.1 

但是所需的输出是长度与输入向量相同的向量,就好像该函数在每个向量的第一个元素上运行,然后是第二个,然后是第三个元素。即

# 0.7    4.2     28.5 

为方便起见,这里的输出就像它们都是单独运行一样

test_funct(4, 6) # 0.7
test_funct(3.5, 6) # 4.2
test_funct(3, 6.5) # 28.5

如何对一个基于输入的数据子集的函数进行矢量化处理,以便可以接收矢量输入?

3 个答案:

答案 0 :(得分:5)

您可以使用Vectorize

tv <- Vectorize(test_funct)

tv(sep_wid_vector, sep_len_vector)
# [1]  0.7  4.2 28.5

这基本上是mapply的包装。请注意,在后台运行的是*apply函数,这完全是一个循环

答案 1 :(得分:4)

问题在于filter接受向量输入,因此它将在Sepal.widthSepal.length比较中循环使用向量。

一种方法是使用map2包中的purrr

map2_dbl(sep_wid_vector, sep_len_vector, test_funct)

当然,您可以将其包装在函数中。您可能还需要考虑将数据帧作为函数参数传递。

答案 2 :(得分:1)

这是使用sapply

的一种方法
# function using sapply
test_funct <- function(sep_wid, sep_len) {
  sapply(seq_along(sep_wid), function(x) {
    sum(iris$Petal.Width[iris$Sepal.Width > sep_wid[x] & iris$Sepal.Length < sep_len[x]])
  })
}

# testing with single value
test_funct(4,6)
[1] 0.7

# testing with vectors
test_funct(sep_wid_vector, sep_len_vector)
[1]  0.7  4.2 28.5