I try to embed cca
(and also capscale
) from package vegan (version 2.5-7, R 4.1.2) in another function to test an analysis pipeline with some data transformation and then varying model formulas. The used data matrices (e.g. bio
and env
) can have different names and are normally not visible in the global work space. The error that I get is:
Error in eval(match.call()$data, environment(formula), enclos = .GlobalEnv) :
object 'env' not found
that looks like a scoping issue. Looking around, it seems that vegan had some problems with scoping in the past that are said to be fixed, so I wonder if I overlooked something. Any workaround is also welcome, e.g. environment manipulation.
library("vegan")
## create some example data
set.seed(123)
bio <- matrix(sample(0:10, 50, replace = TRUE), nrow = 10)
env <- data.frame(
x = sample(1:10, 10),
y = 1:10 rnorm(10),
z = rnorm(10)
)
cca(bio ~ x y, data = env) # works
## enclose cca with some other stuff in a function
foo <- function(model, bio, env) {
## do preparatory data transformation
fm <- cca(model, data = env)
print(fm)
## do something else
}
model <- formula(bio ~ x y) # works
foo(model, bio=bio, env=env)
## now rename data to test scoping
bio2 <- bio
env2 <- env
rm(bio, env)
foo(model, bio = bio2, env = env2) # error
# Error in eval(match.call()$data, environment(formula), enclos = .GlobalEnv) :
# object 'env' not found
CodePudding user response:
Yes, looks to be a scoping issue. I think the key is to update the formula's environment inside the function:
foo <- function(model, bio, env) {
# update model environment
environment(model) = environment()
## do preparatory data transformation
fm <- cca(model, data = env)
print(fm)
## do something else
}