当R中的默认值为NULL时,如何指定参数对象?

How can I specify an argument object when the default is NULL in R?

提问人:Reid 提问时间:10/11/2023 更新时间:10/11/2023 访问量:49

问:

我正在尝试编写一个函数,将某些参数的默认值设置为 NULL。但是,当我在调用函数时将这些参数指定为不为 NULL 时,我收到找不到这些对象的错误。

简单的启动功能:

library(dplyr)
toydf <- data.frame(Name = "Fred", Age="Old", Hair="Brown")
toyA <- function(df, groupA){
  data.frame(A = df%>%dplyr::select({{groupA}}))
}
toyA(toydf, Name)
toyA(toydf, Age)

我想指定一些参数以具有 NULL 默认值,这似乎和这似乎表明应该有效。我试试这个:

toyB <- function(df, groupA, groupB=NULL, groupC=NULL){
  if((!is.null(groupB)) & (!is.null(groupC))){
    data.frame(A = df%>%dplyr::select({{groupA}}),
               B = df%>%dplyr::select({{groupB}}),
               C = df%>%dplyr::select({{groupC}}))
  }
  else{
    data.frame(A = df%>%dplyr::select({{groupA}}))
  }
}

但这给我带来了错误:

toyB(toydf, Name, Age, Hair)
Error in toyB(toydf, Name, Age, Hair) : object 'Age' not found

我们可以通过检查其他一些问题和解决方案来解决这个问题。missing()

toyC <- function(df, groupA, groupB, groupC){
  if((!missing(groupB)) & (!missing(groupC))){
    data.frame(A = df%>%dplyr::select({{groupA}}),
               B = df%>%dplyr::select({{groupB}}),
               C = df%>%dplyr::select({{groupC}}))
  }
  else{
    data.frame(A = df%>%dplyr::select({{groupA}}))
  }
}
toyC(toydf,Name)
toyC(toydf, Name, Age, Hair)

为什么 NULL 默认值不起作用?

R 函数 null 默认值

评论

1赞 Calum You 10/11/2023
还没有打开 R 进行测试,所以这是一个评论,但可以肯定的是,这是一个非标准的评估。你{{}} select里面的参数,但在检查is.null时不能,所以R尝试检查,解析为,然后找不到要检查的对象(因为它是数据帧的一列)。is.null(groupB)is.null(Age)Age
1赞 MrFlick 10/11/2023
stackoverflow.com/questions/68007842/ 的可能重复......当您检查时,您正在评估指向的 promise,并且该变量在您检查时不存在,它仅存在于 data.frame 中。dup 向您展示了如何避免早期评估。is.null(GroupB)Ageis.null

答:

1赞 Onyambu 10/11/2023 #1

您应该直接在 中使用 NSE。select

toyB <- function(df, groupA, groupB=NULL, groupC=NULL){
  df %>% select({{groupA}}, {{groupB}}, {{groupC}})
}

toyB(head(iris), Species)
  Species
1  setosa
2  setosa
3  setosa
4  setosa
5  setosa
6  setosa

toyB(head(iris), Species, Sepal.Length, Sepal.Width)
  Species Sepal.Length Sepal.Width
1  setosa          5.1         3.5
2  setosa          4.9         3.0
3  setosa          4.7         3.2
4  setosa          4.6         3.1
5  setosa          5.0         3.6
6  setosa          5.4         3.9

评论

2赞 LMc 10/11/2023
我想OP正在用这些变量做更多的事情,但是如果他们所做的只是简单地选择,那么他们可以做:toyB <- function(df, ...) df %>% select(...)
0赞 jay.sf 10/11/2023
toyB <- \(df, ...) df[sapply(substitute(...()), deparse)]可能更有效率。
0赞 Onyambu 10/11/2023
@jay.sf 这完全取决于 OP 是否有兴趣再次使用变量名称。如果不需要,那么甚至应该工作toyB <- \(df, ...) df[as.character(substitute(...()))]
0赞 jay.sf 10/11/2023
@Onyambu 效率更高,真实。
0赞 Reid 10/17/2023
我的帖子不清楚我的真实需求。我主要试图弄清楚如何正确检查参数是否为空。这与实际选择列无关。我相信 MrFlick 在我的帖子下的链接问题是我需要的。