Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

Package Building: How


`DESCRIPTION`, `NAMESPACE`,
`roxygen`, and
`devtools::document` work
together
Feb 12, 2019 · 8 min read ·  R (/categories/r)


(https://twitter.com/intent/tweet?text=Package%20Building%3a%20How%20%60DESCRIPTION

%60%2c%20%60NAMESPACE%60%2c%20%60roxygen%60%2c%20and%20%60devtools

%3a%3adocument%60%20work%20together&url=%2f2019%2f02%2f12%2fpackage-building-

description-namespace%2f)


(https://www.facebook.com/sharer.php?u=%2f2019%2f02%2f12%2fpackage-building-description-

namespace%2f)


(https://www.linkedin.com/shareArticle?mini=true&url=%2f2019%2f02%2f12%2fpackage-building-

description-namespace%2f&title=Package%20Building%3a%20How%20%60DESCRIPTION%60%2c

%20%60NAMESPACE%60%2c%20%60roxygen%60%2c%20and%20%60devtools%3a%3adocument

%60%20work%20together)


(http://service.weibo.com/share/share.php?url=%2f2019%2f02%2f12%2fpackage-building-

description-namespace%2f&title=Package%20Building%3a%20How%20%60DESCRIPTION%60%2c

%20%60NAMESPACE%60%2c%20%60roxygen%60%2c%20and%20%60devtools%3a%3adocument

%60%20work%20together)


(mailto:?subject=Package%20Building%3a%20How%20%60DESCRIPTION%60%2c

%20%60NAMESPACE%60%2c%20%60roxygen%60%2c%20and%20%60devtools%3a%3adocument

1 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

%60%20work%20together&body=%2f2019%2f02%2f12%2fpackage-building-description-

As part of my new year’s resolution to learn new things about R, I’m trying to plug some
holes in my R knowledge by writing more vignettes to explain them to myself this year.

This week I �nally think I understand more about namespaces in R and why you should use
them in your R package.

Namespaces: Why Bother?


In short, we need namespaces because of the ambiguity of function names. Think of how
many packages have a filter() function! How does R know which function from which
package you’re talking about? One nightmare case is the Bioconductor exprs() method
and the rlang exprs() function. These functions do very, very different things (one of
them extracts an expression matrix from a Bioconductor ExpressionSet , and the other one
is used for quoting multiple expressions).

What happens when you call library on both of these packages? The worst case scenario
is that you mean to call one package function and R executes the other one. This is called a
namespace collision, and unfortunately it can break your code.

Enter the namespace, which allows us to be package and function speci�c. If I want to use
the function filter from dplyr , I write it as dplyr::filter . The dplyr:: part is the
namespace of the dplyr package.

DESCRIPTION : The gatekeeper for calling packages


The DESCRIPTION �le is one of the gatekeepers in your package. Ever wonder how
install.packages knows how to install the packages your package depends on? It’s
actually because of a �eld in the DESCRIPTION �le. Here’s the DESCRIPTION �le for my
burro package:

2 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

Package: burro
Type: Package
Title: Shiny App Package for setting up a data exploration session ("burro"w
into the data)
Version: 0.1.0
Authors@R: as.person(c(
"Ted Laderas <tedladeras@gmail.com> [aut, cre]",
"Jessica Minnier <minnier@ohsu.edu> [ctb]",
"Gabrielle Choonoo <choonoo@ohsu.edu> [ctb]"
))
Maintainer: Ted Laderas <ted.laderas@gmail.com>
Description: Allows the teacher to deploy a simple data exploration app for e
xploring a dataset (mostly for teaching purposes).
License: MIT LICENSE
Encoding: UTF-8
LazyData: true
Imports:
dplyr,
shinydashboard,
ggplot2,
visdat,
skimr,
naniar,
data.table,
magrittr,
glue,
usethis,
here,
viridis,
DT
Depends:
shiny
Roxygen: list(markdown = TRUE)
RoxygenNote: 6.1.0
Suggests:
testthat

Look at the Imports: �eld. You can see a list of all of the packages that burro utilizes. In
ye olde days of R, we used the Depends: �eld. Nowadays we use the Imports: �elds.
Here’s a Stack Over�ow post explaining why (https://stackover�ow.com/questions/8637993
/better-explanation-of-when-to-use-imports-depends). The main reason is that Imports:
requires the package to have a namespace.

Modifying the DESCRIPTION �le by hand is possible, but I don’t recommend it. Instead, you
can use the usethis package to modify it. For example, if I want to use dplyr in my
package I can do this in the console, while I am building it.

usethis::use_package("dplyr")

3 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

This will add dplyr to the Imports: �eld of your DESCRIPTION �le.

Addition (Thanks Hao Ye, for the suggestion): If the function is in a development version
(i.e., hosted on GitHub), you can use usethis::use_dev_package() to add it to your
DESCRIPTION �le. It will add an additional �eld called Remotes: to your package:

usethis::use_dev_package("tidyverse∕dplyr")

For more info about using remotes, check out the vignette: https://remotes.r-lib.org/articles
/dependencies.html (https://remotes.r-lib.org/articles/dependencies.html)

Using namespaces to call functions from other


packages
Now that we have speci�ed the package in our DESCRIPTION �le, we can now call any
function in dplyr by adding a dplyr:: before the function. So if we wanted to call
mutate() in our package function we can do this:

mutate_iris <- function(iris){


dplyr::mutate(iris, sepal_sum = Sepal.Length + Sepal.Width)
}

In many cases, calling a function by specifying its namespace is good practice. For one,
there are many functions called filter() : I can think of at least the ones that are in base
and dplyr . Using the namespace makes it unambiguous to both R and other developers
which filter() function you’re talking about.

How do I call functions from other packages? Using


roxygen docstrings
Ugh, I’ve already written a bunch of code and I don’t want to add the namespaces before all
of the functions from other packages! How can I avoid this?

This is where roxygen and devtools::document() come in.

roxygen docstrings are responsible for at least three things in your package: 1) producing
the documentation ( .Rd ) �les, but also: 2) specifying what package namespaces you want
to utilize, or import in your function, and 3) whether you want to export that function (i.e.,
make it accessible publicly).

