I would like source() to only find and load functions within a .R file.
For example, in the file Analysis.R:
print.hw <- function() {
print("hello world")
}
x <- 1 + 2
...
When I source("Analysis.R"), it will create the function print.hw but also assign x, which I do not want.
Anyone have any ideas? The best I could find was this question:
Source only part of a file
This works without using regex. It's also probably less computationally efficient than regex solutions. It creates a new environment, sources the entire file, then returns only the functions back to the global environment.
SourceFunctions<-function(file) {
MyEnv<-new.env()
source(file=file,local=MyEnv)
list2env(Filter(f=is.function,x=as.list(MyEnv)),
envir=parent.env(environment()))
}
I think its a good practice to separate test code before the end of source files (as we usually do in Python) and then invoke them with external scripts or packages (like testthat). Hadley's dplyr may give you a reference.
Related
I have wrote a bunch of functions for my project for users to invoke interactively.
Now I'd like to have them safely included in the session.
I want to avoid a scenario where user types rm(list=ls()) and erases my functions from memory.
Initially I tried to save function to another environment and attach that environment to search path but along the way I changed something and R is not longer able to find my function.
My code is split among multiple files but snippet below ilustrates how are things organised, normally user will run app.R because it contains refernces to other files, configurations etc.:
./funs.R
id.mapping.env <- new.env(parent = emptyenv())
attach(id.mapping.env)
id.mapping.env$test_function<- function() {
print("It works")
}
./app.R
source("./funs.R")
test_function
If I run app.R I get error:
Error: could not find function "test_function"
Why won't R find my function? Do I have to resort to writing my own package to ensure all of my functions can be found?
I am not familiar with writing packages, if this is needed could you give me a tiny demo/tutorial(which I am googling right now).
Following your recommendations (or trying to do it, at least), I have tried some options, but the problem remains, so there must be something I am missing.
I have included a more complete code
setwd("C:/naapp")
#' #import utils
#' #import devtools
I have tried with and without using suppressForeignCheck
if(getRversion() >= "2.15.1"){
utils::globalVariables(c("eleven"))
utils::suppressForeignCheck(c("eleven"))
}
myFunctionSum <- function(X){print(X+eleven)}
myFunctionMul <- function(X){print(X*eleven)}
myFunction11 <- function(X){
assign("eleven",11,envir=environment(myFunctionMul))
}
maybe I should use a particular environment?
package.skeleton(name = "myPack11", list=ls(),
path = "C:/naapp", force = TRUE,
code_files = character())
I remove the "man" directory from the directory myPack11,
otherwise I would get an error because the help files are empty.
I add the imports utils, and devtools to the descrption
Then I run check
devtools::check("myPack11")
And I still get this note
#checking R code for possible problems ... NOTE
#myFunctionMul: no visible binding for global variable 'eleven'
#myFunctionSum: no visible binding for global variable 'eleven'
#Undefined global functions or variables:eleven
I have tried also to make an enviroment, combining Tomas Kalibera's suggetion and an example I found in the Internet.
myEnvir <- new.env()
myEnvir$eleven <- 11
etc
In this case, I get the same note, but with "myEnvir", instead of "eleven"
First version of the question
I trying to use "globalVariables" from the package utils. I am building an interface in R and I am planning to submit to CRAN. This is my first time, so, sorry if the question is very basic.I have read the help and I have tried to find examples, but I still don't know how to use it.
I have made a little silly example to ilustrate my question, which is:
Where do I have to place this line exactly?:
if(getRversion() >= "2.15.1"){utils::globalVariables("eleven")}
My example has three functions. myFunction11 creates the global variable "eleven" and the other two functions manipulate it. In my real code, I cannot use arguments in the functions that are called by means of a button. Consider that this is just a silly example to learn how to use globalVariables (to avoid binding notes).
myFunction11 <- function(){
assign("eleven",11,envir=environment(myFunctionSum))
}
myFunctionSum <- function(X){
print(X+eleven)
}
myFunctionMul <- function(X){
print(X*eleven)
}
Thank you in advance
I thought that the file globals.R would be automatically generated when using globalsVariables. The problem was that I needed to create the package skeleton, then create the file globals.R, add it to the R directory in the package and check the package.
So, I needed to place this in a different file:
#' #import utils
utils::globalVariables(c("eleven"))
and save it
The documentation clearly says:
## In the same source file (to remind you that you did it) add:
if(getRversion() >= "2.15.1") utils::globalVariables(c(".obj1", "obj2"))
so put it in the same source file as your functions. It can go in any of your R source files, but the comment above recommends you put it close to your code. Looking at a bunch of github packages reveals another common pattern is to have a globals.R function with it in, but this is probably a bad idea. If you later remove the global from your package but neglect to update globals.R you could mask a problem. Putting it right close to the functions that use it will hopefully remind you when you edit those functions.
Make sure you put it outside any function definitions in the file, or it won't get seen.
You cannot modify bindings in a package namespace once the package is loaded (and namespace sealed, and bindings locked). The check tool helps you to spot violations of this restriction, so you find out about the problem when checking the package rather than while running it. globalVariables is just a call to silence check when looking for these violations, which is undesirable in almost all cases. If you really need mutable state in a package, you can create a new environment (using new.env) and bind it to an (unexported) "global" variable in your namespace. This binding will be locked, but this is ok, because in R you can change an environment in place (add/remove elements, effectively modifying the elements).
The best situation is however when you can keep all mutable state in user objects (passed in as arguments into functions, and their modified versions returned as output values of functions).
I would like source() to only find and load functions within a .R file.
For example, in the file Analysis.R:
print.hw <- function() {
print("hello world")
}
x <- 1 + 2
...
When I source("Analysis.R"), it will create the function print.hw but also assign x, which I do not want.
Anyone have any ideas? The best I could find was this question:
Source only part of a file
This works without using regex. It's also probably less computationally efficient than regex solutions. It creates a new environment, sources the entire file, then returns only the functions back to the global environment.
SourceFunctions<-function(file) {
MyEnv<-new.env()
source(file=file,local=MyEnv)
list2env(Filter(f=is.function,x=as.list(MyEnv)),
envir=parent.env(environment()))
}
I think its a good practice to separate test code before the end of source files (as we usually do in Python) and then invoke them with external scripts or packages (like testthat). Hadley's dplyr may give you a reference.
I have lots of .r scripts that I want to source all. I have written a function like the one below to source.
sourcer=function(){
source("wil.r")
source("k.r")
source("l.r")
}
Please can any one tell me how to get this codes activated and how to call each one any time I want to use it?
In addition to the answer by #user2885462, if the amount of R code you need to source becomes bigger, you might want to wrap the code into an R package. This provides a convenient way of loading the code, and allows you to add tests, documentation, etc. Reading the official package writing tutorial is a good place to start for that.
For an individual project, I like to have all (or most) of my R functions in separate .r files, all in the same folder: e.g., AllFunctions
Then at the beginning of my main code I run the following line of code, which sources all .r (and other extensions if they exist - which they usually don't) in the AllFunctions folder:
for (nm in list.files("AllFunctions", pattern = ".[RrSsQq]$")) source(file.path("AllFunctions", nm))
I'm sorry if this has been asked before but I can't find the answer.
Let's say I write a small function in R
add2<-function(a){
return(a+2)
}
I save it as add2.R in my home directory (or any directory). How do I get R to find it??
> add2(4)
Error: could not find function "add2"
I know I can open up the script, copy/paste it in the console, run it, and then it works. But how do I get it built-in so if I open and close R, it still runs without me copying and pasting it in?
One lightweight option:
dump("add2", file="myFunction.R")
## Then in a subsequent R session
source("myFunction.R")
An alternative:
save("add2", file="myFunction.Rdata")
## Then just double click on "myFunction.Rdata" to open
## an R session with add2() already in it
## You can also import the function to any other R session with
load("myFunction.Rdata")
Until you're ready to package up functions into your own private package, storing them in well organized, source()-ready text files (as in the 1st example above) is probably the best strategy. See this highly up-voted SO question for some examples of how experienced useRs put this approach into practice.
Before invoking the function (e.g. at the beginning of the script), you should source the file containing your user defined function/s, i.e. :
source("add2.R") # this executes add2.R script loading add2 function
Basically, source function executes the code included in the script passed as argument. So if the file contains only functions definitions it loads the function in memory for future use.
If you want to start it automatically, then you have to set-up startup script and then use one of the methods outlined in answers above.
/Library/Frameworks/R.framework/Versions/2.15/Resources/etc/
is(for mac) the location of Rprofile.site, which must be edited adequately.
My version of it is:
.First <- function()
{
dir='~/Desktop/Infobase/R/0_init/0_init.R'
if(file.exists(dir))
{
source(dir, chdir = TRUE)
} else {cat("startup file is not found at:",dir)}
cat("\nWelcome at", date(), "\n")
}
.Last <- function()
{
cat("\nGoodbye at ", date(), "\n")
}
Note, that after you have sourced 1 R script, you do not need to enter this file anymore. Just do all you need from the file you sourced. In my case file "0_init.R" contains no functions, it just contains loading of other scripts. Well, you've got the idea.
Also, if you are doing this I recommend you to store them in new environment. Actual environments are not really suitable for your own functions(They are better implemented if you have a package developed, otherwise you lose a lot of control).
use "attach", "detach", "search", etc....
attach(FUN,name="af2tr")