0

I'm looking to assign a data.frame to the global environment so that the name of the data.frame is the same as the one passed into a function I create. The typical way to do this is using assign(arg_name, x, envir = .GlobalEnv):

my_fun <- function(x) {
  
  arg_name <- deparse(substitute(x)) 
  print(arg_name)
  
  x[["newvariable"]] <- 1
  
  assign(arg_name, x, envir = .GlobalEnv)

}

my_fun(mtcars)

which works but I'm trying to do the short hand version using "super-assignment": <<-. I haven't been able to make it work as it just returns a data.frame called arg_name rather than mtcars:

my_fun2 <- function(x) {
  
  arg_name <- deparse(substitute(x)) 
  print(arg_name)
  
  x[["newvariable"]] <- 1
  
  arg_name <<- x
}

my_fun2(mtcars)

Any suggestions? Also, is deparse(substitute(x)) still the best (shortest) way to extract the name of the data.frame for this type of case?

Thanks

user63230
  • 4,095
  • 21
  • 43
  • 3
    `<<-` does not necessarily assign to the global environment. If you want to do this, use `assign`. But, can you explain why you are doing this? R tries to be a functional language and you are breaking that paradigm (and doing that is not recommended). There are a few cases where that can be justified (usually for better performance) but I don't see that here. – Roland Jun 23 '20 at 13:33
  • thanks this seems to answer my question (just use `assign`)... The only reason was to shorten `assign(arg_name, x, envir = .GlobalEnv)` syntax using `<<-`. I often use `<<-` if I `source` a long script (where I create its own environment) that has many objects in it but I just want one object passed from that environment to the global one to be used in other analysis – user63230 Jun 23 '20 at 13:42
  • 3
    Yes, very bad practice. You are creating code that is confusing to others and difficult to maintain. Learn to create and use functions with proper return values instead. – Roland Jun 23 '20 at 13:44
  • 2
    In R, it is usually recommended that the scoping operator, `<<-`, and `assign` are rarely used, if not used at all. See Dirk's final quoted warning in your linked SO post: *The Evil and Wrong use is to modify variables in the global environment.* – Parfait Jun 23 '20 at 14:02

1 Answers1

1

As said in the comments that it is a bad practice, but it's worth understanding why the second variant of function not working.

my_fun2 <- function(x) {
  
  arg_name <- deparse(substitute(x))  #line 1
  print(arg_name)                       
  
  x[["newvariable"]] <- 1
  
  arg_name <<- x                      #line 4
}

In line 1, you have created a variable arg_name that exists only in function's loval environment. Whereas in line 4, you have created another variable arg_name. If you were to use <- it would overwrite the arg_name value in line 1, but since you are using <<- operator, it behaves differently. <<- will cause a search for arg_name in parent environment (1 level above, not in function environment) and if in case the variable is not found in the search path, a new variable arg_name will be created in your Global Env.

Hence you see, the name of your dataframe as arg_name in your global env, rather than mtcars.

As per the best approach, the first function seems to be the one.

Alternate approach could be to use a combination of eval and substitute, but with caution.

my_fun3 <- function(x){
    arg_name <- deparse(substitute(x))
    x[['newvariable']] <- 1
    eval(substitute(arg_name <- x), env=.GlobalEnv)
}
monte
  • 1,482
  • 1
  • 10
  • 26