我将一个标题传递给用户定义的函数,其中列名是变量。在研究了这个,这个,还有这个之后,我得到了下面这个函数。我的目标是在R包中包含一个等价的函数。我的问题是,虽然这个函数有效,但在dplyr/tidyval/tidyverse世界中是否有更正确的最佳实践?
library(tidyverse)
dat0 <- tibble( a = seq(as.Date('2022-02-10'), as.Date('2022-03-01'), by = "5 days")
, b = seq(10,40,10))
myCalc <- function(data, dateIn, numIn, yearOut, numOut) {
data <- data %>%
mutate(.
, {{yearOut}} := lubridate::year(.data[[dateIn]])
, {{numOut}} := 10 * .data[[numIn]]
) %>%
filter(.
, .data[[numOut]] > 250
)
}
dat2 <- myCalc(dat0
, dateIn = "a"
, numIn = "b"
, yearOut = "c"
, numOut = "d")
dat2
# A tibble: 2 × 4
a b c d
<date> <dbl> <dbl> <dbl>
1 2022-02-20 30 2022 300
2 2022-02-25 40 2022 400
既然您已经使用了花括号{{
运算符,那么您可以在函数中进一步实现带引号的参数:
myCalc <- function(data, dateIn, numIn, yearOut, numOut) {
data <- data %>%
mutate(.
, {{yearOut}} := lubridate::year({{ dateIn }})
, {{numOut}} := 10 * {{ numIn }}
) %>%
filter(.
, {{ numOut }} > 250
)
return(data)
}
你对字符串的使用确实有效(例如.data[[dateIn]]
,在你的例子中计算为.data[["a"]]
)。正如@r2evans在评论中提到的,差异真正出现在函数调用期间。
这个函数可以这样调用(注意参数中没有引号):
dat2 <- myCalc(dat0,
dateIn = a,
numIn = b,
yearOut = c,
numOut = d)
您可以阅读更多关于?rlang::`nse-defuse`
和?rlang::`nse-force`
的内容。还有一篇关于这个主题的文章。