Помощь метода S3 (roxygen2)
Я пытаюсь использовать S3-метод в пакете и думал, что понял, как настроить его, задав здесь вопрос: Предупреждение о непротиворечивости метода S3 при создании пакета R с Roxygen
Но теперь я получаю результаты, которых я не ожидаю. Если я запускаю код ниже непосредственно в R, он дает мне ожидаемые результаты, но если я скомпилирую его в пакет, я не получу правильные результаты (обратите внимание на слово, которое подсчитывается дважды, когда оно должно принимать только уникальные слова из vector a
). Я не уверен, что я неправильно настроил.
Файл .R:
#' Find Common Words Between Groups
#'
#' Find common words between grouping variables (e.g. people).
#'
#' @param word.list A list of names chacter vectors.
#' @param overlap Minimum/exact amount of overlap.
#' @param equal.or A character vector of c(\code{"equal"}, \code{"greater"},
#' \code{"more"}, \code{"less"}).
#' @param \dots In liu of word.list the user may input n number of character
#' vectors.
#' @rdname common
#' @return Returns a dataframe of all words that match the criteria set by
#' \code{overlap} and \code{equal.or}.
#' @export
#' @examples
#' \dontrun{
#' a <- c("a", "cat", "dog", "the", "the")
#' b <- c("corn", "a", "chicken", "the")
#' d <- c("house", "feed", "a", "the", "chicken")
#' common(a, b, d, overlap=2)
#' common(a, b, d, overlap=3)
#'
#' r <- list(a, b, d)
#' common(r)
#' common(r, overlap=2)
#'
#' common(word_list(DATA$state, DATA$person)$cwl, overlap = 2)
#' }
common <-
function(word.list, ...){
UseMethod("common")
}
#' @return \code{NULL}
#'
#' @rdname common
#' @method common list
common.list <-
function(word.list, overlap = "all", equal.or = "more", ...){
if(overlap=="all") {
OL <- length(word.list)
} else {
OL <- overlap
}
LIS <- sapply(word.list, unique)
DF <- as.data.frame(table(unlist(LIS)), stringsAsFactors = FALSE)
names(DF) <- c("word", "freq")
DF <- DF[order(-DF$freq, DF$word), ]
DF <- switch(equal.or,
equal = DF[DF$freq == OL, ],
greater = DF[DF$freq > (OL - 1), ],
more = DF[DF$freq > (OL - 1), ],
less = DF[DF$freq < (OL + 1), ])
rownames(DF) <- 1:nrow(DF)
return(DF)
}
#' @return \code{NULL}
#'
#' @rdname common
#' @method common default
#' @S3method common default
common.default <-
function(..., overlap = "all", equal.or = "more", word.list){
LIS <- list(...)
return(common.list(LIS, overlap, equal.or))
}
a <- c("a", "cat", "dog", "the", "the")
b <- c("corn", "a", "chicken", "the")
d <- c("house", "feed", "a", "the", "chicken")
common(a, b, d, overlap=2)
r <- list(a, b, d)
common(r, overlap=2)
Запуск кода из командной строки (ожидаемое поведение):
> common(a, b, d, overlap=2)
word freq
1 a 3
2 the 3
3 chicken 2
>
>
> r <- list(a, b, d)
> common(r, overlap=2)
word freq
1 a 3
2 the 3
3 chicken 2
Результат после компиляции пакета:
> a <- c("a", "cat", "dog", "the", "the")
> b <- c("corn", "a", "chicken", "the")
> d <- c("house", "feed", "a", "the", "chicken")
> common(a, b, d, overlap=2)
word freq
1 a 3
2 the 3
3 chicken 2
>
>
> r <- list(a, b, d)
> common(r, overlap=2)
word freq
1 the 4
2 a 3
3 chicken 2
Ответы
Ответ 1
Ошибка, которую вы видите, чаще всего вызвана тем, что метод списка общего родословного не экспортируется, поэтому вместо него вызывается common.default
. Вы можете решить эту проблему, используя devtools::missing_s3
- функция немного эвристична, поэтому вы можете получить несколько ложных срабатываний (например, в настоящее время она не может сказать, что is.list
не является методом). Это невероятно распространенная проблема (она меня так много раз поймала), и следующая итерация roxygen сделает больше, чтобы предотвратить ее.
В настоящее время, чтобы правильно экспортировать методы S3 с помощью roxygen, вам необходимо выполнить следующие действия:
-
@S3method generic class
(и ничего больше), если вы не хотите документировать метод
-
@method generic class
и @export
, если вы хотите экспортировать и документировать его.
У вас никогда не должно быть @S3method
и @method
в том же блоке документации.
Обновление для roxygen2 > 3.0.0
Теперь roxygen автоматически определяет, является ли функция S3-методом так:
- Никогда не используйте
@S3method
или @method
- Используйте
@export
, если вы хотите, чтобы метод был экспортирован (что вы обычно делаете, даже если общий не является)