Assign a dynamic function to Global Environment in R


Assign a dynamic function to Global Environment in R



This question will be a simple one for some members of this forum, but I am expending a lot of time searching for an answer and I did not find any working one.
Let me clarify: I have a simple function that conducts a linear regression, and the results become a variable and this variable is assigned to the global environment. Straightforward method.



However, every time I run this function, the variable is replaced, what I don't want.
I just want to define a specific name instead of replacing this variable.



Please check out this code to understand my question:


set.seed(123)
ds <- data.frame(income=rnorm(1000,700,20), sex=c(0,1), age=rnorm(1000,30,10))

regress <- function(iv_string) {
regression_formula <- as.formula(paste("income ~", iv_string))
results <<- lm(regression_formula, ds)
plot(results)
print(results)
}
regress("age")
regress("sex")



Something like that


regress <- function(iv_string, **custom_name**) {
regression_formula <- as.formula(paste("income ~", iv_string))
results[**custom_name**] <<- lm(regression_formula, ds)
plot(results)
print(results)
}
regress("sex","sex_on_income") #this model will be used in other analysis, once it will be assigned at global environment
regress("age","age_on_income") #this model will be used !!



final solution
Thanks much.





You should return the value from the function and assign it outside the function. <<- is not a good way to do what you are trying here
– dww
Jun 30 at 23:31



return


<<-





Thanks, I edited my question to make it clear.
– Luis
Jun 30 at 23:53




2 Answers
2



This will write the lm object out to the parent frame or other environment specified by env, plot it, print it and invisibly return it. Also we make sure that the formula's environment is env which allows iv_string to refer to objects in env as well as columns in ds. (If we knew that iv_string only referred to column names in ds then we could just use fo <- paste("income ~", iv_string) as lm will accept character strings as formulas.) We use do.call(...) to ensure that the lm output shows the actual formula rather than just fo. We used the parent frame as the default for env which is more usual but if you really want the default to be the global environment replace parent.frame() with .GlobalEnv or withglobalenv().


lm


env


env


env


ds


iv_string


ds


fo <- paste("income ~", iv_string)


lm


do.call(...)


lm


fo


env


parent.frame()


.GlobalEnv


globalenv()


regress <- function(iv_string, custom_name = iv_string, env = parent.frame()) {
fo <- as.formula(paste("income ~", iv_string), env)
env[[custom_name]] <- results <- do.call("lm", list(fo, quote(ds)))
plot(results)
print(results)
invisible(results)
}

regress("age", "lm_age")



giving:


Call:
lm(formula = income ~ age, data = ds) <-- note that formula shows, not just fo

Coefficients:
(Intercept) age
695.1540 0.1699



That said, the normal style in R is not to write objects out to the parent frame or to the global environment but to return them:


regress <- function(iv_string, env = parent.frame()) {
fo <- as.formula(paste("income ~", iv_string), env)
results <- do.call("lm", list(fo, quote(ds)))
plot(results)
print(results)
invisible(results)
}

lm_age <- regress("age")





Thanks, it worked! I appreciate the additional information you provided.
– Luis
Jul 1 at 1:50



Here is a modified version of your code that I think gives you what you want.


regress <- function(iv_string, custom_name) {
regression_formula <- as.formula(paste("income ~", iv_string))
assign(custom_name, lm(regression_formula, ds), envir = .GlobalEnv)
plot(get(custom_name))
print(get(custom_name))
}

regress("age", "age_reg")



In the code above, I assign the regression results to a global variable defined by the string custom_name. For the plot and print statements, I use get to get the variable named in that string and pass it to those functions. So, in my example, it'll create the plots and print the results and a variable called age_reg will appear in the global environment and contain the regression results.


assign


custom_name


plot


print


get


age_reg





I dont think this is a good answer. There is no apparent reason OP should need to assign to global environemtn like this rather than returning the result from the function and doing the assignment outside
– dww
Jun 30 at 23:30






@dww Yup, I agree.
– Lyngbakr
Jun 30 at 23:33





Actually, this function worked and solved my problem. Thanks much.
– Luis
Jul 1 at 1:51






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

How to input without newline? (Python)

C++ thread error: no type named ‘type’ MINGW

Analog for TagView in flutter