knitr::opts_chunk$set( collapse = TRUE, comment = "#> " ) knitr::opts_knit$set(root.dir = tempdir()) try(detach("package:mypackage", unload = TRUE), silent = TRUE) unlink(file.path(tempdir(), "my_project"), recursive = TRUE, force = TRUE)
In this document we present a basic R Suite usage. It covers:
If you are stuck feel free to contact us:
RSuite uses the following options to configure behavior:
To create a new project (called my_project
) we have to call the following function:
RSuite::prj_start(name = 'my_project')
The RSuite project is being created in folder not under git/svn control. This is the cause of warning you can see
above.
To avoid that warning messages you can pass the TRUE
for skip_rc
argument.
Every project has a special structure. Lets change working directory to the project we just created to check it.
setwd("my_project")
# it's a hack: knitr will restore current folder after chunk to the onet from opts_knit knitr::opts_knit$set(root.dir = file.path(tempdir(), "my_project"))
Lets see the contents of the project folder created:
cat(list.files(".", all.files = TRUE), sep = "\n")
In folder R
there are master scripts - these are execution scripts in our project. R Suite by default creates exemplary
script R\master.R
of following contents:
cat(readLines(con = "R/master.R"), sep = "\n")
To check if everything is working properly run the R/master.R
script:
source("R/master.R") print("master.R sourced successfully.")
You should not see any error messages.
R Suite forces the users to keep logic in packages. To create a package (called mypackage
) call the following function:
RSuite::prj_start_package(name = "mypackage", skip_rc = TRUE)
Open in any editor R/master.R
and change it to look like this:
write("\nlibrary(mypackage)\n", file = "R/master.R", append = TRUE) cat(readLines(con = "R/master.R"), sep = "\n")
You can check if your package is visible to your master script by running the master script
source('R/master.R')
You can notice an error saying there is no such package as mypackage
. This is fine because in R you have to install package to have access to it.
Adding a package to the project is not enough to use it. You have to build it. You can do this by calling the following function:
RSuite::prj_build()
Now you can check if your master script has access to the package mypackage
source('R/master.R') print("master.R sourced successfully and loaded mypackage.")
If everything worked properly you shouldn't see any error messages.
Lets add a function hello_world
to our package mypackage
. To do this you have to create a new file in folder packages/mypackage/R/hello_world.R
. Edit hello_world.R to have the following content:
writeLines(c("#' @export", "hello_world <- function(name) {", " sprintf(\"Hello %s!\", name)", "}"), con = "packages/mypackage/R/hello_world.R") cat(readLines("packages/mypackage/R/hello_world.R"), sep = "\n")
Please remember to add #' @export
. It is required to expose the function into global namespace.
Now you can change master script by adding one line to it:
write("hello_world(\"John\")\n", file = "R/master.R", append = TRUE) cat(readLines("R/master.R"), sep = "\n")
In order to check if everything works, run the master script:
source('R/master.R')
As you can see you got an error message that there is no such function as hello_world
You have to rebuild packages to have all the functionality available to master scripts. You do it with the following function call.
RSuite::prj_build()
And check if R/master.R
works:
source('R/master.R', print.eval = TRUE)
You can add dependencies to external packages in two ways:
DESCRIPTION
file in each packagelibrary
or require
in master scriptsTo add a dependency to an external package we will edit file packages\mypackage\DESCRIPTION
like below:
dcf <- read.dcf(file = "packages/mypackage/DESCRIPTION") dcf <- cbind(dcf, Depends = "data.table (>= 1.10.1)") write.dcf(dcf, file = "packages/mypackage/DESCRIPTION") cat(readLines("packages/mypackage/DESCRIPTION"), sep = "\n")
I have added data.table (>= 1.10.1)
to the Depends section. This means I declared that mypackage depends on data.table package in version 1.10.1 or newer.
Lets rebuild package to have master scripts see the changes:
RSuite::prj_build()
You can conclude that you have to install dependencies to build your package.
To install dependencies you have to call the following function:
RSuite::prj_install_deps()
From this output you can see that we use MRAN
as our package repository. Moreover R Suite detected 1 dependency to be installed.
You can check if installation succeeded by calling the following function:
RSuite::prj_build()
Lets check what happens if you run our master script
source('R/master.R', print.eval = TRUE)
The output says that data.table
was loaded. This is exactly what we wanted to be.
devtools
If you want to develop a package the cycle dev-build can take too long. This is especially important if the packages are bigger. You can use devtools to speedup this process. Lets go through such process.
Lets perform change in our mypackage
in packages/mypackage/R/hello_world.R
file to look it like this:
writeLines(c("#' @export", "hello_world <- function(name) {", " sprintf(\"Hello %s! Good to see you again.\", name)", "}"), con = "packages/mypackage/R/hello_world.R") cat(readLines("packages/mypackage/R/hello_world.R"), sep = "\n")
Now we can load the changed package for testing without rebuilding it with following command:
devtools::load_all("packages/mypackage")
Lets see how hello_world
function behaves now:
hello_world("John")
As you can see that no package rebuild was required and changed package is reloaded.
R Suite promotes good programming practices and using loggers is one of them. R Suite is based on logging
package.
Lets update R/master.R
as follows
lines <- readLines("R/master.R") lines <- c(lines[c(1:15)], "", "#library(mypackage)", "", "#hello_world(\"Jony\")", "", "loginfo(\"Master info\")", "logdebug(\"Master debug\")", "logwarn(\"Master warning\")", "logerror(\"Master error\")", "") writeLines(lines, con = "R/master.R") cat(readLines("R/master.R"), sep = "\n")
Lets check how it works
source('R/master.R')
As you can see there are logging messages. You can see that debug message is missing as by default logging level is set to present only messages on INFO
and higher levels.
To see debug logging message change project configuration file. Project configuration is in config.txt
file in project root folder. Please change the file to look like this:
writeLines("LogLevel: DEBUG", con = "config.txt") cat(readLines("config.txt"), sep = "\n")
Lets check how it works
source('R/master.R')
As you can see now debug logging message is printed.
Logs
folderLogging messages are stored in logs folder in files named with current date. You can check this by issuing a command
list.files(path = "./logs")
When you open this log in an editor you should see content similar to this
log_file <- list.files(path = "./logs", pattern = "*.log", full.names = TRUE)[1] cat(tail(readLines(log_file), n = 7), sep = "\n")
As you can see this is very similar to the output you saw in console.
R Suite allows you to use loggers in your custom packages. Lets open packages/mypackage/R/hello_world.R
and change its content to the following one
writeLines(c("#' @export", "hello_world <- function(name) {", " pkg_loginfo(\"Package info\")", " pkg_logdebug(\"Package debug\")", " pkg_logwarn(\"Package warning\")", " pkg_logerror(\"Package error\")", "", " sprintf(\"Hello %s! Good to see you again.\", name)", "}"), con = "packages/mypackage/R/hello_world.R") cat(readLines("packages/mypackage/R/hello_world.R"), sep = "\n")
Lets load changed package with devtools and see how hello_world
function behaves:
devtools::load_all("packages/mypackage") hello_world("John")
As you can see there are messages from your package. They are marked with package name mypackage
. Please also note that as you used devtools
you did not have to rebuild package to see the changes.
Lets restore log level to default value:
logging::setLevel('INFO')
RSuite allows the user to lock the project environment. It collects all dependencies' versions and stores them in a lock file to enforce exact dependency versions in the future. To lock the project environment we have to call the following function:
RSuite::prj_lock_env()
The lock file is in the 'deployment' directory under the 'env.lock' name. It is a dcf file that stores information about packages in the local environment together with their versions. A sample record from the 'env.lock' file is presented below:
cat(readLines("deployment/env.lock"), sep = "\n")
When dependencies are being installed using RSuite::prj_install_deps()
the 'env.lock' file will be used to detect whether any package will change versions. If that's the case an appropriate warning message will be displayed. The feature allows to safely deploy packages with specific dependencies' versions. It prevent errors caused by newer versions of packages which might work differently than previous ones used in the project.
To safely unlock the local project environment we use the following function:
RSuite::prj_unlock_env()
The function deletes an existing 'env.lock' file.
We can now prepare a deployment package to ship our project on a production.
First lets restore R/master.R
contents:
lines <- readLines("R/master.R") lines <- c(lines[c(1:15)], "", "library(mypackage)", "", "hello_world(\"John\")", "") writeLines(lines, con = "R/master.R") cat(readLines("R/master.R"), sep = "\n")
Now lets check that all project dependencies have been collected:
RSuite::prj_install_deps()
As you did not add any new dependencies R Suite smartly understands it and does not repeat lengthy dependencies installation phase.
Lets rebuild our custom packages:
RSuite::prj_build()
To build a deployment package you use the following function (we specify there to put the deployment package with path
argument):
RSuite::prj_zip(path = tempdir())
As project is not under version control and contains only one package R Suite chooses default version for the deployment
package to be the same as package version(0.1). Suffix x
means that it is not a real tag.
For projects under version control consistency of project source code with repository state is checked and
deployment package is versioned by source code tag (tag under Git or revision number under SVN) without x
suffix.
If project inconsistency with repository is detected (like new/uncontrolled files or source code changes) R Suite prevents building deployment package unless you enforce deployment package version explicitly:
RSuite::prj_zip(path = tempdir(), zip_ver = '1.0')
You have created file my_project_1.0x.zip
that contains all information necessary to run your solution on a production environment.
To test if the deployment package is working you can extract my_project_1.0x.zip
created in previous step in a new folder say prod
:
dir.create(path = file.path(tempdir(), "prod"), showWarnings = FALSE) unzip(zipfile = file.path(tempdir(), "my_project_1.0x.zip"), exdir = file.path(tempdir(), "prod")) cat(list.files(path = file.path(tempdir(), "prod", "my_project")), sep = "\n")
readme.txt
file contains version number the project has been tagged with:
cat(readLines(file.path(tempdir(), "prod", "my_project", "readme.txt")))
Now you can run your solution with the command
output <- system2(command = Sys.which("Rscript"), args = file.path(tempdir(), "prod", "my_project", "R", "master.R"), stdout = TRUE) cat(output, sep = "\n")
As you can see the output is exactly the same you would expect.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.