Last updated: 2019-04-10

Checks: 6 0

Knit directory: rrresearch/

This reproducible R Markdown analysis was created with workflowr (version 1.2.0). The Report tab describes the reproducibility checks that were applied when the results were created. The Past versions tab lists the development history.


Great! Since the R Markdown file has been committed to the Git repository, you know the exact version of the code that produced these results.

Great job! The global environment was empty. Objects defined in the global environment can affect the analysis in your R Markdown file in unknown ways. For reproduciblity it’s best to always run the code in an empty environment.

The command set.seed(20190216) was run prior to running the code in the R Markdown file. Setting a seed ensures that any results that rely on randomness, e.g. subsampling or permutations, are reproducible.

Great job! Recording the operating system, R version, and package versions is critical for reproducibility.

Nice! There were no cached chunks for this analysis, so you can be confident that you successfully produced the results during this run.

Great! You are using Git for version control. Tracking code development and connecting the code version to the results is critical for reproducibility. The version displayed above was the version of the Git repository at the time these results were generated.

Note that you need to be careful to ensure that all relevant files for the analysis have been committed to Git prior to generating the results (you can use wflow_publish or wflow_git_commit). workflowr only checks the R Markdown file, but you know if there are other scripts or data files that it depends on. Below is the status of the Git repository when the results were generated:


Ignored files:
    Ignored:    .DS_Store
    Ignored:    .Rhistory
    Ignored:    .Rproj.user/
    Ignored:    analysis/.DS_Store
    Ignored:    analysis/assets/
    Ignored:    assets/
    Ignored:    data/metadata/
    Ignored:    data/raw/
    Ignored:    demos/demo-rmd-0_files/
    Ignored:    demos/demo-rmd-1_files/
    Ignored:    demos/demo-rmd_files/
    Ignored:    docs/.DS_Store
    Ignored:    docs/assets/.DS_Store
    Ignored:    docs/assets/img/.DS_Store
    Ignored:    docs/demo-rmd-0_files/
    Ignored:    docs/demo-rmd-1_files/
    Ignored:    docs/demo-rmd-2_files/
    Ignored:    docs/demo-rmd-3_files/
    Ignored:    docs/demo-rmd_files/
    Ignored:    docs/figure/10_compendium.Rmd/
    Ignored:    docs/index-demo-pre_files/
    Ignored:    figure/
    Ignored:    install.R
    Ignored:    rmd/
    Ignored:    slides/libs/

Unstaged changes:
    Modified:   analysis/_site.yml

Note that any generated files, e.g. HTML, png, CSS, etc., are not included in this status report because it is ok for generated content to have uncommitted changes.


These are the previous versions of the R Markdown and HTML files. If you’ve configured a remote Git repository (see ?wflow_git_remote), click on the hyperlinks in the table below to view them.

File Version Author Date Message
html a3cfb2c annakrystalli 2019-04-10 update navmenu
Rmd ed954cd annakrystalli 2019-04-10 rename and add pkg functionality

R Package Structure

Used to share functionality with the R community

  • Useful conventions

  • Useful software development tools

  • Easy publishing through GitHub


R Package conventions:

  • metadata: in the DESCRIPTION file

  • functions in .R scripts in the R/ folder

  • tests in the tests/ folder

  • Documentation:
    • functions using Roxygen notation
    • workflows using .Rmd documents in the vignettes/ folder

Software Engineering approach

Following conventions allows us to make use of automated tools for:

  • Checking and testing code

  • Producing documentation for code and workflows

  • Publishing, distributing and citing code


Anatomy of an R package

Let’s use pkgreviewr, a package I authored to help automate some aspects of the rOpenSci review process, as an example to examine some elements of what makes a package:

DESCRIPTION file

Capture metadata around the package - Functionality description - Creators - License

Package: pkgreviewr
Type: Package
Title: rOpenSci package review project template
Version: 0.1.1
Authors@R: c(person("Anna", "Krystalli", email = "annakrystalli@googlemail.com",
                  role = c("aut", "cre")),
             person("Maëlle", "Salmon", email = "maelle.salmon@yahoo.se", role = "aut"))
Description: Creates files and collects materials necessary to complete an rOpenSci package review. 
    Review files are prepopulated with review package specific metadata. Review package source code is
    also cloned for local testing and inspection.
