Packages are how R code is shared, tested and documented, even inside a single team.
Install from CRAN with install.packages("pkg"), from Bioconductor with BiocManager::install, and from GitHub with remotes::install_github("user/repo") or pak::pak(). library(pkg) attaches a package to the search path; pkg::fun() calls one function without attaching, which is clearer in scripts and required inside packages. When two attached packages export the same name, the last attached wins (masking), which is another reason to prefer ::.
For reproducible projects, renv records exact package versions in a lockfile (renv::init(), renv::snapshot(), renv::restore()), so collaborators and servers get the same library.
A package is a directory with a standard layout:
DESCRIPTION: name, version, authors, and dependencies inImports.NAMESPACE: which functions are exported and which are imported, usually generated by roxygen2 comments (#' @export).R/for code,tests/testthat/for tests,man/for generated help,vignettes/for long-form docs.
The usethis and devtools packages automate the workflow: usethis::create_package(), usethis::use_r("file"), devtools::load_all() to reload during development, devtools::document(), devtools::test() and devtools::check(), which runs R CMD check just as CRAN does.
Example
# Uses only base R: a package-shaped directory and the :: operator
print(stats::median(c(5, 1, 9))) #> [1] 5
print("package:stats" %in% search()) #> [1] TRUE
print(exists("filter")) #> [1] TRUE (stats::filter)
print(environmentName(environment(median))) #> [1] "stats"
dir <- file.path(tempdir(), "tempconv")
dir.create(file.path(dir, "R"), recursive = TRUE, showWarnings = FALSE)
writeLines(c("Package: tempconv", "Version: 0.1.0", "Title: Convert Temperatures",
"Imports: stats", "License: MIT"), file.path(dir, "DESCRIPTION"))
writeLines("export(c_to_f)", file.path(dir, "NAMESPACE"))
writeLines(c("#' @export", "c_to_f <- function(c) c * 9 / 5 + 32"),
file.path(dir, "R", "convert.R"))
print(sort(list.files(dir, recursive = TRUE)))
#> [1] "DESCRIPTION" "NAMESPACE" "R/convert.R"
# then: devtools::load_all(dir); devtools::check(dir)Remember
pkg::fun()avoids masking and is required inside packages- renv pins package versions per project
- A package = DESCRIPTION + NAMESPACE + R/ + tests/
- usethis/devtools automate create, document, test and check
Watch out for
- Calling library() inside package code instead of declaring dependencies in DESCRIPTION Imports.