用途
该技能用于在开发 R 包时提供专家级指导,确保遵循正确的工作流、测试模式和文档标准。当进行 R 包开发、编写 R 测试、编写 R 函数文档、搭建 R 包基础设施、运行 R 包检查,或使用 devtools、testthat、roxygen2 时,可激活此技能。该技能提供 R 专属的开发模式,项目特定的架构与领域知识应保留在项目的 CLAUDE.md 文件中。
开发工作流
R 环境
使用 radian 并将 R 作为别名,以便通过 Rscript 调用 R 脚本。不要使用 grep 运行 devtools::test,应阅读完整输出。
包构建与管理
- 交互式开发加载包:
devtools::load_all() - 更新文档(提交 R 变更前必需):
devtools::document() - 运行所有测试:
devtools::test() - 运行特定测试文件:
testthat::test_file("tests/testthat/test-filename.R") - 按模式运行测试:
devtools::test(filter = "pattern")或testthat::test_local(filter = "pattern") - 检查包(R CMD check):
devtools::check() - 构建包:
devtools::build() - 本地安装包:
devtools::install() - 构建 vignettes 后检查:
devtools::check(build_args = c("--compact-vignettes=both"))
代码质量与风格
- 对包进行 lint(配置在 .lintr):
lintr::lint_package() - 对特定文件进行 lint:
lintr::lint("R/filename.R") - 格式化代码(pre-commit 钩子通常使用 tidyverse 风格):
styler::style_pkg() - 检查测试覆盖率:
covr::package_coverage()
文档构建
- 构建 vignettes:
devtools::build_vignettes() - 构建特定 vignette:
rmarkdown::render("vignettes/name.Rmd") - 本地构建 pkgdown 站点:
pkgdown::build_site()
测试最佳实践
testthat 模式
优先使用的期望函数:
expect_identical()优于expect_equal()(当期望精确匹配时)- 多个
expect_true()调用优于用&&堆叠条件 expect_s3_class()优于expect_true(inherits(...))- 使用具体的 expect_* 函数:
expect_lt()、expect_gt()、expect_lte()、expect_gte()、expect_length()、expect_named()、expect_type()
示例:
# Good
expect_identical(result, expected)
expect_s3_class(obj, "data.frame")
expect_lt(value, 10)
expect_true(condition1)
expect_true(condition2)
# Avoid
expect_equal(result, expected) # when identical match is needed
expect_true(inherits(obj, "data.frame"))
expect_true(value < 10)
expect_true(condition1 && condition2)
测试组织
- 使用 testthat 第 3 版
- 测试文件命名为 test-{component}.R
- 辅助文件放在 tests/testthat/helper-{name}.R
- 共享 fixture 的 setup 文件放在 tests/testthat/setup.R
- 自定义期望放在 tests/testthat/helper-expectations.R
条件测试
- 在 CRAN 上跳过测试:
testthat::skip_on_cran() - 不在 CI 时跳过:
testthat::skip_if_not(on_ci()) - 包不可用时跳过:
testthat::skip_if_not_installed("package")
文档标准
roxygen2 最佳实践
使用 @inheritParams 避免重复:
#' @param x Input data
#' @param ... Additional arguments
my_function <- function(x, ...) {}
#' @inheritParams my_function
#' @param y Another parameter
wrapper_function <- function(x, y, ...) {}
文档结构:
- 描述中每行一句话
- 每行最多 80 个字符
- 使用 @family 标签标记相关函数
- 使用 @examples 或 @examplesIf 提供示例
- 使用英式英语拼写
示例文档:
#' Process input data
#'
#' This function processes the input data according to specified parameters.
#' It returns a processed data frame with additional columns.
#'
#' @param data A data.frame containing the input data
#' @param method Character string specifying the processing method
#'
#' @return A data.frame with processed results
#'
#' @family preprocessing
#'
#' @examples
#' \dontrun{
#' result <- process_data(my_data, method = "standard")
#' }
#'
#' @export
process_data <- function(data, method = "standard") {
# implementation
}
代码风格指南
命名约定
- 内部函数:以 . 为前缀,如
.internal_helper <- function() {} - 导出函数:使用 snake_case,如
public_function <- function() {}
格式化
- 每行最多 80 个字符
- 无行尾空白
- 无多余空行
- 使用 tidyverse 风格指南
- 设置 pre-commit 钩子以自动格式化
Pre-commit 钩子
典型的 .pre-commit-config.yaml 包括:
- style-files:自动格式化 R 代码
- lintr:对 R 代码进行 lint
- readme-rmd-rendered:确保 README.md 是最新的
- parsable-R:检查 R 语法
- deps-in-desc:检查依赖是否在 DESCRIPTION 中
# Install pre-commit
pip install pre-commit
# Install hooks
pre-commit install
# Run manually
pre-commit run --all-files
常见数据结构
data.table 用法
许多 R 包使用 data.table 以提升性能:
- 函数通常期望/返回 data.table 对象
- 使用
data.table::setDT()或自定义coerce_dt()确保输入为 data.table - 设置键以实现高效连接:
data.table::setkey(dt, col) - 使用
:=进行原地修改
S3 类
- 使用
inherits()或expect_s3_class()检查类 - 正确记录 S3 方法
- 导出构造函数,而非内部类定义
包依赖
管理依赖
- 使用
::调用特定包的函数:package::function() - 添加到 DESCRIPTION 的 Imports 或 Suggests:
usethis::use_package("package_name")usethis::use_package("package_name", type = "Suggests")
常见 R 包生态工具
- devtools:开发工作流
- testthat:测试框架
- roxygen2:文档生成
- usethis:包设置自动化
- lintr:代码 lint
- styler:代码格式化
- covr:测试覆盖率
- pkgdown:网站生成
适用场景
在以下情况激活此技能:
- 开发 R 包
- 编写 R 测试
- 编写 R 函数文档
- 搭建 R 包基础设施
- 运行 R 包检查
- 使用 devtools、testthat 或 roxygen2
限制
该技能提供 R 专属的开发模式。项目特定的架构与领域知识应保留在项目的 CLAUDE.md 文件中。