License: GPL-3 + file LICENSE
URL: https://github.com/ropenscilabs/pkgreviewr
BugReports: https://github.com/ropenscilabs/pkgreviewr/issues
Encoding: UTF-8
LazyData: true
Imports:
    devtools,
    git2r (>= 0.23.0),
    usethis (>= 1.2.0),
    here,
    reprex,
    gh,
    base64enc,
    whoami,
    magrittr,
    covr,
    goodpractice,
    assertthat,
    httr,
    rstudioapi,
    clipr,
    clisymbols,
    crayon,
    dplyr,
    glue,
    fs,
    urltools,
    shiny
Suggests: 
    testthat,
    mockery,
    knitr,
    rmarkdown
RoxygenNote: 6.1.1
Remotes: 
    ropensci/git2r
VignetteBuilder: knitr
Roxygen: list(markdown = TRUE)

Dependency management

It’s the job of the DESCRIPTION to list the packages that your package needs to work.

Imports:
    devtools,
    git2r (>= 0.23.0),
    usethis (>= 1.2.0),
    here,
    reprex,
    gh,
    base64enc,
    whoami,
    magrittr,
    covr,
    goodpractice,
    assertthat,
    httr,
    rstudioapi,
    clipr,
    clisymbols,
    crayon,
    dplyr,
    glue,
    fs,
    urltools,
    shiny

Imports are necessary dependencies for the functions in your package to work

Suggests: 
    testthat,
    mockery,
    knitr,
    rmarkdown

Suggests are dependencies that are not necessary for the functions in your package but might be neccessary to run all the vignettes or tests in your package


R/

  • Keep all functions in R scripts in R/ folder
.
├── github.R
├── pkgreview.R
├── pkgreviewr-package.R
├── render-templates.R
├── rmd-utils.R
├── style.R
└── utils.R

0 directories, 7 files

example function script

Create a new function .R file in the R/ folder

R
└── add.R

0 directories, 1 files

tests/

Tests provide confidence in what the code is doing.

Contents of pkgreviewr test folder

.
├── testthat
│   ├── setup.R
│   ├── test-create-pkgreview.R
│   ├── test-gh-calls.R
│   ├── test-render-templates.R
│   └── test-setup.R
└── testthat.R

1 directory, 6 files

Example test

tests
├── testthat
│   ├── test-add.R
└── testthat.R

The R package structure can help with providing a logical organisation of files, by providing a set of standard locations for certain types of files.

To work with packages in RStudio we use the Build pane, which includes a variety of tools for building, documenting and testing packages. This will appear if Rstudio recognises the project as an R package.

Create your first package

Let’s go ahead and create our first package! We do that as we would any project, but this time we select R package instead of New Project. Call your package mypackage.

File > New Project… > New Directory > R package > mypackage

Your new project should have the following structure. The build pane should also be visible.

.
├── DESCRIPTION
├── NAMESPACE
├── R
│   └── hello.R
├── man
│   └── hello.Rd
└── mypackage.Rproj

2 directories, 5 files

Functions in the R/ dir

Let’s inspect hello.R

it contains a function that takes now arguments and prints hello world to the console when called. The comments above are just that, comments and don’t serve any functional purpose.

Install package.

You can install a package locally from it’s source code with function install()

You can now load it like any other package…

And use your function!

[1] "Hello, world!"

Roxygen documentation

Roxygen2 allows you to write specially-structured comments preceeding each function definition to document:

  • the inputs and outputs
  • a description of what it does
  • an example of how to use it

These are processed automatically to produce .Rd help files for your functions and control which functions are exported to the package NAMESPACE.

Let’s document our example function. First, clear the demo comments above the function and all contents of the exampleNAMESPACE. Also delete the file in the man folder.

Insert Roxygen skeleton

You can insert a Roxygen skeleton by placing the curson with a function and clicking:

Code > Insert Roxygen Skeleton

Roxygen basics

  • roxygen notation indicated by beginning line with #'.

  • First line will be the title for the function.

  • After title, include a blank #' line and then write a longer description.

  • @param argument_name description of the argument.

  • @return description of what the function returns.

  • @export tells Roxygen2 to add this function to the NAMESPACE file, so that it will be accessible to users.
  • @examples allows to include example of how to use a function

Create documentation

Use function devtools::document() to create documentation. This re-creates a hello.Rd helpfile in the man/ folder and populates the NAMESPACE with our functions

