Skip to main content

package-dependencies

Complete guide to managing R package dependencies, including Imports vs Suggests, namespace imports, and handling dependencies in code, tests, examples, and vignettes

来源信息

仓库
choxos/RPkgAgent
最近来源活动
2026年2月15日 21:57
检测到的 SKILL.md 语言
英语
星标
0
分支
0

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
Package Dependencies
description
Complete guide to managing R package dependencies, including Imports vs Suggests, namespace imports, and handling dependencies in code, tests, examples, and vignettes
# Package Dependencies ## Overview Managing dependencies correctly is critical for R packages. This skill covers the different dependency types, how to declare and use them, and common patterns for conditional dependencies. ## CRITICAL Concept: Listing vs Importing **Most important rule**: Listing a package in `Imports:` does NOT make its functions available! ```r # DESCRIPTION: Imports: dplyr # This does NOT work: my_function <- function(data) { filter(data, value > 0) # ERROR: object 'filter' not found } # You must ALSO either: # Option 1: Use explicit namespace (RECOMMENDED for most cases): my_function <- function(data) { dplyr::filter(data, value > 0) } # Option 2: Import to namespace via roxygen2: #' @importFrom dplyr filter my_function <- function(data) { filter(data, value > 0) } ``` **Listing in DESCRIPTION ensures the package is installed.** **Importing to NAMESPACE makes functions available in your code.** ## Dependency Types ### Imports Packages required for your package to work. ```dcf # DESCRIPTION: Imports: dplyr (>= 1.0.0), rlang (>= 1.0.0), tidyr ``` **Guarantees:** - Installed when your package is installed - Loaded when your package is loaded (but not attached) - Functions available via `pkg::fun()` **Use for:** - Packages your code depends on - Packages used in most functions - Critical dependencies **Usage pattern:** ```r # Default: Use pkg::fun() my_function <- function(x) { dplyr::mutate(x, new_col = value * 2) } # Or import specific functions: #' @importFrom dplyr mutate select filter my_function <- function(x) { x %>% filter(value > 0) %>% mutate(doubled = value * 2) } ``` ### Suggests Optional packages for enhanced functionality, tests, or documentation. ```dcf # DESCRIPTION: Suggests: ggplot2, testthat (>= 3.0.0), knitr, rmarkdown, covr ``` **No guarantees:** - May or may not be installed - Must check availability before use - Cannot use `pkg::fun()` without checking **Use for:** - Packages for optional features - Testing frameworks (testthat, covr) - Vignette builders (knitr, rmarkdown) - Packages for examples only - Heavy dependencies users may not need **Usage pattern:** ```r # MUST check availability: my_plot <- function(data) { if (!requireNamespace("ggplot2", quietly = TRUE)) { stop("Package 'ggplot2' required but not installed.\n", "Install with: install.packages('ggplot2')", call. = FALSE) } ggplot2::ggplot(data, ggplot2::aes(x, y)) + ggplot2::geom_point() } # Better: Use rlang::check_installed() my_plot <- function(data) { rlang::check_installed("ggplot2", reason = "to create plots") ggplot2::ggplot(data, ggplot2::aes(x, y)) + ggplot2::geom_point() } ``` ### Depends Makes another package's functions available in user's workspace (rarely recommended). ```dcf # DESCRIPTION: Depends: R (>= 4.1.0), methods ``` **Effects:** - Package is attached when yours is attached - Functions available in user's search path - Modifies user's environment **Modern usage:** - `R (>= version)` - minimum R version (ALWAYS use this) - `methods` - if defining S4 classes - Almost never use for other packages **Why avoid:** ```r # If you use Depends: dplyr: library(mypackage) # Also attaches dplyr # Now user's environment has all dplyr functions: filter # Available (might conflict with stats::filter) ``` **Better approach:** ```r # Use Imports + explicit namespace: Imports: dplyr # In code: dplyr::filter(...) ``` ### LinkingTo For packages with C/C++ code using headers from other packages. ```dcf # DESCRIPTION: LinkingTo: Rcpp, RcppArmadillo ``` **Use for:** - Rcpp packages - Packages providing C++ headers - Compiled code dependencies **Often combined with Imports:** ```dcf Imports: Rcpp (>= 1.0.0) LinkingTo: Rcpp ``` ### Config/Needs/* Dependencies for development tools, not package functionality. ```dcf # DESCRIPTION: Config/Needs/website: pkgdown Config/Needs/coverage: covr Config/Needs/development: devtools, usethis, roxygen2 ``` **Use for:** - pkgdown for website - covr for coverage - Development tools - CI-specific packages **Not installed by default:** ```r # Install with: pak::pak("mypackage", dependencies = TRUE) # Includes Config/Needs/* ``` ## Adding Dependencies ### Using usethis Helpers ```r # Add to Imports: usethis::use_package("dplyr") usethis::use_package("rlang", min_version = "1.0.0") # Add to Suggests: usethis::use_package("ggplot2", type = "Suggests") # Add to Imports with @importFrom: usethis::use_import_from("dplyr", c("filter", "mutate", "select")) # Adds to DESCRIPTION AND creates roxygen2 skeleton # Add minimum R version: usethis::use_package("R", min_version = "4.1.0", type = "Depends") ``` ### Manual Addition ```dcf # DESCRIPTION: Imports: dplyr (>= 1.1.0), rlang (>= 1.0.0), tidyr, purrr Suggests: ggplot2 (>= 3.4.0), testthat (>= 3.0.0) ``` **Version specifications:** ```dcf dplyr # Any version dplyr (>= 1.0.0) # At least 1.0.0 dplyr (>= 1.0.0, < 2.0.0) # Rarely used, not recommended ``` ## Importing Functions to Namespace ### Pattern 1: Explicit Namespace (Recommended) ```r # No NAMESPACE imports needed # Just use pkg::fun() everywhere: my_function <- function(data) { data %>% dplyr::filter(value > 0) %>% dplyr::mutate(doubled = value * 2) %>% dplyr::select(id, doubled) } ``` **Advantages:** - Clear where functions come from - No NAMESPACE management needed - Easy to understand - No import conflicts **Disadvantages:** - More typing - Slightly verbose ### Pattern 2: Selective Import (@importFrom) ```r # Import specific functions: #' @importFrom dplyr filter mutate select #' @importFrom rlang .data .env my_function <- function(data) { data %>% filter(value > 0) %>% mutate(doubled = .data$value * 2) %>% select(id, doubled) } ``` **When to use:** - Functions used many times - Infix operators (%>%, %||%, :=) - Core package dependencies - Reduces verbosity **Where to put @importFrom:** ```r # Option 1: In function documentation: #' My function #' @importFrom dplyr filter mutate my_function <- function() { ... } # Option 2: In package-level doc (R/mypackage-package.R): #' @importFrom dplyr filter mutate select arrange #' @importFrom rlang .data .env %||% "_PACKAGE" # Option 3: Dedicated imports file (R/aaa-imports.R): #' @importFrom dplyr filter mutate select #' @importFrom rlang .data %||% NULL ``` ### Pattern 3: Full Import (@import) - Rare ```r #' @import rlang ``` **Only for:** - rlang (if building tidy evaluation package) - Your own internal package **Avoid for most packages:** - Namespace pollution - Potential conflicts - Unclear provenance ### Operators and Infix Functions **Always import operators:** ```r # WRONG - doesn't work: data %>% dplyr::filter(x > 0) # Error: %>% not found # RIGHT: #' @importFrom magrittr %>% data %>% dplyr::filter(x > 0) # Or use base pipe (R >= 4.1): data |> dplyr::filter(x > 0) # No import needed ``` **Common operators to import:** ```r #' @importFrom magrittr %>% #' @importFrom rlang %||% !! !!! #' @importFrom data.table := .N .SD ``` ## Using Dependencies in Different Contexts ### In Package Code (R/) ```r # Imports dependencies - use pkg::fun() or @importFrom: #' @importFrom dplyr filter my_function <- function(data) { filter(data, value > 0) # OK: imported } # Or: my_function <- function(data) { dplyr::filter(data, value > 0) # OK: explicit namespace } # Suggests dependencies - MUST check first: my_optional_feature <- function(data) { rlang::check_installed("ggplot2", reason = "for plotting") ggplot2::ggplot(data, ggplot2::aes(x, y)) + ggplot2::geom_point() } ``` ### In Examples (@examples) ```r # Imports - can use freely: #' @examples #' my_function(mtcars) # Suggests - must check or wrap: #' @examples #' \dontrun{ #' # Requires ggplot2 #' my_plot(mtcars) #' } #' #' @examplesIf requireNamespace("ggplot2", quietly = TRUE) #' my_plot(mtcars) ``` ### In Tests (tests/testthat/) ```r # Imports - can use freely: test_that("function works", { result <- my_function(data) expect_equal(result$value, expected) }) # Suggests - MUST skip if not available: test_that("plotting works", { skip_if_not_installed("ggplot2") plot <- my_plot(data) expect_s3_class(plot, "gg") }) test_that("integration with optional package", { skip_if_not_installed("dplyr") library(dplyr) result <- data %>% my_transform() %>% summarize(mean = mean(value)) expect_equal(result$mean, 5) }) ``` ### In Vignettes (vignettes/) ```r # YAML header for Suggests dependency: # --- # title: "My Vignette" # vignette: > # %\VignetteIndexEntry{My Vignette} # %\VignetteEngine{knitr::rmarkdown} # --- # First chunk - setup with conditional evaluation: # ```{r setup, include=FALSE} # knitr::opts_chunk$set( # eval = requireNamespace("ggplot2", quietly = TRUE) # ) # ``` # Now code chunks only run if ggplot2 available: # ```{r} # library(ggplot2) # ggplot(data, aes(x, y)) + geom_point() # ``` ``` **Alternative: Use separate vignettes:** ```dcf # DESCRIPTION: Suggests: knitr, rmarkdown, ggplot2 # vignettes/basic-usage.Rmd - no optional deps # vignettes/advanced-plotting.Rmd - requires ggplot2 ``` ### In Documentation (roxygen2) ```r # References to Suggests packages: #' @description #' This function provides plotting capabilities. Requires the #' \pkg{ggplot2} package to be installed. #' #' @seealso [ggplot2::ggplot()] for more plotting options ``` ## Minimum Version Specifications ### When to Specify Versions ```dcf # Always specify if you need specific features:
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看