使用列名包装purrr :: pmap周围的函数

时间:2018-02-02 11:47:24

标签: r lazy-evaluation purrr nse

我尝试编写一个包含purrr :: pmap_dbl()函数的简单函数。

我有以下数据:

df <- data.frame(
          col1 = 1:5, 
          col2 = 2:6, 
          col3 = 3:7
)

以下功能:

addfn <- function(x, y){
   x^2 + y
}

然后我想写一个像:

这样的函数
testfn <- function(data, a, b){
    purrr::pmap_dbl(data, function(a, b, ...) addfn(a, b))
}

不幸的是,testfn(df, col1, col2)在这种情况下会出错。我想获得与输出获得的输出相同的输出:

purrr::pmap_dbl(df, function(col1, col2, ...) addfn(col1, col2))

这样做的方法是什么?

3 个答案:

答案 0 :(得分:4)

您可以在地图中使用之前选择你的df:

library(rlang)
library(dplyr)
library(purrr)
testfn <- function(data, x, y){
  data <- select(data, !!enquo(x), !!enquo(y))
  pmap_dbl(data, ~ addfn(.x, .y))
}

testfn(df, col1, col3) 

答案 1 :(得分:1)

1)testfn 首先,请注意使用testfn来解决这个问题:

testfn(unname(df[c("col1", "col3")]))
## [1]  4  8 14 22 32

2)testfn2 我们可以将其修改为:

testfn2 <- function(data, ...) {
  data %>% select(...) %>% unname %>% purrr::pmap_dbl(addfn)
}

testfn2(df, col1, col3)
## [1]  4  8 14 22 32

testfn2(df, "col1", "col3")
## [1]  4  8 14 22 32

3)基础R 当然,正如已经指出的那样,我们并不需要为此做好准备。这适用于基数R,因为addfn是矢量化的:

with(df, addfn(col1, col3))
## [1]  4  8 14 22 32

或如果addfn没有被矢量化,那么:

with(df, mapply(addfn, col1, col3))
## [1]  4  8 14 22 32

我们可以使用标准评估来编写这个函数:

testfn3 <- function(data, a, b) mapply(addfn, df[[a]], df[[b]])

testfn3(df, "col1", "col3")
## [1]  4  8 14 22 32

或使用非标准评估:

testfn4 <- function(data, ...) eval.parent(substitute(
  with(data, mapply(addfn, ...))
))

testfn4(df, col1, col3)
## [1]  4  8 14 22 32

答案 2 :(得分:0)

或者您可以使用apply个功能。

addfn <- function(x){
  apply(x,1,function(y) y[1]^2 + y[2])
}

addfn(df[,1:2])
[1]  3  7 13 21 31

addfn(df[,2:3])
[1]  7 13 21 31 43