Click Install and Restart to re-install the package and make the documentation available.

You can configure your build tools in the Global Options to automatically build documentation every time you Install & Rebuild

Personalise function

Let’s go a step further and customise our function so that the greeting is from ourselves!

Add some fun!

Programming is most useful for having fun. So let’s make our function extra fun!

We’ll use package cowsay

which has a single function say, which does this…

Colors cannot be applied in this environment :( Try using a terminal or RStudio.

    
 -------------- 
Say whaaaaaat? 
 --------------
    \
      \
        \
              /""-._
              .       '-,
               :          '',
                ;      *     '.
                 ' *         () '.
                   \               \
                    \      _.---.._ '.
                    :  .' _.--''-''  \ ,'
        .._           '/.'             . ;
        ; `-.          ,                \'
         ;   `,         ;              ._\
          ;    \     _,-'                ''--._
          :    \_,-'                          '-._
          \ ,-'                       .          '-._
          .'         __.-'';            \...,__       '.
        .'      _,-'        \              \   ''--.,__  '\
        /    _,--' ;         \              ;           \^.}
        ;_,-' )     \  )\      )            ;
             /       \/  \_.,-'             ;
            /                              ;
         ,-'  _,-'''-.    ,-.,            ;      PFA
      ,-' _.-'        \  /    |/'-._...--'
     :--``             )/
  '
  

😜

So let’s create a function that randomly chooses one of the animals available in cowsay to deliver the greeting, and also allow the user to customise who the recipient of the greeting is

Document, Install and restart to load our changes

Colors cannot be applied in this environment :( Try using a terminal or RStudio.


 ----- 
Hello y'all from Anna! 
 ------ 
    \   
     \
    .ハ,,ハ
    ( ゚ω゚)
    |つ  つ
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    |    |
    U "  U
        [BoingBoing]
    

Check package integrity

An important part of the package development process is R CMD check. R CMD check automatically checks your code and can automatically detects many common problems that we’d otherwise discover the hard way.

To check our package, we can:

  • use devtools::check()

  • press Ctrl/Cmd + Shift + E

  • click on the ✅Check tab in the Build panel.

This:

  • Ensures that the documentation is up-to-date by running devtools::document().

  • Bundles the package before checking it.

More info on checks here.


Both these run R CMD check which return three types of messages:

  • ERRORs: Severe problems that you should fix regardless of whether or not you’re submitting to CRAN.

  • WARNINGs: Likely problems that you must fix if you’re planning to submit to CRAN (and a good idea to look into even if you’re not).

  • NOTEs: Mild problems. If you are submitting to CRAN, you should strive to eliminate all NOTEs, even if they are false positives.

Let’s Check our package:

Click on the Check button (📋 ✅)

   
── R CMD check results ──────────────────────────────────── mypackage 0.1.0 ────
Duration: 8.4s

❯ checking DESCRIPTION meta-information ... WARNING
  Non-standard license specification:
    What license is it under?
  Standardizable: FALSE

❯ checking dependencies in R code ... WARNING
  '::' or ':::' import not declared from: ‘cowsay’

0 errors ✔ | 2 warnings ✖ | 0 notes ✔
Error: R CMD check found WARNINGs
Execution halted

Exited with status 1.

Aha, so our checks have thrown up some warnings! First, it’s telling us we haven’t added a LICENSE. It’s also telling us that we have a dependency (import) from package cowsay which we haven’t documented in the DESCRIPTION file. usethis to the rescue!

Add dependencies

Add cowsay as a dependency.

✔ Setting active project to '/Users/Anna/Desktop/mypackage'
✔ Adding 'cowsay' to Imports field in DESCRIPTION
● Refer to functions with `cowsay::fun()`

Add License

Check again…All should be good!

── R CMD check results ──────────────────────────────────── mypackage 0.1.0 ────
Duration: 9.3s

0 errors ✔ | 0 warnings ✔ | 0 notes ✔

R CMD check succeeded

Add Test

Testing is a vital part of package development. It ensures that our code does what you want it to do.

Once you’re set up with a testing framework, the workflow is simple:

  1. Modify your code or tests.

  2. Test your package with Ctrl/Cmd + Shift + T or devtools::test().

  3. Repeat until all tests pass.

create test file

To create a new test file (and the testing framework if required), use function usethis::use_test(). It’s good practice to name the test files after the .R files containing the functions being tested.

This just created the following folders and files

tests
├── testthat
│   └── test-hello.R
└── testthat.R

1 directory, 2 files

It also added testthat to the suggested packages in the DESCRIPTION file.

Suggests: 
    testthat

That’s because you don’t need test that to run the functions in mypackage, but you do if you want to run the tests.

When the tests are run (either through running devtools::test(), clicking on More > Test Package in the Build panel or Cmd/Ctrl + Shift + T), the code in each test script in directory testthat is run.

test-hello.R

Let’s load the library so we can explore the testthat testing framework

If the test doesn’t pass it throws an error

Error: Test failed: 'multiplication works'
* 2 * 2 not equal to 5.
1/1 mismatches
[1] 4 - 5 == -1

Write test

Let’s write a simple test to check that we are getting an expected output type. The first thing to note, looking at the say() documentation is that it takes an argument type which allows us to specify the output we want. It defaults message which means the output of the function is returned as a message.

We can therefore use testthat::expect_message()

Now let’s test our package

Success!

==> devtools::test()

Loading mypackage
Testing mypackage
✔ | OK F W S | Context
✔ |  1       | test-hello

══ Results ════════════════════════════════════════════════════════
OK:       1
Failed:   0
Warnings: 0
Skipped:  0

Complete package metadata

Let’s head to the DESCRIPTION file and complete the details.

Authors

First let’s complete the authors. Remove the current author and maintainer lines and replace it with the following line:

Authors@R: person("First", "Last", email = "first.last@example.com", role = c("aut", "cre"))

completed with your own details

Add a title and description

Complete the title and description fields with appropriate details. If you want to form a paragraph of text, make sure do indent the hanging lines by 4 spaces (one tab). And make sure that your Description field ends in a full-stop.

Add a date

Use today’s date in ISO format, ie 2019-04-10. This will populate a citation entry for us.

Completed DESCRIPTION

The complete DESCRIPTION file should look something like this:

Package: mypackage
Type: Package
Title: Customised greetings from me!
Version: 0.1.0
Authors@R: person("Anna", "Krystalli", 
  email = "annakrystalli@googlemail.com", 
  role = c("aut", "cre"))
Description: Prints a customised greeting from myself, 
    delivered by a friend.
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
RoxygenNote: 6.1.1
Imports: 
    cowsay
Suggests: 
    testthat
Date: 2019-04-10

Check your package. If all is good, document, install and restart!

Now, check you’re package’s citation:


To cite package 'mypackage' in publications use:

  Anna Krystalli (2019). mypackage: Customised greetings from me!.
  R package version 0.1.0.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {mypackage: Customised greetings from me!},
    author = {Anna Krystalli},
    year = {2019},
    note = {R package version 0.1.0},
  }

