将未加引号的字符参数列表列表传递给 apply/map/pmap 调用 [英] Pass a list of lists of unquoted character parameters to an apply/map/pmap call

查看:38
本文介绍了将未加引号的字符参数列表列表传递给 apply/map/pmap 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个函数来进行某种类型的分析:

I have created a function to do a certain type of analysis:

library(tidyverse)
library(mediation)

causal_med_so <- function(predictor, mediator, outcome, data, ...){
  
  if(!missing(...)) {
    data <- {{data}} %>%
      dplyr::select({{predictor}}, {{mediator}}, {{outcome}}, ...) %>% 
      dplyr::filter(across(.cols = everything(), .fns = ~ !is.na(.)))
    
    predictor <- enquo(predictor)
    mediator <- enquo(mediator)
    outcome <- enquo(outcome)
    
    med.form <- formula(paste0(
      quo_name(mediator), "~",
      paste0(
        quo_name(predictor), "+",
        paste0(c(...), collapse = "+"), 
        collapse = "+"
      )
    ))
    
    med.fit <- eval(bquote(lm(.(med.form), data = data)))
    
    out.form <- formula(paste0(quo_name(outcome), "~",
                               paste0(
                                 quo_name(predictor), "+",
                                 quo_name(mediator), "+",
                                 paste0(c(...), collapse = "+"),
                                 collapse = "+"
                               )))
    
    out.fit <- eval(bquote(lm(.(out.form), data = data)))
    
    med.out <- mediation::mediate(med.fit, out.fit,
                                  treat = quo_name(predictor),
                                  mediator = quo_name(mediator),
                                  boot=T, boot.ci.type = "bca")
    return(med.out)
  } else {
    data <- {{data}} %>%
      dplyr::select({{predictor}}, {{mediator}}, {{outcome}}) %>% 
      dplyr::filter(across(.cols = everything(), .fns = ~ !is.na(.)))
    
    predictor <- enquo(predictor)
    mediator <- enquo(mediator)
    outcome <- enquo(outcome)
    
    med.form <- formula(paste0(quo_name(mediator), "~", quo_name(predictor)))
    
    med.fit <- eval(bquote(lm(.(med.form), data = data)))
    
    out.form <- formula(paste0(quo_name(outcome), "~",
                               quo_name(predictor), "+", quo_name(mediator)))
    
    out.fit <- eval(bquote(lm(.(out.form), data = data)))
    
    med.out <- mediation::mediate(med.fit, out.fit,
                                  treat = quo_name(predictor),
                                  mediator = quo_name(mediator),
                                  boot=T, boot.ci.type = "bca")
    return(med.out)
  }
}

该功能似乎按预期工作:

The function appears to work as intended:

 causal_med_so(mpg, cyl, qsec, mtcars) 

我现在想在 apply/map/pmap 调用中使用此函数以所有可能的组合同时运行多个模型:

I would now like to use this function in an apply/map/pmap call to run many models at once in all possible combinations:

param_list <- list(
  predictor = c("mpg", "cyl"),
  mediator = c("drat", "disp", "wt", "cyl"),
  outcome = c("qsec", "gear", "carb", "hp"),
  data = c("mtcars")
) %>%
  cross()

我正在尝试做这样的事情:

I am trying to do something like this:

lmap(param_list, causal_med_so)
lapply(param_list, causal_med_so)

但我遇到一些错误消息,表明列表元素被视为字符.我尝试了几种 noquote()syms()!!!syms() 的组合,但似乎无法找到解决方案.

But I am encountering some error messages that suggest the list elements are being treated as characters. I have tried several combinations of noquote(), syms(), !!!syms() but can't quite seem to find a solution.

推荐答案

