Search code examples
rscopingvegan

Data objects not found in embedded vegan:cca. Scoping issue?


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

Solution

  • 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
    }