safe way of including a function in R environment - r

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).

Related

Finding help files for moduled package functions in R

I am writing an R package which is organized into modules as per Sebastian Warnholz's modules package. Each function is organized into its own R file under, e.g., R/m1/fun.R. Each one of those files begins with roxygen code. The modules are defined in another file, R/modules.R. Here's an idea of how that file is structured:
#' Module 1
#' #name m1
#' #export
m1 <- modules::module({
expose("R/m1/fun.R")
expose("R/m1/foo.R")
})
The package checks and builds cleanly and I can call functions by issuing m1$fun() and m1$foo(). However, calling the help files don't work, no matter what I try (i.e., combinations of ? or help() with the function names, with or without the module prefix m1$.
Actually, I can't even expect the help files to be there, because after running devtools::document(), the roxygen code is not converted into man/*.Rd files. So I guess my problem is having devtools::document() search into the R subfolders. Running devtools::document("R/m1") doesn't do the trick, though.
One thing that works is putting the function scripts in the parent folder, R/, but then they lose the module scope and the help files (but not the functions themselves) can be seen at package level. Moreover, the "usage" section will state "foo(...)" instead of "m1$foo(...)", which sounds inadequate but I am not sure is currently fixable. This is my first time working with modules, so I was wondering if there's a cleaner way of organizing my functions and help files.

how to make a function available at start up in R

I have a user defined function in R
blah=function(a,b){
something with a and b
}
is it possile to put this somewhere so that I do not need to remember to load in the workspace every time I start up R? Similar to a built in function like
summary(); t.test(); max(); sd()
You can put the function into your .rprofile file.
However, be very careful with what you put there, since it essentially makes your code non-reproducible — it now depends on your .rprofile:
Let’s say you have an R code file performing some analysis, and the code uses the function blah. Executing the code on any other system will fail due to the non-existence of the blah function.
As a consequence, this file should only contain system-specific setup. Don’t define helper functions in there — or if you do, make them defined only in interactive sessions, so that you have a clear environment when R is running a non-interactive script:
if (interactive()) {
# Helper functions go here.
}
And if you find yourself using the same helper functions over and over again, bundle them into packages (or modules) and reuse those.

How to call R script from another R script, both in same package?

I'm building a package that uses two main functions. One of the functions model.R requires a special type of simulation sim.R and a way to set up the results in a table table.R
In a sharable package, how do I call both the sim.R and table.R files from within model.R? I've tried source("sim.R") and source("R/sim.R") but that call doesn't work from within the package. Any ideas?
Should I just copy and paste the codes from sim.R and table.R into the model.R script instead?
Edit:
I have all the scripts in the R directory, the DESCRIPTION and NAMESPACE files are all set. I just have multiple scripts in the R directory. ~R/ has premodel.R model.R sim.R and table.R. I need the model.R script to use both sim.R and table.R functions... located in the same directory in the package (e.g. ~R/).
To elaborate on joran's point, when you build a package you don't need to source functions.
For example, imagine I want to make a package named TEST. I will begin by generating a directory (i.e. folder) named TEST. Within TEST I will create another folder name R, in that folder I will include all R script(s) containing the different functions in the package.
At a minimum you need to also include a DESCRIPTION and NAMESPACE file. A man (for help files) and tests (for unit tests) are also nice to include.
Making a package is pretty easy. Here is a blog with a straightforward introduction: http://hilaryparker.com/2014/04/29/writing-an-r-package-from-scratch/
As others have pointed out you don't have to source R files in a package. The package loading mechanism will take care of losing the namespace and making all exported functions available. So usually you don't have to worry about any of this.
There are exceptions however. If you have multiple files with R code situations can arise where the order in which these files are processed matters. Often it doesn't matter or the default order used by R happens to be fine. If you find that there are some dependencies within your package that aren't resolved properly you may be faced with a situation where a custom processing order for the R files is required. The DESCRIPTION file offers the optional Collate field for this purpose. Simply list all your R files in the order they should be processed to satisfy the dependencies.
If all your files are in R directory, any function will be in memory after you do a package build or Load_All.
You may have issues if you have code in files that is not in a function tho.
R loads files in alphabetical order.
Usually, this is not a problem, because functions are evaluated when they are called for execution, not at loading time (id. a function can refer another function not yet defined, even in the same file).
But, if you have code outside a function in model.R, this code will be executed immediately at time of file loading, and your package build will fail usually with a
ERROR: lazy loading failed for package 'yourPackageName'
If this is the case, wrap the sparse code of model.R into a function so you can call it later, when the package has fully loaded, external library too.
If this piece of code is there for initialize some value, consider to use_data() to have R take care of load data into the environment for you.
If this piece of code is just interactive code written to test and implement the package itself, you should consider to put it elsewhere or wrap it to a function anyway.
if you really need that code to be executed at loading time or really have dependency to solve, then you must add the collate line into DESCRIPTION file, as already stated by Peter Humburg, to force R to load files order.
Roxygen2 can help you, put before your code
#' #include sim.R table.R
call roxygenize(), and collate line will be generate for you into the DESCRIPTION file.
But even doing that, external library you may depend are not yet loaded by the package, leading to failure again at build time.
In conclusion, you'd better don't leave code outside functions in a .R file if it's located inside a package.
Since you're building a package, the reason why you're having trouble accessing the other functions in your /R directory is because you need to first:
library(devtools)
document()
from within the working directory of your package. Now each function in your package should be accessible to any other function. Then, to finish up, do:
build()
install()
although it should be noted that a simple document() call will already be sufficient to solve your problem.
Make your functions global by defining them with <<- instead of <- and they will become available to any other script running in that environment.

With Roxygen and testthat, what is the proper way to make internal helper functions available to testcases called during R CMD check?

I am creating an R package, and found it useful to break parts of the logic in one file into internal helper functions, which I define in the same file. I have sort of a special case where my function decides which helper function to use via match.fun(). Since they won't be useful to other functions or people, I don't want to put these in separate files, and I don't want to export them.
All my testthat cases pass using test_dir(). When I don't export these functions, my testthat cases fail during R CMD check.
"object 'helperfunction1' of mode 'function' was not found", quote(get(as.character(FUN),
mode = "function", envir = envir)))
After looking at this post, I am able to get things to work if I explicitly export or add export entries to NAMESPACE, but again I don't want to export these.
Is there a better way to do this and doesn't require me to export? (I'll admit that the source of the issue may be match.fun() and am open to other ways of calling functions at runtime.)
From memory it wasn't clear in the documentation last time I read it (it may have changed), but it will work correctly (without having to export) so long as everything is in the right directories:
You should have a file:
tests/run-all.R
That looks like:
library(testthat)
library(myPackage)
test_package("myPackage")
Then your individual test files should be in the directory inst/tests
These will be run when you do R CMD check, otherwise you can call test_package("myPackage") in R manually.

Make a user-created function in R

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")

Resources