由于这些是字符串,最好转换为 symbol 并评估 (!!) (为了测试,只使用了'param_dat'的前两行(将cross改为cross_df,以返回一个tibble)

As these are strings, it is better convert to symbol and evaluate (!!) (For testing, used only the first two rows of 'param_dat' (changed cross to cross_df so as to return a tibble)

causal_med_so <- function(predictor, mediator, outcome, data, ...){
  predictor <- rlang::ensym(predictor)
  mediator <- rlang::ensym(mediator)
  outcome <- rlang::ensym(outcome)
 
 
 if(!missing(...)) {
     data <- get(data, envir = .GlobalEnv) %>%
       dplyr::select(!!predictor, !!mediator, !!outcome, ...) %>% 
       dplyr::filter(across(.cols = everything(), .fns = ~ !is.na(.)))
    
     predictor <- enquo(predictor)
     mediator <- enquo(mediator)
     outcome <- enquo(outcome)
    
     med.form <- formula(paste0(
       quo_name(mediator), "~",
       paste0(
         quo_name(predictor), "+",
         paste0(c(...), collapse = "+"), 
         collapse = "+"
       )
     ))
    
     med.fit <- eval(bquote(lm(.(med.form), data = data)))
    
     out.form <- formula(paste0(quo_name(outcome), "~",
                                paste0(
                                  quo_name(predictor), "+",
                                  quo_name(mediator), "+",
                                  paste0(c(...), collapse = "+"),
                                  collapse = "+"
                                )))
    
     out.fit <- eval(bquote(lm(.(out.form), data = data)))
    
     med.out <- mediation::mediate(med.fit, out.fit,
                                   treat = quo_name(predictor),
                                   mediator = quo_name(mediator),
                                   boot=T, boot.ci.type = "bca")
     return(med.out)
   } else {
 
    data <- get(data, envir = .GlobalEnv) %>%
      dplyr::select(!!predictor, !!mediator, !!outcome) %>% 
      dplyr::filter(across(.cols = everything(), .fns = ~ !is.na(.)))
    
    
    
  med.form <- formula(paste0(quo_name(mediator), "~", quo_name(predictor)))
  
  med.fit <- eval(bquote(lm(.(med.form), data = data)))
  
  out.form <- formula(paste0(quo_name(outcome), "~",
                             quo_name(predictor), "+", quo_name(mediator)))
  
  out.fit <- eval(bquote(lm(.(out.form), data = data)))
  
  med.out <- mediation::mediate(med.fit, out.fit,
                                treat = quo_name(predictor),
                                mediator = quo_name(mediator),
                                boot=T, boot.ci.type = "bca")
  return(med.out)
  }
  
  


}

-测试

param_dat <- list(
  predictor = c("mpg", "cyl"),
  mediator = c("drat", "disp", "wt", "cyl"),
  outcome = c("qsec", "gear", "carb", "hp"),
  data = c("mtcars")
)    %>% cross_df

out <- param_dat %>%
        slice_head(n = 2)%>%
     pmap(., causal_med_so)
Running nonparametric bootstrap

Running nonparametric bootstrap

-输出

> str(out)
List of 2
 $ :List of 56
  ..$ d0           : num -0.0731
  ..$ d1           : num -0.0731
  ..$ d0.ci        : Named num [1:2] -0.1545 0.0325
  .. ..- attr(*, "names")= chr [1:2] "3.053716%" "97.96547%"
  ..$ d1.ci        : Named num [1:2] -0.1545 0.0325
  .. ..- attr(*, "names")= chr [1:2] "3.053716%" "97.96547%"
  ..$ d0.p         : num 0.158
  ..$ d1.p         : num 0.158
  ..$ d0.sims      : num [1:1000, 1] -0.0181 -0.0445 -0.0792 -0.1008 -0.088 ...
  ..$ d1.sims      : num [1:1000, 1] -0.0181 -0.0445 -0.0792 -0.1008 -0.088 ...
  ..$ z0           : num 0.197
  ..$ z1           : num 0.197
  ..$ z0.ci        : Named num [1:2] 0.0461 0.3122
  .. ..- attr(*, "names")= chr [1:2] "1.787667%" "96.56288%"
  ..$ z1.ci        : Named num [1:2] 0.0461 0.3122
  .. ..- attr(*, "names")= chr [1:2] "1.787667%" "96.56288%"
...

这篇关于将未加引号的字符参数列表列表传递给 apply/map/pmap 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