Assignment B-2: Making an R package

Total Points: 100

In Assignment B-1, you practiced writing a function. This time, we’ll be evaluating your ability to wrap that function (or something else!) in an R package.

Need some help? Checkout chapter 2 of the “R packages” book.

Options for what function to wrap into a package

Option 1: The function you made in Assignment B1

You can turn the function you made in Assignment B1 into a package for Assignment B2.

The work in Assignment B1 was deliberately designed to make it easier for you to convert it into a package down the line.

However, note that the deadlines for Assignments B1 and B2 are close together as they are on sequential topics, and so you are not guaranteed feedback before the B2 deadline.

Option 2: “Pre-baked” function

A documented function with tests written by the instructional team will be released to Canvas; you can choose to make that into a package for Assignment B2.

Click here for the link to download the function. (Note that the download links on that page won’t work before the morning after the Assignment B1 deadline.)

Note: If you take this option, then you may modify the documentation or the tests in any way you see fit. This “pre-baked” function is simply intended to serve as a clean starting point for this assignment that doesn’t depend on your personal success level in Assignment B1.

Option 3: Something new!

If you like, you can choose to write a new function - not used in Assignment B1 - for Assignment B2.

Setup

Go to canvas to get your invitation to create a GitHub repository for this project. You can find this in the description of Assignment B-2. The name of the repo will be the name of your package (see e.g. https://github.com/lucylgao/clusterpval), so make sure to give your repo an appropriate name! If you find yourself wanting to rename your package after you accept your invitation, see the Github Docs.

Tidy Submission (20 points)

Follow these steps once you’re ready to submit your work.

  1. Increase the version number in the DESCRIPTION file, using semantic versioning conventions. You should not have a trailing .9000.
    • Summary of convention: MAJOR.MINOR.PATCH, where initial development starts at 0.1.0, and then increment the minor version for each subsequent release
      • Only release 1.0.0 if your package is being used in production and ready for public use.
      • e.g. 0.1.0 ➡️ 0.1.1 ➡️ 0.1.X ➡️ 1.0.0 ➡️ 1.0.1 ➡️ 1.0.X ➡️ 1.1.0
    • Your release versioning is especially important if you will be choosing to develop your package further.
  2. Tag a release in your GitHub repository corresponding to your submission before the deadline, using the package version as your tag.
  3. Grab the URL corresponding to your tagged release, and submit that to canvas. Make sure the TAs and Lucy can see your repository! Either it should be public or private with TAs and Lucy added as collaborators.

Tidy submission rubric:

  • The above steps were followed.
  • Your work must be reproducible from beginning to end, error-free.
  • Your work is self-contained in a GitHub repository.
  • Code should adopt a consistent and easy-to-read style – ideally, the tidyverse style, although we’re certainly not looking for strict adherence.
  • You use proper English, spelling, and grammar, and write concisely. If there’s any uncertainty in determining a grade here, the UBC MDS writing rubric will be referred to.
  • If there’s any further uncertainty in determining a grade for this tidy submission portion, the UBC MDS mechanics rubric will be referred to.

Specific to this assignment:

  • Extra emphasis is placed on English, spelling, and grammar, because package documentation is a big part of producing an R package.
  • All files necessary for a tidy R package are present, in working form, and up-to-date. This includes, at a minimum:
    • NAMESPACE
    • DESCRIPTION
    • README.Rmd (and README.md)
    • R/ directory
    • tests/ directory
    • man/ directory
  • Your package can be installed using devtools::install_github(...), or at least, from source, without a fuss.
  • After clicking Check on your package, there are no “warnings” and no “errors” (errors are worse). “Notes” are allowed, although you should try to get rid of them, too.
  • Your R package works, is effectively designed, and has orderly components.

Exercise 1: Function(s) (20 points)

Render the documentation for all of the functions / objects in your package. You should include documentation as requested in Assignment B-1 (title, description, parameter description, and output description), but also (1) include examples under the @examples tag, and (2) be sure to include the @export tag to make functions available to users (unless you want the function to be strictly internal)

Hint: if you’re using the same function as in Assignment B-1, you should only need to put your function in an R script in the R/ folder with the specified additions to your roxygen2 documentation. Then, run document() after loading the devtools package.

What we’re looking for:

  • You followed the above instructions.
  • You should have .Rd files automatically generated in your man/ folder. Don’t touch these files.
  • Functions intended to be used by a package user are deliberately listed under “exports” in the NAMESPACE file (this should happen automatically after running document() and having @export tags with your functions).
  • Documentation for each function should load after executing ?function after loading your package.

Exercise 2: High-level documentation (20 points)

Create documentation for your R package at a high level.

  1. Fill out a README.Rmd file, being sure to include the package description, installation instructions, and demonstrated usage. Knit to README.md using devtools::build_readme(), and don’t ever touch the README.md file.
  2. In the DESCRIPTION file, update the package title and description fields (you can use the same description as you did in your README).

Hints:

  • When writing your description, imagine coming across the package on CRAN, and evaluating whether the package is relevant to you based solely on this description. It should be concise and informative.
  • Use the README boilerplate that comes with running usethis::use_readme_rmd().
  • Installation instructions: should be as simple as running, for example, install_github("org/repo", build_vignettes = TRUE, ref = "0.1.0") (don’t include build_vignettes if you have no vignettes; change the version number to your own).

What we’re looking for:

  • The above instructions were followed.
  • The documentation is clear, simple, and effective.

Exercise 3: DESCRIPTION file (20 points)

Aside from the description field in the DESCRIPTION file, ensure everything else in the DESCRIPTION file (and its related parts) are in place.

  1. Ensure a license is in place, and found in the DESCRIPTION file. We suggest usethis::use_mit_license() as an open-source-friendly license.
  2. Ensure package dependencies are listed in the DESCRIPTION file, and are effectively chosen (probably listed under “Imports”). Packages that come pre-loaded upon opening R are candidates to be listed here, too, such as the datasets and stats packages (but not the base package).
  3. Ensure all calls to functions from external packages are called using the form package::function() (only in very rare situations will you not need to use ::).
  4. Ensure all other mechanical structure of the DESCRIPTION file is in place, i.e., passes a Check.

Exercise 4: Tests (20 points)

Properly install unit tests in your package.

Hint: if you’re using the same function as in Assignment B-1, you should only need to copy and paste your test_that calls after creating a test file using usethis::use_test(...).

What we’re looking for:

  • The extent of testing should match that of Assignment B-1. So, you may not need to add any more tests if your tests were sufficient, but this is an important note if you plan on adding more functions / objects to your R package.
  • Your tests should all pass after running devtools::test().
  • You should use testthat for writing unit tests, and nothing else.
  • If you create an object in a test script, you clean up after yourself using rm('name_of_object') (not needed if the objects are created within a test_that() function.)