10

我正在尝试在包中使用 S3 方法,并在此处提出问题后认为我理解了如何设置它:使用 Roxygen 构建 R 包时的 S3 方法一致性警告

但现在我得到了我没想到的结果。如果我直接在 R 中运行下面的代码,它会给我预期的结果,但如果我将它编译到一个包中,我不会得到正确的结果(请注意,当它应该只取唯一单词时,单词 the 被计数两次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
4

1 回答 1

16

您看到的错误很可能是因为未导出通用泛型的 list 方法,因此common.default被调用。您可以使用devtools::missing_s3- 该函数有点启发式来解决这个问题,因此您可能会得到一些误报(例如,它目前无法判断这is.list不是一种方法)。这是一个非常普遍的问题(它已经困扰了我很多次),并且 roxygen 的下一次迭代将采取更多措施来防止它。

目前,要使用 roxygen 正确导出 S3 方法,您需要执行以下任一操作:

  • @S3method generic class(仅此而已)如果您不想记录该方法
  • @method generic class@export如果你想导出和记录它。

你不应该在同一个文档块中拥有@S3method和。@method

roxygen2 >3.0.0 的更新

现在 roxygen 会自动判断一个函数是否是 S3 方法,所以:

  • 切勿使用@S3method@method
  • 如果@export您希望导出方法(您通常会这样做,即使不是泛型),请使用
于 2013-01-16T20:45:46.440 回答