Search code examples
rlistmethodsroxygen2generic-function

R - problems dispatching to new method print.list()


In my summarytools package, I have successfully defined the print.by method. However, even though I've followed the exact same steps for print.list, the dispatch fails.

The method seems to have registered, along with the two other print methods defined in the package:

grep("print(\\.summarytools$|\\.by$|\\.list$)", methods("print"), value = TRUE)
[1] "print.by"           "print.list"         "print.summarytools"

In NAMESPACE, I have:

S3method(print,by)
S3method(print,list)
S3method(print,summarytools)

Example

devtools::install_github("dcomtois/summarytools", ref = "dev-current")
library(summarytools)
list_obj <- lapply(tobacco[,c(1,3)], freq))

## $gender
## For best results printing list objects with summarytools, use view(x, method = 'pander')
## Frequencies   
## tobacco$gender     
## Type: Factor   
## 
##               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------- ------ --------- -------------- --------- --------------
##           F    489     50.00          50.00     48.90          48.90
##           M    489     50.00         100.00     48.90          97.80
##        <NA>     22                               2.20         100.00
##       Total   1000    100.00         100.00    100.00         100.00
## 
## $age.gr
## Frequencies   
## tobacco$age.gr     
## Type: Factor   
## 
##               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------- ------ --------- -------------- --------- --------------
##       18-34    258     26.46          26.46     25.80          25.80
##       35-50    241     24.72          51.18     24.10          49.90
##       51-70    317     32.51          83.69     31.70          81.60
##        71 +    159     16.31         100.00     15.90          97.50
##        <NA>     25                               2.50         100.00
##       Total   1000    100.00         100.00    100.00         100.00

Compare with...

summarytools:::print.list(list_obj)

## Frequencies   
## tobacco$gender     
## Type: Factor   
## 
##               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------- ------ --------- -------------- --------- --------------
##           F    489     50.00          50.00     48.90          48.90
##           M    489     50.00         100.00     48.90          97.80
##        <NA>     22                               2.20         100.00
##       Total   1000    100.00         100.00    100.00         100.00
##   
## tobacco$age.gr    
## Type: Factor   
## 
##               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------- ------ --------- -------------- --------- --------------
##       18-34    258     26.46          26.46     25.80          25.80
##       35-50    241     24.72          51.18     24.10          49.90
##       51-70    317     32.51          83.69     31.70          81.60
##        71 +    159     16.31         100.00     15.90          97.50
##        <NA>     25                               2.50         100.00
##       Total   1000    100.00         100.00    100.00         100.00

Here is the contents of print.list.R:

#' Print Method for Objects of Class \dQuote{list}.
#'
#' Displays a list comprised of summarytools objects created with \code{lapply}. 
#'
#' @usage
#'  \method{print}{list}(x, method = "pander", file = "", 
#'   append = FALSE, report.title = NA, table.classes = NA, 
#'   bootstrap.css = st_options('bootstrap.css'), 
#'   custom.css = st_options('custom.css'), silent = FALSE, 
#'   footnote = st_options('footnote'), 
#'   escape.pipe = st_options('escape.pipe'), \dots)
#' 
#' @inheritParams print.summarytools
#' @method print list
#' @export
print.list <- function(x, method = "pander", file = "", append = FALSE, 
                       report.title = NA, table.classes = NA, 
                       bootstrap.css = st_options('bootstrap.css'), 
                       custom.css = st_options('custom.css'),
                       silent = FALSE, footnote = st_options('footnote'), 
                       escape.pipe = st_options('escape.pipe'), ...) {
  if (inherits(x[[1]], "summarytools")) {
    view(x, method = method, file = file, append = append, 
         report.title = report.title, table.classes = table.classes, 
         bootstrap.css = bootstrap.css, custom.css = custom.css,
         silent = silent, footnote = footnote, escape.pipe = escape.pipe,
         ...)
  } else {
    base::print.default(x, ...)
  }
}

I've read several documents having to do with generic functions and their methods, but I can't pinpoint the problem, nor see a solution. I looked at the setMethod() function and the "signature" parameter, but since the function will most likely be called without arguments, I don't see how this would help.

One difference between the two is that print.by exists in the base package, while print.list doesn't. But I couldn't establish whether that is relevant or not.

Further background information about how I came to use this type of function definition can be found in this question I asked earlier.

Edit: I tried a few others things which didn't work...

  • Redefining print.default instead of defining print.list, as suggested here, but it still doesn't work.
  • Adding a call to setMethod after the function definition (setMethod(f = "print", signature = "list", definition = print.list)); still no good results (I'm not too sure I get what the "signature" argument is supposed to be. I find the documentation about it rather confusing).

I'm starting to think there might be a little twist I need to do with Roxygen for it to work... But what twist, I don't know.

Any help much appreciated.


Solution

  • As explained (somewhat cryptically) in comments in the source code (available here) and stated (more explicitly) in this Stack Overflow answer that quotes them, "auto-printing" (which occurs, for example, with (list_obj <- lapply(tobacco[,c(1,3)], freq))) can only dispatch on explicit classes, and so won't work with a list. It will work with any call to print, though:

    devtools::install_github("dcomtois/summarytools", ref = "dev-current", quiet = TRUE)
    library(summarytools)
    # For best results, consider updating pander to its most recent version. You can do so
    # by using devtools::install_github('rapporter/pander')
    list_obj <- lapply(tobacco[,c(1,3)], freq)
    list_obj # will not work since it uses auto-printing
    # $gender
    # For best results printing list objects with summarytools, use view(x, method =
    # 'pander')
    # Frequencies   
    # tobacco$gender     
    # Type: Factor   
    # 
    #               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
    # ----------- ------ --------- -------------- --------- --------------
    #           F    489     50.00          50.00     48.90          48.90
    #           M    489     50.00         100.00     48.90          97.80
    #        <NA>     22                               2.20         100.00
    #       Total   1000    100.00         100.00    100.00         100.00
    # 
    # $age.gr
    # Frequencies   
    # tobacco$age.gr     
    # Type: Factor   
    # 
    #               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
    # ----------- ------ --------- -------------- --------- --------------
    #       18-34    258     26.46          26.46     25.80          25.80
    #       35-50    241     24.72          51.18     24.10          49.90
    #       51-70    317     32.51          83.69     31.70          81.60
    #        71 +    159     16.31         100.00     15.90          97.50
    #        <NA>     25                               2.50         100.00
    #       Total   1000    100.00         100.00    100.00         100.00
    
    print(list_obj) # will work
    # Frequencies   
    # tobacco$gender     
    # Type: Factor   
    # 
    #               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
    # ----------- ------ --------- -------------- --------- --------------
    #           F    489     50.00          50.00     48.90          48.90
    #           M    489     50.00         100.00     48.90          97.80
    #        <NA>     22                               2.20         100.00
    #       Total   1000    100.00         100.00    100.00         100.00
    #   
    # tobacco$age.gr    
    # Type: Factor   
    # 
    #               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
    # ----------- ------ --------- -------------- --------- --------------
    #       18-34    258     26.46          26.46     25.80          25.80
    #       35-50    241     24.72          51.18     24.10          49.90
    #       51-70    317     32.51          83.69     31.70          81.60
    #        71 +    159     16.31         100.00     15.90          97.50
    #        <NA>     25                               2.50         100.00
    #       Total   1000    100.00         100.00    100.00         100.00