How do they accomplish 2)? When you call devtools::document() to build the
documentation, they scan for multiple �elds, such as @import and @importFrom in the

4 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

roxygen doc strings. Then devtools::document() actually modi�es the NAMESPACE �le
in your package.

Using @importFrom : When you only need one function


Say you just wanted to use filter from dplyr , but didn’t want to write dplyr::filter
before all of your functions. You can just import the filter() function by including the
following docstring:

#' @importFrom dplyr filter

And then you can just use filter() like normal in your code:

#' @importFrom dplyr filter #This is where you add the @importFrom
use_filter <- function(df, cutoff=0.5) {

filter(df, value < cutoff)

Using @import : When you need a lot of functions from


a package
What if you had a lot of functions from one package, such as shiny , that you want to use?
Do you need to add an @importFrom for each of these functions? Nope. You can just use
one @import �eld for the whole package:

#` @import shiny

And then code like usual:

#` @import shiny # This is where you add the @import


shinyUI <- function() {
selectInput("")
}

Importing multiple packages: just don’t do it


(UPDATED).
Just a note to not import multiple packages using @import . As Hadley Wickham has noted,
you have no control over the development of the packages you import. Just because there
are no function collisions right now between the packages doesn’t mean that one of the

5 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

developers may add a function down the line that might collide. So, if you need to use
multiple packages, @import one package and use @importsFrom or namespaces to refer
to functions in the other packages.

Exported versus Internal functions


Remember I mentioned ‘@export’ above? Specifying in a docstring for your function exports
it. Specifying it means that ‘devtools::document()’ will add an Export directive for the
function in the NAMESPACE �le. That means you can access it using ‘::’. Going back to our
use_filter example:

#' @export #This is where you add the @export


#' @importFrom dplyr filter
use_filter <- function(df, cutoff=0.5) {

filter(df, value < cutoff)

If our package name is mypackage , then this function will be accessible if we use
library(mypackage) or mypackage::use_filter() .

Why is this important? You may write some internal functions that are useful in your
package, but they aren’t necessarily ones you want your users to use in their daily use.
@export allows you to control which functions you make publicly accessible in your
package.

For example, try typing dplyr:: in RStudio and hit the tab key. You’ll see the usual dplyr
verbs pop up. But these are only the exported functions. Now try dplyr::: and hit the tab
key. You’ll see a list of functions that pop up that’s much longer - these are all the functions,
including the internal functions.

So, if there’s a cool bit of internal code you want to use in a package, you can use ‘:::’ to
specify it. Just be aware that oftentimes, internal functions may change a lot as code gets
refactored, so code that utilizes them may be refactored.

Remember to run devtools::document()


Once you’ve written code and want to test it in your package, remember to run
devtools::document() before you reinstall your package for testing. Otherwise, the
NAMESPACE �le won’t be modi�ed, and your code won’t work.

You can also modify your Project Options for your package and check the Tools >> Project

6 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

Options >> Build Tools >> Generate Documentation with Roxygen box. Next to it, there is
also a Configure button that lets you select the option to run devtools::document()
whenever you build a package for testing.

Go forth and Package!

7 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

TL;DR:

1. Use usethis::use_package() to add packages to your DESCRIPTION �le (while in


the console) after you’ve created your package skeleton using use_package() .
2. Use namespaces (such as mypackage::usefilter() ) to refer to external functions
where possible to avoid collisions in function names when you are writing code.
3. Use @imports and @importsFrom judiciously in your roxygen documentation for a
function if you need to use many extenral package functions within a function. Use
only 1 @import statement in a function, use namespaces/ @importsFrom for the
other packages.
4. Expose functions you want to be made public using @export in your roxygen
documentation.
5. Remember to run devtools::document() in the console after you modify/add these
�elds to the roxygen documentation when you build for testing, or set it up in Tools >>
Project Options.

I hope this helps you to understand exactly the relationships between all of the components
that are responsible for accessing namespaces in your package. I was confused about this
for years, so writing this has helped me understand these relationships.

Further Reading
If you want to know how R searches for a function across its environments and why
namespaces are a good thing, this is an excellent writeup:
http://blog.obeautifulcode.com/R/How-R-Searches-And-Finds-Stuff/
(http://blog.obeautifulcode.com/R/How-R-Searches-And-Finds-Stuff/)
More about the usethis work�ow: https://www.hvitfeldt.me/blog/usethis-work�ow-
for-package-development/ (https://www.hvitfeldt.me/blog/usethis-work�ow-for-
package-development/)
More about the DESCRIPTION �le: http://r-pkgs.had.co.nz/description.html (http://r-
pkgs.had.co.nz/description.html)
More about namespaces: http://r-pkgs.had.co.nz/namespace.html (http://r-
pkgs.had.co.nz/namespace.html)
More about roxygen: http://r-pkgs.had.co.nz/man.html#roxygen-comments (http://r-
pkgs.had.co.nz/man.html#roxygen-comments)
An alternative work�ow to modify the DESCRIPTION �le: You can use
attachment::att_to_description() to scan code and add packages to the �le
after coding (thanks, Sébastien!).

Acknowledgements

8 of 9 11/21/20, 11:43 PM
Package Building: How `DESCRIPTION`, `NAMESPAC... https://laderast.github.io/2019/02/12/package-building...

Thanks to Hao Ye, Sébastien Rochette, Michael Chirico, Tim Hesterberg, and Hadley
Wickham for their comments and questions. I’ve incorporated your suggestions.

Note
I want this to be clear and correct. Please email me (mailto:laderast@ohsu.edu) if there are
any mistakes I’ve made.

R (/tags/r) package (/tags/package) development (/tags/development)

devtools (/tags/devtools)

Related
Things we learned teaching clinical data wrangling (/2018/10/15/clinical-data-
wrangling/)
A gRadual Introduction to Shiny (/2018/01/24/gradual-introduction-to-shiny/)
Clinical Data Wrangling Workshop (/teaching/clinical_wrangling/)
Introduction to igraph (/teaching/igraph_tutorial/)
Data Analytics (/teaching/data_analytics/)

© 2018 · Powered by the Academic theme (https://sourcethemes.com/academic/) for Hugo (https://gohugo.io).


9 of 9 11/21/20, 11:43 PM

You might also like