jmpsteen / medflex

Flexible mediation analysis using natural effect models in R
23 stars 6 forks source link

Medflex within functions #16

Open JonasBeal opened 5 years ago

JonasBeal commented 5 years ago

Dear medflex authors,

Thanks for this very convenient package. I have some problems when I try to use medflex functions within another function. This seems to me to be related to scoping problems, perhaps related to issues 6 or 14. However, the answers to these issues did not allow me to solve my problem satisfactorily. Here are examples.

1) Not working example

dta <- UPBdata
fmla <- UPB~att+negaff

return_direct_effect <- function(fmla, dta){
  output <- Reduce(paste, deparse(fmla[[2]]))#Left-hand variable as character
  input <- as.character(fmla[[3]][[2]])#Exposure variable as character

  expData <- neImpute(fmla, dta, family = gaussian)
  neMod <- neModel(as.formula(paste0(output, "~", input, "0+", input, "1")),
                   family = gaussian, expData = expData,
                   se = "bootstrap", nBoot = 10, progress=F)
  DE <- unname(neMod$neModelFit$coefficients[2])
  return(DE)
}
return_direct_effect(UPB~att+negaff, UPBdata)

Last command results in :

Error in eval(args$data, environment(stats::formula(fit))) : object 'dta' not found

Please note that naming my dta variable data as suggested in issue 14 for xFit seems to circumvent the problem but result in a new one

Error in data[[x]] : object of type 'closure' is not subsettable

2) Without function

If I remove the functional form it works fine:

dta <- UPBdata
fmla <- UPB~att+negaff
output <- Reduce(paste, deparse(fmla[[2]]))#Left-hand variable as character
input <- as.character(fmla[[3]][[2]])#Exposure variable as character

expData <- neImpute(fmla, dta, family = gaussian)
neMod <- neModel(as.formula(paste0(output, "~", input, "0+", input, "1")),
                   family = gaussian, expData = expData,
                   se = "bootstrap", nBoot = 10, progress=F)
DE <- unname(neMod$neModelFit$coefficients[2])

3) Force global variable

By the way, if I force my function/local variable to be global, putting the following code at the beginning of my function in 1), it works but it seems a little unsatisfactory

dta <<- dta
fmla <<- fmla

Thanks a lot for your insights and your time

kaz-yos commented 4 years ago

I seem to be having the same problem trying to run neWeight() within purrr:pmap() to examine different mediator model settings. I have a nested tibble with each row containing a formula, data tibble, and model fit. I wanted to run neWeight() in each row. The same data object not found error was encountered.

kaz-yos commented 4 years ago

It seems to stem from the discrepancy of the environment the model formula was defined and the environment in which the dataset resides. I'll try to resolve this.

eval(args$data, environment(stats::formula(fit)))