简体   繁体   English

在R中使用lapply从函数调用中的向量返回实际函数参数

[英]Returning actual function argument from vector in function call with lapply in R

Please consider the following.请考虑以下事项。

I want to use lapply() to subsequently apply several function arguments stored in a character vector to some other function.我想使用lapply()随后将存储在字符向量中的几个函数参数应用于其他函数。 A minimal reproducible example could be to apply two or more "families" to the glm() function.一个最小的可重现示例可能是将两个或多个“族”应用于glm()函数。 Please note that the example might be nonsensical for applying such families and is used for illustration purposes only.请注意,该示例对于应用此类族可能毫无意义,仅用于说明目的。

The following is taken from the example in ?glm()以下内容取自?glm()中的示例

counts <- c(18,17,15,20,10,20,25,13,12)
outcome <- gl(3,1,9)
treatment <- gl(3,3)
data.frame(treatment, outcome, counts) # showing data

We can now run a GLM with family "gaussian" or "poisson"我们现在可以运行带有家族“高斯”或“泊松”的 GLM

glm(counts ~ outcome + treatment, family = "gaussian")
glm(counts ~ outcome + treatment, family = "poisson")

This could also be "automated" by creating a character vector with these family names:这也可以通过创建具有这些姓氏的字符向量来“自动化”:

families <- c("poisson", "gaussian")

And using this in an lapply() function.并在lapply()函数中使用它。

But once this runs, the returned function call does not return the family names anymore but the anonymous function argument x .但是一旦运行,返回的函数调用不再返回姓氏,而是返回匿名函数参数x

lapply(families, function(x) glm(counts ~ outcome + treatment, family = x))
#> [[1]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = x)
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   3.045e+00   -4.543e-01   -2.930e-01   -3.242e-16   -2.148e-16  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       10.58 
#> Residual Deviance: 5.129     AIC: 56.76
#> 
#> [[2]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = x)
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   2.100e+01   -7.667e+00   -5.333e+00    2.221e-15    2.971e-15  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       176 
#> Residual Deviance: 83.33     AIC: 57.57

Question: How can the family names from the vector families be preserved/shown in the function call after lapply() ?问题:如何在lapply()之后的函数调用中保留/显示来自向量families的家族名称?


Desired outcome: The outcome should look like this:期望的结果:结果应该是这样的:

#> [[1]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = "gaussian")
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   3.045e+00   -4.543e-01   -2.930e-01   -3.242e-16   -2.148e-16  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       10.58 
#> Residual Deviance: 5.129     AIC: 56.76
#> 
#> [[2]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = "poisson")
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   2.100e+01   -7.667e+00   -5.333e+00    2.221e-15    2.971e-15  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       176 
#> Residual Deviance: 83.33     AIC: 57.57

I tried eval(bquote(x)) as suggested here: R: Passing named function arguments from vector , but this did not work.我按照这里的建议尝试eval(bquote(x))R: Passing named function arguments from vector ,但这不起作用。 See:看:

lapply(families, function(x) glm(counts ~ outcome + treatment, family = eval(bquote(x))))
#> [[1]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = eval(bquote(x)))
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   3.045e+00   -4.543e-01   -2.930e-01   -3.242e-16   -2.148e-16  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       10.58 
#> Residual Deviance: 5.129     AIC: 56.76
#> 
#> [[2]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = eval(bquote(x)))
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   2.100e+01   -7.667e+00   -5.333e+00    2.221e-15    2.971e-15  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       176 
#> Residual Deviance: 83.33     AIC: 57.57

Created on 2022-07-22 by the reprex package (v2.0.1)reprex 包于 2022-07-22 创建 (v2.0.1)

Thank you!谢谢!

An approach could be to extract the family name and add it to the formula within each model object.一种方法是提取族名并将其添加到每个模型对象内的公式中。 For instance like this:例如像这样:

