【问题标题】:Passing the Data Argument in R User Defined Functions在 R 用户定义函数中传递数据参数
【发布时间】:2023-10-09 23:12:01
【问题描述】:

对于 R 中的 lm() 之类的函数,您将“数据”参数传递给函数,通常是一个数据框,然后 R 通过名称而不是引用它们来知道所有列。所以区别在于x=column,而不是引用时尚x=df$column。那么如何在我自己的用户定义函数中使用相同的方法呢?

一个简单的例子:

library(tidyverse)

df <- tibble(x=1:100,y=x*(1+rnorm(n=100)))

test_corr <- function(x,y) {
  cor(x,y) %>% return()
}

# Right now I would do this
test_corr(df$x,df$y)

# I want to be able to do this
test_corr(data=df, x, y)

【问题讨论】:

  • 你能举个例子说明你想到的函数类型以及你想如何调用它吗?
  • 如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则更容易为您提供帮助。
  • @camille 感谢您的反馈,我附上了我正在寻找的示例。
  • @MrFlick 感谢您的反馈,我附上了我正在寻找的示例。

标签: r function arguments user-defined-functions


【解决方案1】:

由于您使用的是tidyverse 函数,因此对此类任务使用整洁的评估是有意义的。对于这个功能,你可以做

test_corr <- function(data, x, y) {
  quo( cor({{x}}, {{y}}) ) %>% 
    rlang::eval_tidy(data=data)
}

test_corr(df, x, y)

首先,我们确定构建您要评估的表达式,然后我们使用{{ }}(拥抱)语法将您传递给函数的变量名插入到表达式中。然后,我们会在您使用eval_tidy 提供的data.frame 的上下文中评估该quosure。

您可能还对tidyselect 包小插图感兴趣,其中讨论了更多选项。

【讨论】:

    【解决方案2】:

    你可以使用reformulate

    apply_fun <- function(response, terms, data) {
       lm(reformulate(terms, response), data)
    }
    
    apply_fun("mpg", "cyl", mtcars)
    #Call:
    #lm(formula = reformulate(terms, response), data = data)
    
    #Coefficients:
    #(Intercept)          cyl  
    #     37.885       -2.876  
    
    apply_fun("mpg", c("cyl", "am"), mtcars)
    
    #Call:
    #lm(formula = reformulate(terms, response), data = data)
    
    #Coefficients:
    #(Intercept)          cyl           am  
    #     34.522       -2.501        2.567  
    

    【讨论】: