r语言 - "no applicable method" 对于 S3 泛型,尽管存在默认方法



这很棘手,因为这个问题只发生在包的上下文中——在全局命名空间中定义时,一切都按预期工作。

我定义了一个S3泛型称为coerce_na_range(),它有两个方法,coerce_na_range.factor()coerce_na_range.default()coerce_na_range()是导出的,但这两种方法都没有导出。(该函数的目的是在给定范围内用NA替换编码为字符或因子标签的数字。)

在全局命名空间中定义时,如果我将一个字符向量传递给coerce_na_range(),它将其分派给coerce_na_range.default()并按预期工作:

vec <- c("green", "yellow", "-9", "red", "-1")
coerce_na_range(vec)
# [1] "green"  "yellow" NA       "red"    NA   
然而,如果我在一个新的会话中加载包,它似乎忽略了默认方法:
library(lighthouse)
vec <- c("green", "yellow", "-9", "red", "-1")
coerce_na_range(vec)
# Error in UseMethod("coerce_na_range") : 
#  no applicable method for 'coerce_na_range' applied to an object of class "character"

我不认为问题是方法没有导出?例如,tidyr:::full_seq.Date()等不能导出,而tidyr::full_seq()显然可以。

包托管在https://github.com/ccsarapas/lighthouse。coerce_na_range()、它的方法和它们所依赖的几个函数的代码如下:

#' Suppress NA warning when coercing to numeric
#'
#' Coerces `x` to numeric. If `x` cannot be coerced, returns `NA` and suppresses
#' coercion warning.
#'
#' @export
try_numeric <- function(x) {
if (is.factor(x)) {
warning(
"`x` is a factor and will be converted based on factor codes, not factor labels."
)
}
withCallingHandlers(
warning = function(w) {
if (conditionMessage(w) == "NAs introduced by coercion") {
rlang::cnd_muffle(w)
}
},
as.numeric(x)
)
}
#' @rdname try_numeric
#'
#' @export
try.numeric <- function(x) try_numeric(x)
#' Generate NA values of appropriate type
#'
#' Returns compatible `NA` based on `x`. This is usually of the same type as `x`
#' (e.g., `NA_real_` if `x` is a double vector). If `x` is a factor, will
#' return `NA_character_` if `factor_as_character = TRUE` (the default) and
#' `NA_integer_` otherwise.
#'
#' @export
na_like <- function(x, factor_as_character = TRUE, match_length = FALSE) {
stopifnot("`x` must be an atomic vector" = is.atomic(x))
type_out <- if (factor_as_character && is.factor(x)) "character" else typeof(x)
length_out <- if (match_length) length(x) else 1L
rep(methods::as(NA, type_out), length_out)
}

#' Set NA values based on numbers stored as strings.
#'
#' Changes values coercible to numeric in range `range_min`:`range_max` to `NA`.
#' Useful for imported SPSS files.
#'
#' @export
coerce_na_range <- function(x, ...) UseMethod("coerce_na_range")
coerce_na_range.default <- function(x, range_min = -Inf, range_max = -1) {
coerced <- try.numeric(x)
dplyr::if_else(
is.na(coerced) | (coerced < range_min) | (coerced > range_max),
x,
na_like(x)
)
}
coerce_na_range.factor <- function(x, range_min = -Inf, range_max = -1) {
lvls <- levels(x)
coerced <- try.numeric(as.character(lvls))
lvls <- lvls[is.na(coerced) | coerced < range_min | coerced > range_max]
factor(x, levels = lvls)
}

generic.factor之前添加@export标签并运行roxgenize应该可以解决这个问题:

# [...]
#' @exportS3Method coerce_na_range factor
coerce_na_range.factor <- function(x, range_min = -Inf, range_max = -1) {
lvls <- levels(x)
coerced <- try.numeric(as.character(lvls))
lvls <- lvls[is.na(coerced) | coerced < range_min | coerced > range_max]
factor(x, levels = lvls)
}

然后在控制台中运行:roxygen2::roxygenise()

相关内容

  • 没有找到相关文章

最新更新