rfunctiondplyrtidyversemetafor

Using metafor::escalc() in a function to optimise workflow


I am performing a meta analysis and am trying to streamline my workflow. Essentially, I have numerous variables with the form x_y_mean_time_int1, where x, y and time change depending on the outcome (eg dynamic_pain_mean_24h_int1 would be mean dynamic pain scores at 24 hours with intervention 1). I have also included code for the time that x isn't in the variable name (eg ome_mean_24h_int1)

My goal is to create a function that takes the different components of the variables, enables selection of a group of variables and feed that into metafor::escalc() to be able to meta analyse the data.

Here is a reproducible dataset:

library(tidyverse)
library(metafor)

# Create dataset
dat <- tibble(
  study = c("study1", "study2", "study3"),
  int1 = c("GA", "GA", "GA"),
  int2 = c("Spinal", "Epidural", "Spinal"),
  n_int1 = c(20, 25, 30),
  n_int2 = c(20, 25, 30),
  dynamic_pain_mean_24h_int1 = c(4.5, 4.7, 4.2),
  dynamic_pain_sd_24h_int1 = c(0.5, 0.7, 1.0),
  dynamic_pain_mean_24h_int2 = c(2.2, 2.1, 1.5),
  dynamic_pain_sd_24h_int2 = c(0.4, 0.6, 0.7),
  ome_mean_24h_int1 = c(54, 65, 70),
  ome_sd_24h_int1 = c(15, 20, 18),
  ome_mean_24h_int2 = c(40, 35, 50),
  ome_sd_24h_int2 = c(12, 17, 15),
)

Here is the function:

var_select <- function(df, x, y, z){
  if(missing(x)) {
    varname1 <- paste({y}, "mean", {z}, "int1", sep = "_")} 
  else {varname1 <- paste({x}, {y}, "mean", {z}, "int1", sep = "_")}
  
  if(missing(x)) {
    varname2 <- paste({y}, "sd", {z}, "int1", sep = "_")} 
  else {varname2 <- paste({x}, {y}, "sd", {z}, "int1", sep = "_")}
  
  if(missing(x)) {
    varname3 <- paste({y}, "mean", {z}, "int2", sep = "_")} 
  else {varname3 <- paste({x}, {y}, "mean", {z}, "int2", sep = "_")}
  
  if(missing(x)) {
    varname4 <- paste({y}, "sd", {z}, "int2", sep = "_")}
  else {varname4 <- paste({x}, {y}, "sd", {z}, "int2", sep = "_")}  
  
  dat <- df |> 
    dplyr::select(study, int1, int2, n_int1, n_int2, varname1:varname4) |> 
    drop_na()
  
  dat <- metafor::escalc(measure = "MD", 
                         n1i = n_int2, n2i = n_int1, 
                         m1i = varname1, sd1i = varname2, 
                         m2i = varname3, sd2i = varname4, 
                         data = dat)
}

When I run this, the error message states that m1i, sd1i, m2i and sd2i are not numeric. When I exclude the escalc() part of the function, the resultant variables are numeric. When using as.numeric(), the error message comes up that NAs are coercible.

I've tried using dat$varname1 and got this error:

The object/variable ('dat$varname1') specified for the 'm1i' argument is NULL.

Solution

  • You are passing literal strings to the arguments, which is not what escalc() expects as input. For example, this works:

    dat <- dat.bcg
    dat <- escalc(measure="RR", ai=tpos, bi=tneg, ci=cpos, di=cneg, data=dat)
    

    but this won't:

    dat <- escalc(measure="RR", ai="tpos", bi="tneg", ci="cpos", di="cneg", data=dat)
    

    But if you have (constructed) strings for the variable names, then this works:

    dat <- escalc(measure="RR", ai=dat[["tpos"]], bi=dat[["tneg"]], ci=dat[["cpos"]], di=dat[["cneg"]])