Create README

The final document you will need for your package is a README.

✔ Writing 'README.Rmd'
✔ Adding '^README\\.Rmd$' to '.Rbuildignore'
● Modify 'README.Rmd'
✔ Writing '.git/hooks/pre-commit'

Because it’s an .Rmd but GitHub can only display an md document as it’s landing page, this is a special .Rmd that renders to a markdown document rather than html. The function adds a check to .git to ensure you commit an up to date version on the md when you commit changes to the .Rmd.

Complete the README, including an example.

Commit and push to GitHub

Now you have everything you need to share your package on GitHub.

Anyone will be able to install it using, eg:

Check out my complete example here

R version 3.5.2 (2018-12-20)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.3

Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] testthat_2.0.1

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.1        knitr_1.22        whisker_0.3-2    
 [4] magrittr_1.5      workflowr_1.2.0   R6_2.4.0         
 [7] rlang_0.3.4       stringr_1.4.0     tools_3.5.2      
[10] xfun_0.5          cowsay_0.7.0      git2r_0.25.2.9000
[13] htmltools_0.3.6   fortunes_1.5-4    yaml_2.2.0       
[16] rprojroot_1.3-2   digest_0.6.18     assertthat_0.2.0 
[19] crayon_1.3.4      purrr_0.3.2       fs_1.2.7         
[22] rmsfact_0.0.3     glue_1.3.1        evaluate_0.13    
[25] rmarkdown_1.12    emo_0.0.0.9000    stringi_1.3.1    
[28] compiler_3.5.2    backports_1.1.3   lubridate_1.7.4