Masking methods in R

后端 未结 2 1581
感动是毒
感动是毒 2021-02-07 06:32

This question and in particular this answer brought up the following question: How can I get a warning about the masking of methods in R?

If you run the following code

2条回答
  •  攒了一身酷
    2021-02-07 07:25

    Update There is now an R package on github that tries to solve these issues. It is still far from an ideal solution, but it goes som way towards solving the issue. It currently has functions require, library and warnS3Methods.

    devtools::install_github("blasern/warnS3")
    require(warnS3)
    
    # Examples
    require2(dplyr)
    ## Loading required package: dplyr
    ##
    ## Attaching package: ‘dplyr’
    ##
    ## The following object is masked from ‘package:stats’:
    ##  
    ##  filter
    ##
    ## The following objects are masked from ‘package:base’:
    ##   
    ##  intersect, setdiff, setequal, union
    ## 
    ## The following methods are masked by 'package:dplyr':
    ##  
    ##  'lag.default' from 'package:stats'
    
    require2(roxygen2)
    ## Loading required package: roxygen2
    ## The following methods are masked by 'package:roxygen2':
    ##  
    ##  'escape.character' from 'package:dplyr'
    
    warnS3Methods()
    ## The following methods are available in multiple packages: 
    ##  
    ##  'escape.character' in packages: dplyr, roxygen2
    ##  'lag.default' in packages: dplyr, stats
    

    This is only a an idea of how one can find masked S3 methods. It is by no means a perfect solution, but I guess until somebody comes up with a better idea it will at least help with debuging.

    #' Get all S3 methods from a package
    #' 
    #' Find all S3 methods from a package
    #' 
    #' @param pkg can be either the name of an installed package
    #' or the path of a package
    getPkgS3Methods <- function(pkg){
      if (basename(pkg) == pkg) pkg <- path.package(pkg)
      ns <- parseNamespaceFile(basename(pkg), 
                               dirname(pkg), 
                               mustExist = FALSE)
      if (length(ns$S3methods) == 0) return(NULL)
      df <- cbind.data.frame(basename(pkg), ns$S3methods)
      colnames(df) <- c("package", "method", "class", "other")
      df
    }
    
    #' Get masked S3 methods
    #' 
    #' Finds all S3 methods that are currently available that are
    #' duplicated
    getMaskedS3Methods <- function(){
      paths <- as.character(gtools::loadedPackages(silent = TRUE)[, "Path"])
      lst <- lapply(paths, getPkgS3Methods)
      all_methods <- do.call(rbind, lst)
      duplicates <- 
      duplicated(all_methods[, c("method", "class")]) |
        duplicated(all_methods[, c("method", "class")], fromLast = TRUE)
      res <- all_methods[duplicates, ]
      res[order(res$method, res$class, res$package), ]
    }
    

    Called from a clean workspace (with the above functions, but no packages loaded), you can then observe the following:

    getMaskedS3Methods()
    ## [1] package method  class   other  
    ## <0 rows> (or 0-length row.names)
    
    require(dplyr)
    getMaskedS3Methods()
    ## package method   class other
    ## 143   dplyr    lag default  
    ## 438   stats    lag default  
    

    That just tells you that here are two lag.default methods. It does not actually tell you, which one is masking the other. It just points out potential problems.

提交回复
热议问题