lapply(families, \(fam) { model <- glm(counts ~ outcome + treatment, family = fam); model$call[3] <- model$family$family; return(model)})

Output:输出:

[[1]]

Call:  glm(formula = counts ~ outcome + treatment, family = "poisson")

Coefficients:
(Intercept)     outcome2     outcome3   treatment2   treatment3  
  3.045e+00   -4.543e-01   -2.930e-01   -3.242e-16   -2.148e-16  

Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
Null Deviance:      10.58 
Residual Deviance: 5.129    AIC: 56.76

[[2]]

Call:  glm(formula = counts ~ outcome + treatment, family = "gaussian")

Coefficients:
(Intercept)     outcome2     outcome3   treatment2   treatment3  
  2.100e+01   -7.667e+00   -5.333e+00    2.221e-15    2.971e-15  

Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
Null Deviance:      176 
Residual Deviance: 83.33    AIC: 57.57

Depending on the purpose, you could also (just) name your elements in your vector and each list element would have its name.根据目的,您还可以(仅)命名向量中的元素,并且每个列表元素都有其名称。

families <- c(poisson = "poisson", gaussian = "gaussian")
lapply(families, function(x) glm(counts ~ outcome + treatment, family = x))

Output:输出:

$poisson

Call:  glm(formula = counts ~ outcome + treatment, family = x)

Coefficients:
(Intercept)     outcome2     outcome3   treatment2   treatment3  
  3.045e+00   -4.543e-01   -2.930e-01   -3.242e-16   -2.148e-16  

Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
Null Deviance:      10.58 
Residual Deviance: 5.129    AIC: 56.76

$gaussian

Call:  glm(formula = counts ~ outcome + treatment, family = x)

Coefficients:
(Intercept)     outcome2     outcome3   treatment2   treatment3  
  2.100e+01   -7.667e+00   -5.333e+00    2.221e-15    2.971e-15  

Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
Null Deviance:      176 
Residual Deviance: 83.33    AIC: 57.57

Update with approach 1.使用方法 1 更新。

A more direct way to do this would be to build and evaluate the call directly inside lapply更直接的方法是直接在lapply内部构建和评估调用

lapply(families, function(x) {
  eval(as.call(list(quote(glm), 
               formula = counts ~ outcome + treatment, 
               data = quote(df), 
               family = x)))
  })
#> [[1]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = "poisson", 
#>     data = df)
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   3.045e+00   -4.543e-01   -2.930e-01    1.338e-15    1.421e-15  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       10.58 
#> Residual Deviance: 5.129     AIC: 56.76
#> 
#> [[2]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = "gaussian", 
#>     data = df)
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   2.100e+01   -7.667e+00   -5.333e+00    2.056e-16    7.252e-16  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       176 
#> Residual Deviance: 83.33     AIC: 57.57

Created on 2022-07-22 by the reprex package (v2.0.1)reprex 包于 2022-07-22 创建 (v2.0.1)

Yet another possible solution:另一个可能的解决方案:

families <- c("gaussian", "poisson") 
lapply(families, \(x) eval(parse(text=paste0("glm(counts ~ outcome + treatment, 
  df, family = ", x, ")"))))

#> [[1]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = gaussian, 
#>     data = df)
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   2.100e+01   -7.667e+00   -5.333e+00    8.729e-16    7.252e-16  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       176 
#> Residual Deviance: 83.33     AIC: 57.57
#> 
#> [[2]]
#> 
#> Call:  glm(formula = counts ~ outcome + treatment, family = poisson, 
#>     data = df)
#> 
#> Coefficients:
#> (Intercept)     outcome2     outcome3   treatment2   treatment3  
#>   3.045e+00   -4.543e-01   -2.930e-01    1.011e-15    7.105e-16  
#> 
#> Degrees of Freedom: 8 Total (i.e. Null);  4 Residual
#> Null Deviance:       10.58 
#> Residual Deviance: 5.129     AIC: 56.76

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM