用户定义的函数参数-可以定义为什么参数?

时间:2020-02-21 17:14:31

标签: r function dplyr arguments user-defined-functions

我正在尝试编写R函数,这些函数执行与SAS中的宏类似的任务,例如

  1. 过程变量
  2. 命名新变量
  3. 命名新数据框

我使用内置的df“ iris”和dplyr尝试了一些基本功能,如下所示。

函数f3和f4尝试获取一个变量名并对其进行处理。错误消息是“错误:找不到对象'Species'”和“在mean.default(var)中:参数不是数字或逻辑:返回NA”。

函数f5和f6尝试命名新变量或新df。运行该函数后,新变量或df会以参数名称命名。

f7尝试使用该函数来命名变量的一部分。

library(dplyr)

data(iris)
view(iris)

### Char Variable
f3 <- function(var){
      iris %>% filter(var == "setosa")
}
f3(Species)

f4 <- function(var){
      iris %>% summarise(
            avg = mean(var)
      )
}
f4("Sepal.Length")

### Variable Name
f5 <- function(name){
      iris %>% 
            mutate(name = 1)
}
f5("newname")

### df Name
f6 <- function(dfname){
      dfname <- iris 
}
f6("newdf")

f7 <- function(name){
      test <- iris %>% 
            mutate(
                  v_name = 1
            )
}
f7("1")

1 个答案:

答案 0 :(得分:0)

使用tidyverse,如果我们不加引号,则可以将其转换为quosure(rlang::enquo)并求值(!!),这是通过{{}}卷曲卷曲来完成的运算符

f3 <- function(var){
  iris %>%
       filter({{var}} == "setosa")
 }
f3(Species)
#    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1           5.1         3.5          1.4         0.2  setosa
#2           4.9         3.0          1.4         0.2  setosa
#3           4.7         3.2          1.3         0.2  setosa
#4           4.6         3.1          1.5         0.2  setosa
#5           5.0         3.6          1.4         0.2  setosa
#...

f4也可以用相同的方式处理

f4 <- function(var){
  iris %>% 
      summarise(
        avg = mean({{var}})
      )
   }

f4(Sepal.Length)
#     avg
#1 5.843333

如果打算传递带引号或不带引号,请用ensym转换为符号并求值(!!

 f4 <- function(var){
  iris %>% 
    summarise(
        avg = mean(!! rlang::ensym(var))
   )
 }
 f4(Sepal.Length)
 #       avg
 #1 5.843333
 f4("Sepal.Length")
 #     avg
 #1 5.843333

对于f7,我们可以使用:=

library(stringr)
f7 <- function(name){
  iris %>% 
        mutate(
              !!str_c("v_", name) := 1
        )
 }

f7("1")
#      Sepal.Length Sepal.Width Petal.Length Petal.Width    Species v_1
#1            5.1         3.5          1.4         0.2     setosa   1
#2            4.9         3.0          1.4         0.2     setosa   1
#3            4.7         3.2          1.3         0.2     setosa   1
#4            4.6         3.1          1.5         0.2     setosa   1
#...

或与f5

f5 <- function(name){
  iris %>% 
        mutate(!! name := 1)
 }
f5("newname")
#     Sepal.Length Sepal.Width Petal.Length Petal.Width    Species newname
#1            5.1         3.5          1.4         0.2     setosa       1
#2            4.9         3.0          1.4         0.2     setosa       1
#3            4.7         3.2          1.3         0.2     setosa       1
#4            4.6         3.1          1.5         0.2     setosa       1
# ..

注意:如果我们将<-作为最后一个return语句,则需要将其分配给对象或用()包装以打印输出,即(f5("newname"))

f6正在assign创建对象,可以使用assign

f6 <- function(dfname){
   assign(dfname, value = iris, envir = .GlobalEnv) 
 }
f6("newdf")
head(newdf, 2)
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1          5.1         3.5          1.4         0.2  setosa
#2          4.9         3.0          1.4         0.2  setosa