Being involved in creating R packages, I thought it would be helpful to document the procedure for quick reference, after having recently posted an answer on Stack Overflow for the same.
Before proceeding to the steps to be followed, there are some pre-requisites, which include:
- an IDE
- RStudio
- a few packages
- devtools (for most of the functions involved in the creation of a package)
- roxygen2 (for roxygen-based documentation)
In case you don’t have the aforementioned packages, you can install them with the commandinstall.packages("packageName")
.
Steps:
- Import devtools in RStudio by using
library(devtools)
. (It’s a package that makes creation and development of R packages easier with its toolset) - Create your package by using:
create_package("~/directory/packageName")
for a custom directory.
or
create_package("packageName")
if you want your package to be created in the current workspace directory.
- Soon after you execute this function, it will open a new RStudio session. You will observe that in the old session some lines will be auto-generated, basically telling R to create a new package with required components in the specified directory.
After this, we are done with this old instance of RStudio. We will continue our work on the new RStudio session window.
By far the package creation part is already over (yes, that simple!) however, a package isn’t directly functional just by its creation, and the fact that you need to include a function in it requires some additional aspects of a package such as its documentation (where the function’s title, parameters, return types, examples, etc. are prevalent, and are mentioned appropriately in your source code using @param
, @return
, @examples
, etc. which conform to the roxygen-based style of documentation) and R CMD checks to get it working.
I’ll get to that in the subsequent steps, but just in case you want to verify that your package is created, you can look at:
- The top right corner of the new RStudio session, where you can see the package name that you created.
- The console, where you will see that R created a new directory/folder in the path that we specified in
create_package()
function. -
The files panel of your RStudio session, where you’ll notice a bunch of new files and directories within your directory.
- Now we can drop our functions in a script file, for which we will need to create the script first, which can be done using:
use_r("function_name")
A new R script will pop up in your working session, ready to be used. Now go ahead and write your function(s) in it!
- After you’re done, you need to load the function(s) you have written for your package. This is accomplished by using the
devtools::load_all()
function.
When you execute load_all()
in the console, you’ll get to know that the functions have been loaded into your package when you’ll see ‘Loading packageName’ displayed in the console. You can try calling your functions after that in the console to verify that they work as a part of the package.
- Now that your function has been written and loaded into your package, it is time to move on to checks. It is a good practice to check the whole package as we make changes to our package. The function
devtools::check()
offers an easy way to do this.
Try executing check()
in the console. It should and will go through several routines, checking your package for warnings/errors and providing details for the same as messages on the screen. The R CMD check results at the end will contain the vital logs for you to see what errors and warnings you got along with their frequency.
If the functions in your package are written well (with additional package dependencies taken care of) or are simple enough to not have any errors/complicacies, it will give you two warnings upon execution of check
:
The first warning will be regarding the license that your package uses, which is not specified for a new package.
The second should be the one for documentation, warning us that our code is not documented.
To resolve the first issue (which is regarding the license), use the use_mit_license("license_holder_name")
command (or any other license which suits your package - but then for private use as you mentioned, it doesn’t matter what you specify if you’re the only one to use it or if it is not to be distributed) with your name as in place of license_holder_name
or anything which suits a license name. This will add the license field in the .DESCRIPTION
file (in your files panel) and create an additional file that adds the license information.
Also, you’ll need to edit the .DESCRIPTION
file, which has self-explanatory fields to fill in or edit. Here is an example of how you can have it be:
Package: packageName
Title: Give a brief title
Version: 1.0.0.0
Authors@R:
person(given = "Your_first_name",
family = "Your_surname/family_name",
role = c("package_creator", "author"),
email = "youremailaddress@gmail.com",
comment = c(ORCID = "YOUR-ORCID-ID"))
Description: Give a brief description considering your package functionality.
License: will be updated with whatever license you provide, the above step will take care of this line.
Encoding: UTF-8
LazyData: true
To resolve the documentation warning, you’ll need to document your function using roxygen. Here’s an example:
#' @param a parameter one
#' @param b parameter two
#' @return sum of a and b
#' @export
#'
#' @examples
#' yourfunction(1,2)
yourfunction <- function(a,b)
{
sum <- a+b
return(sum)
}
Follow the roxygen syntax and add attributes as you desire - some may be optional such as @title for specifying the title, while others such as @import
are required (a must) if you’re importing functions from other packages other than the ones present in base R.
After you’re done documenting your function(s) using the Roxygen-based skeleton, we can tell our package that we have documented our functions by running devtools::document()
. After you execute the document()
command, perform check()
again to see if you get any warnings. If you don’t, then that means you’re good to go.
Lastly, you’ll need to install the package, for it to be accessible by R. Simply use the install()
command (yes, the same one you used at the beginning, except you don’t need to specify the package here like install("packageName")
since you are currently working in an instance where the package is loaded (with the namespace and environment being aligned) and is ready to be deployed/installed) and you’ll see after a few lines of installation a statement like “Done (packageName)”, which indicates the installation of our package is complete.
Now you can try your function by first importing the package using library("packageName")
and then calling your desired function from the package. That’s it!
Anirban | 01/24/2020 |