============================================================================================================
About: The up-to-date document is available at https://rpubs.com/sherloconan/802481
Beginner: watch R-Ladies’ YouTube video, 90 minutes.
Intermediate: practise Siegert, Gabry, Lysy, and Goodrich’s vignette, 30 minutes.
Advanced: watch John Muschelli’s YouTube videos, 80 minutes.
Comprehensive: check Sahir Rai Bhatnagar’s summary from time to time.
devtools::has_devel()
available::available("PACKAGENAME", browse = FALSE) #See if a package name is available and appropriate
Create a regular R package by usethis::create_package(“~/PATH/PACKAGENAME”).
Create a Stan-based R package by
rstantools::rstan_create_package(path="~/PATH/PACKAGENAME")
usethis::use_gpl_license(version = 3)
file.remove('Read-and-delete-me')
Authors@R:
c(person(given = "Zhengxiao",
family = "Wei",
role = c("aut", "cre"),
email = "USER1@uvic.ca",
comment = c(ORCID = "0000-0003-1866-2320")),
person(given = "Farouk S.",
family = "Nathoo",
role = c("aut"),
email = "USER2@uvic.ca",
comment = c(ORCID = "0000-0002-2569-3507")),
person(given = "Michael E. J.",
family = "Masson",
role = c("aut"),
email = "USER3@uvic.ca",
comment = c(ORCID = "0000-0002-5430-6078")))
Also, remember to edit the PACKAGENAME-package.R file in “~/PATH/PACKAGENAME/R”.
2023 update:
Updated package doc. @docType "package" is deprecated. Please document "_PACKAGE" instead.
Manually edit the PACKAGENAME-package.R file.
FROM
#' @docType package
#' @name PACKAGENAME-package
#' @aliases PACKAGENAME
NULL
TO
#' @keywords internal
"_PACKAGE"
Create R script as you always do (the icon in the upper left corner) and save to the path “~/PATH/PACKAGENAME/R”.
Remember to write the library name if it is not the base one, e.g., stats::cor.test() and rstan::summary().
Otherwise, e.g., usethis::use_package(“dplyr”) and usethis::use_pipe().
Advanced topics about S3 and S4 objects can be found in, e.g., Liquid Brain’s YouTube video, 20 minutes.
Create Stan file as well but save to the path “~/PATH/PACKAGENAME/inst/stan”. The filename should not contain spaces or dashes and nor should it start with a number or utilize non-ASCII characters
Remember to leave a blank line after the Stan code.
Some Stan/rstan examples can be found in Hedibert Freitas Lopes’s post.
2023 update: Updated Stan deprecated syntax. Required rstan version 2.26 or later. See reference at https://mc-stan.org/docs/reference-manual/postfix-brackets-array-syntax.html
For instance, the syntax vector[C] Y[N]; is deprecated
and will be removed in Stan 2.33. The postfix bracket notation for
arrays is replaced by array[N] vector[C] Y;.
int s[C]; is replaced by
array[C] int s;.
The syntax for declaring vector types, such as
vector[N] b;, remains unchanged.
Place the cursor inside the R function body, and click on the tool bar Code - Insert Roxygen Skeleton.
The first sentence will be the title. The next paragraph will be Description. And, the following paragraphs will all go to the Details section.
As for Examples, use
#' \dontrun{}
(no space before { ) to prevent from running them (when checking).
usethis::use_data_raw()
## code to prepare `DATASET` dataset goes here
recall.long <- data.frame(
"Subject" = factor(paste("s", rep(1:10,3), sep="")),
"Level" = factor(rep(c("Level1", "Level2", "Level3"), each = 10)),
"Response" = c(10,6,11,22,16,15,1,12,9,8,
13,8,14,23,18,17,1,15,12,9,
13,8,14,25,20,17,4,17,12,12))
usethis::use_data(recall.long, overwrite = TRUE, compress = "xz")
recall.wide <- data.frame(
"Level1" = c(10,6,11,22,16,15,1,12,9,8),
"Level2" = c(13,8,14,23,18,17,1,15,12,9),
"Level3" = c(13,8,14,25,20,17,4,17,12,12))
rownames(recall.wide) <- paste("s", c(1:10), sep="")
usethis::use_data(recall.wide, overwrite = TRUE, compress = "xz")
This DATASET.R file will be located in “~/PATH/PACKAGENAME/data-raw”.
See https://r-pkgs.org/data.html. Basically, it is an R script saved along with the R function file(s) in “~/PATH/PACKAGENAME/R”.
Do not use
@source \doi{10.3758/BF03210951}, because this will
increase the build runtime. See my stackflow
answer.
Save an R script (usually named as zzz.R) in “~/PATH/PACKAGENAME/R”. This can print a message whenever the package is loaded.
.onAttach <- function(...) {
packageStartupMessage("For execution on a local, multicore CPU with excess RAM we recommend calling\n",
"options(mc.cores = parallel::detectCores()).\n")
if (.Platform$OS.type == "windows") {
packageStartupMessage("Do not specify '-march=native' in 'LOCAL_CPPFLAGS' or a Makevars file")
}
}
example(source)
try(roxygen2::roxygenize(load_code = sourceDir), silent = TRUE)
pkgbuild::compile_dll()
roxygen2::roxygenize()
The third command may take a while to run. It complies the C++ code.
Now, open NAMESPACE and see if it looks like this
import(Rcpp)
import(methods)
importFrom(rstan,sampling)
useDynLib(PACKAGENAME, .registration = TRUE)
usethis::use_build_ignore("[.]xlsx$", escape = FALSE)
Or, manually edit the file (yes, it is OK to do so).
^.*\.Rproj$
^\.Rproj\.user$
^LICENSE\.md$
^data-raw$
^\.travis\.yml$
^\.DS_Store$
^\.o$
^\.so$
^\.dll$
^\.Rhistory$
^README\.Rmd$
^README\.md$
^\.git$
^appveyor\.yml$
^codecov\.yml$
^_pkgdown\.yml$
^docs$
^pkgdown$
^\.github$
^cran-comments\.md$
To be included…
Click on the tool bar Tools - Version Control - Project Setup - Git/SVN and select Git. The RStudio session will restart. Register a GitHub account and open https://github.com/settings/tokens to generate the token. Create a new (GitHub) project and make sure it has been granted permissions such as gist, repo, user, and workflow.
Open the terminal APP, go the package directory cd /PATH/PACKAGENAME (if you do not know how to form a path, just drag the package PACKAGENAME folder to the terminal APP and it will be displayed).
git remote add origin https://github.com/USER/PACKAGENAME.git
git branch -M main
git push -u origin main
Create README.Rmd.
usethis::use_readme_rmd()
It is time to show your markdown skill. 😃
This means you may have multiple GitHub accounts. For a macOS user, open the Keychain Access APP and search “github”. Open the one with “internet password” and edit it. The password should be your token (not the GitHub account password or desktop password).
.DS_Store
.Rproj.user
.Rhistory
.RData
*.o
See the HDInterval package for reference.
Add GitHub url.
URL: https://github.com/USER/PACKAGENAME
BugReports: https://github.com/USER/PACKAGENAME/issues
Nevertheless, the commit, push, and pull requests are not discussed here. [2021 update: the “master” branch is now called “main”]
install.packages("pkgdown")
usethis::use_pkgdown()
pkgdown::build_site()
Make sure .gitignore does not include “docs”. Commit and push to GitHub.
On GitHub Pages settings, i.e., https://github.com/USER/PACKAGENAME/settings/pages, select “Source” as “Branch:main” - “/(root)”, and then save.
On the upper right corner “About”, https://github.com/USER/PACKAGENAME, now you can fill in the pkgdown “Website”, https://USER/github.io/PACKAGENAME/
If you need to properly render LaTeX equations, then edit README.Rmd like this:
---
output:
github_document:
pandoc_args: --webtex=https://latex.codecogs.com/svg.latex?
---
OR
---
output:
github_document:
pandoc_args: --webtex=https://latex.codecogs.com/png.image?
---
Whenever you modify the function or data documentation and READEME, remember to run the following line again to update index.html in the docs folder.
pkgdown::build_site()
Write the .Rd file to the man (stands for “manual”) folder.
devtools::document()
?PACKAGENAME::FUNC #see documentation
devtools::check(args = c('--as-cran'))
Now, carefully read https://r-pkgs.org/r-cmd-check.html. Review the old and know the new.
CRAN provides an automated service for checking R packages on windows.
devtools::check_win_release()
devtools::check_win_devel()
devtools::check_win_oldrelease()
If you see a warning like this (on macOS):
> checking top-level files ... WARNING
A complete check needs the 'checkbashisms' script.
See section ‘Configure and cleanup’ in the ‘Writing R Extensions’
manual.
Turn to my stackflow answer. The other two notes regarding “checking installed package size” (any package larger than 5Mb) and “checking for GNU extensions in Makefiles” (Stan-based) do not need to worry about.
Example One: Prevent using [[1]] as a list number in the documentation.
checking Rd cross-references ... WARNING
Missing link or links in documentation object 'FUNC.Rd':
‘0,1’ ‘1’ ‘2’ ‘3’
Example Two: Not hiding .travis.yml in .Rbuildignore.
checking for hidden files and directories ... NOTE
Found the following hidden files and directories:
.travis.yml
These were most likely included in error.
Example Three: Writing too long one-line example in the documentation. Need to start a newline.
checking Rd line widths ... NOTE
Rd file '***.Rd':
\examples lines wider than 100 characters:
These lines will be truncated in the PDF manual.
Example Four: I accidentally wrote the year 2024 as 2023 in DESCRIPTION.
Check: CRAN incoming feasibility, Result: NOTE
The Date field is over a month old.
I am not using Travis CI anymore. You could jump to the next section 6.2.
Travis CI domain has been moved from travis-ci.org to travis-ci.com.
usethis::use_travis()
Overwrite pre-existing file ‘.travis.yml’? Enter 1. Then, it automatically adds Travis build status badge to ‘README.Rmd’ like this:
<!-- badges: start -->
[](https://travis-ci.com/github/USER/PACKAGENAME)
Knit README.Rmd again to update README.md.
Open .travis.yml and replace the context with the following one.
language: r
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
- libv8-dev
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
before_install:
- mkdir -p ~/.R/
- echo "CXX14 = g++-7 -fPIC -flto=2" >> ~/.R/Makevars
- echo "CXX14FLAGS = -mtune=native -march=native -Wno-unused-variable -Wno-unused-function -Wno-unused-local-typedefs -Wno-ignored-attributes -Wno-deprecated-declarations -Wno-attributes -O3" >> ~/.R/Makevars
install:
- R -e "install.packages('rstan')"
script:
- R -e "rstan::stan_version()"
usethis::use_appveyor()
It automatically adds AppVeyor build status badge to ‘README.Rmd’ like this:
[](https://ci.appveyor.com/project/USER/PACKAGENAME)
<!-- badges: end -->
And, it automatically adds ‘^appveyor\.yml$’ to ‘.Rbuildignore’. Knit README.Rmd again to update README.md.
Commit and push the changes to GitHub. Let Travis CI check on Linux and Appveyor check on Windows.
To remove
continuous-integration/appveyor/branch - AppVeyor build failed,
delete Webhooks under Settings and delete the
‘appveyor.yml’ file.
Watch Dean Attali’s YouTube video, 20 minutes.
usethis::use_github_action_check_standard()
usethis::use_coverage()
The covr package is required. It automatically adds
‘covr’ to Suggests field in DESCRIPTION; adds ‘^codecov\.yml$’
to ‘.Rbuildignore’; adds Codecov test coverage badge to
‘README.Rmd’; etc.
Open codecov.yml and manually add the following:
comment: false
language: R
sudo: false
cache: packages
after_success:
- Rscript -e 'covr::codecov()'
Now, you can access https://app.codecov.io/gh/USER/PACKAGENAME/
And, run the following line locally (it may take a while):
covr::codecov(token = "YOUR TOKEN")
Or, you can automate it by GitHub Actions, e.g.,
usethis::use_github_action("test-coverage")
which creates test-coverage.yaml in “~/PATH/PACKAGENAME/.github/workflows”.
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
name: test-coverage
jobs:
test-coverage:
runs-on: macOS-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
- uses: r-lib/actions/setup-r@master
- uses: r-lib/actions/setup-pandoc@master
- name: Query dependencies
run: |
install.packages('remotes')
saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
shell: Rscript {0}
- name: Cache R packages
uses: actions/cache@v1
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
- name: Install dependencies
run: |
install.packages(c("remotes"))
remotes::install_deps(dependencies = TRUE)
remotes::install_cran("covr")
shell: Rscript {0}
- name: Test coverage
run: covr::codecov()
shell: Rscript {0}
To increase the codecov percentage, you need to test the
the code in every possible if-statement.
usethis::use_testthat()
The testing R script(s) should be saved in
“~/PATH/PACKAGENAME/tests/testthat” and named as
“test-SOMETHING.R”. Use of context() is no longer
recommended. Check some expected outputs from the usage.
test_that("Error handling - method arg", {
expect_error(FUNC(data.wide = recall.wide, method = -1),
"should be one of")
})
skip_on_cran()
skip_on_os(c("windows", "linux", "solaris"))
test_that("Within-subjects HDI width computed by (default) Method 1", {
HDI <- FUNC(data.wide = recall.wide, seed = 277)
width <- round(HDI$width, 5)
expect_equal(width, 0.53877)
})
test_that("Within-subjects HDI width computed by Method 2", {
w <- capture_warnings(HDI <- FUNC(data.wide = recall.wide, method = 2, seed = 277))
expect_match(w, ".*treedepth", all = FALSE)
expect_match(w, ".*pairs()", all = FALSE)
width <- round(HDI$width, 5)
expect_equal(width, 0.51502)
})
Note: Stan results will only be exactly reproducible if all of the following components are identical:
See my Stan forum post.
Test the package.
devtools::test()
devtools::test_coverage()
devtools::build()
Now, the .tar.gz file is ready to be shared with others.
Step 1. unzip the build file PACKAGENAME_version.tar.gz (xx KB) into PACKAGENAME_version.tar (xxx KB);
Step 2. continue to unzip the Step 1 file into a neat PACKAGENAME (xxx KB) folder;
Some decompression tools (such as Archive Utility) can directly unzip .tar.gz into the folder in one step.
To significantly speed up the installation, you can try the binary build using GitHub Actions.
See Karim Barigou’s post.
Download, copy, and paste the build.yaml and build-linux.yaml files to the path “~/PATH/PACKAGENAME/.github/workflows”. Commit and push to GitHub.
You should get two workflows on GitHub’s Actions tab, https://github.com/USER/PACKAGENAME/actions. Run these two workflows to generate three artifacts.
If the following errors occur for the Windows build, then delete all .o files from your src folder.
System command 'Rcmd.exe' failed, exit status: 1, stdout + stderr:
C:\rtools40\mingw32\bin\nm.exe: RcppExports.o: file format not recognized
...
Download the zip artifacts and unzip them.
Fork https://github.com/kabarigou/drat : open this website, and click on the upper right corner “Fork”.
Create a new R project on RStudio: the upper left second icon - Version Control - Git, input the forked repository url (https://github.com/USER/drat). “Create project as subdirectory of” means where you locally save this project.
On https://github.com/USER/drat/settings/pages, set the source as “Branch: master - /docs” and save. This step is important!
Edit README.md and docs/index.html content accordingly.
Delete the bin folder in the main directory. Delete the bin and src folders in the docs folder.
drat::insertPackage(file="~/PATH/PACKAGENAME_version.zip", repodir="./docs") #for Windows
drat::insertPackage(file="~/PATH/PACKAGENAME_version.tgz", repodir="./docs") #for Mac
drat::insertPackage(file="~/PATH/PACKAGENAME_version.tar.gz", repodir="./docs") #for Ubuntu
Note: it seems that R package is not backward compatible. If you upload the binary build which is created on R 4.0.5, it likely will not be installed on R 4.0.0.
strategy:
fail-fast: false
matrix:
config:
- {os: macOS-latest, r: '4.1.0'}
- {os: macOS-latest, r: '4.0.1'}
- {os: windows-latest, r: '4.1.0'}
- {os: windows-latest, r: '4.0.1'}
devtools::install("~/PATH/PACKAGENAME")
If the following message pops up, you can enter 3 to continue. (roughly 17 minutes)
“These packages have more recent versions available. It is recommended to update all of them. Which would you like to update? 1: All 2: CRAN packages only 3: None 4: R6 (2.5.0 -> 2.5.1) [CRAN] Enter one or more numbers, or an empty line to skip updates:”
Sometimes, it may display the same context in console for a while. Just wait for completion. Here, no need to worry about the compiling warnings regarding RcppEigen.
If only make a change to the R code or the documentation rather than the Stan file(s).
devtools::install("~/PATH/PACKAGENAME", quick = TRUE)
Install the binary pacakge by calling
install.packages("rstan")
install.packages("PACKAGENAME", repos = "https://user.github.io/drat", type = "binary")
remove.packages("PACKAGENAME")
Follow the tutorial.
Create a cran-comments.md file and push it to GitHub. Make sure this file is in .Rbuildignore. If you do not know how to create a .md file, just download and edit one from any GitHub repository of an R package, e.g., ‘httr’.
## Test environments
* local: darwin18.6.0
* travis: 4.0.2
* appveyor: windows-x86_64-release
* win-builder: windows-x86_64-oldrel, release, devel
* GitHub Actions: macOS-latest-release, windows-latest-release, ubuntu-latest-devel, ubuntu-latest-release, ubuntu-latest-oldrel
## R CMD check results
0 errors | 0 warnings | 2 notes
Any package is larger than 5Mb.
> checking installed package size ... NOTE
installed size is 11.8Mb
sub-directories of 1Mb or more:
libs 11.4Mb
This is a Stan-based R package.
> checking for GNU extensions in Makefiles ... NOTE
GNU make is a SystemRequirements.
## Downstream dependencies
There are currently no downstream dependencies for this package.
If everything looks good, you can upload the package bundle (the .tar.gz file by calling devtools::build()) to the CRAN submission form. Based on my experience, CRAN staff respond to my submission by email in a day. Hopefully, the package goes live on CRAN on that same day. In about three days, the binary packages will also be automatically built on CRAN.
Add any comments to cran-comments.md.
For the future development, create a NEWS.md file and push it to GitHub. Also, make sure this file is in .Rbuildignore.
How to fix image not found (the shared library was built with an earlier version of R)
Error in dyn.load(dll_copy_file) : unable to load shared object …
devtools::clean_dll()