使用devtools::check()时R包@examples报错的解决需求
解决R包
make_dicho()函数devtools检查示例报错问题 问题出在哪
- 示例代码有语法错误:你用的
----------------------------------------------------------------------------不是合法的R注释,devtools检查时会把它当成代码执行,直接触发语法错误,这是最直接的原因。 - dplyr环境下变量名获取失效:函数里的
deparse(substitute(x))在mutate()或across()里拿不到正确的原始列名——比如在across里会得到.col,在新生成的因子列里得到临时变量名,导致属性里的描述文本异常。 - 普通因子输入的标签丢失:当输入是普通因子时,
labelled::var_label(x)会返回NULL,手动运行没事,但devtools的严格检查可能会触发警告或错误。
怎么改
1. 先修复示例的语法错误
把那些分割线改成合法注释,前面加#:
# ----------------------------------------------------------------------------
不然R会把这些横线当成无效代码,直接报错。
2. 重写make_dicho()函数,适配dplyr环境
调整变量名获取方式,处理边缘情况:
make_dicho <- function(x, flip_levels = FALSE) { # 用rlang工具在dplyr环境里正确获取变量名 x_expr <- rlang::ensym(x) x_lab <- rlang::as_label(x_expr) # 处理普通因子无标签的情况,避免NULL值 variable_label <- labelled::var_label(x) %||% "" # 转换为因子(输入已是因子则无变化) x <- haven::as_factor(x) # 处理水平文本:移除第一个单词并转为标题格式 x <- dplyr::if_else( stringr::str_detect(x, "\\s"), stringr::str_replace(x, "\\w+\\s", ""), x ) |> stringr::str_to_title() # 提前检查水平数量,防止索引越界报错 x_levels <- unique(x) if (length(x_levels) != 2) { stop("处理后变量必须包含且仅包含两个水平,请检查输入数据") } # 处理水平翻转逻辑 if (flip_levels) { lab <- x_levels[2] x <- forcats::fct_relevel(x, lab) } else { lab <- x_levels[1] x <- forcats::as_factor(x) } # 添加自定义属性 structure( x, transformation = glue::glue( "Converting '{x_lab}' to a dichotomous factor{if(flip_levels) paste0(' and reordering levels so that ', shQuote(lab), ' is reference') else paste0(' with ', shQuote(lab), ' as reference')}" ), label = variable_label ) }
- 用
rlang::ensym()和rlang::as_label()替代原来的deparse(substitute(x)),在dplyr的mutate/across环境中也能拿到正确的列名。 - 用
%||%处理无标签的情况,需要在包中导入rlang的这个函数,或者自己定义:%||% <- function(a, b) if (is.null(a)) b else a。 - 新增水平数量检查,防止数据异常导致索引错误。
- 优化属性文本生成逻辑,更简洁清晰。
3. 调整across示例,无需\dontrun{}
把across里的直接传函数改成匿名函数,确保变量名正确获取:
# function also works inside dplyr::across() # Create new columns using `across()` dicho_df <- df %>% dplyr::mutate( # 不翻转水平的用法 dplyr::across( x:z, ~make_dicho(.), .names = "dicho_{col}" ), # 翻转水平的用法 dplyr::across( x:z, ~make_dicho(., flip_levels = TRUE), .names = "dicho_flipped_{col}" ) )
用~make_dicho(.)的方式传参,结合.names参数,函数内部能正确识别原始列名。
4. 确保包依赖完整
在包的DESCRIPTION文件中添加必要的依赖:
Imports: dplyr, forcats, glue, haven, labelled, rlang, stringr, tibble
同时在函数的文档注释中添加@importFrom导入所需函数:
#' @importFrom rlang ensym as_label %||% #' @importFrom dplyr if_else #' @importFrom forcats fct_relevel as_factor #' @importFrom glue glue #' @importFrom haven as_factor #' @importFrom labelled var_label #' @importFrom stringr str_detect str_replace str_to_title
验证
修改完成后重新运行devtools::check(),示例代码应能正常执行,无报错;手动运行示例也能保持原有功能。
内容的提问来源于stack exchange,提问作者jdenn0514
相关产品推荐
相关产品推荐

