9
votes

I would like to set the "pander" function as an alternative "print" function for when compiling knitr rmarkdown documents. Like this (Example of code to run in R):

require(pander)
print <- function(...) pander(..., style = "rmarkdown") # makes sure that everyhing that everyprint will pass through pander
summary(cars)

This will result in:

> summary(cars)

----------------------------------
&nbsp;    speed          dist     
------ ------------ --------------
 ****  Min.  : 4.0   Min.  : 2.00 

 ****  1st Qu.:12.0 1st Qu.: 26.00

 ****  Median :15.0 Median : 36.00

 ****   Mean :15.4   Mean : 42.98 

 ****  3rd Qu.:19.0 3rd Qu.: 56.00

 ****  Max.  :25.0  Max.  :120.00 
----------------------------------

This way, I will get all of the tables well formatted, instead of manually needing to write "pander" all across the document (imagine I had to write "summary(car) 20 times in the document, changing "print" will save me writing pander(summary(car)) ).

Is that possible? (or is there a smarter way I'm unaware of?)

Thanks.

Update: example for an .rmd file:

TEST
====

```{r}

require(pander)
print <- function(...) pander(..., style = "rmarkdown") # makes sure that everyhing that everyprint will pass through pander

summary(cars)
```


```{r, eval=FALSE}
library(knitr)
knit2html("test.rmd") # http://stackoverflow.com/questions/10646665/how-to-convert-r-markdown-to-html-i-e-what-does-knit-html-do-in-rstudio-0-9
# http://quantifyingmemory.blogspot.co.il/2013/02/reproducible-research-with-r-knitr.html
```

While the output test.md is:

TEST
====




```r

require(pander)
print <- function(...) pander(..., style = "rmarkdown")  # makes sure that everyhing that everyprint will pass through pander

summary(cars)
```

```
##      speed           dist    
##  Min.   : 4.0   Min.   :  2  
##  1st Qu.:12.0   1st Qu.: 26  
##  Median :15.0   Median : 36  
##  Mean   :15.4   Mean   : 43  
##  3rd Qu.:19.0   3rd Qu.: 56  
##  Max.   :25.0   Max.   :120
```






```r
library(knitr)
knit2html("test.rmd")  # http://stackoverflow.com/questions/10646665/how-to-convert-r-markdown-to-html-i-e-what-does-knit-html-do-in-rstudio-0-9
#
# http://quantifyingmemory.blogspot.co.il/2013/02/reproducible-research-with-r-knitr.html
```
5
Yes, and it didn't work. The resulting .md file doesn't accept the change.Tal Galili
I think you need to expand on your problem, especially since "needing to write 'pander' all across the document" is a bit vague.Spacedman
What method is being called by the generic print function for the objects you are trying to print? If I type methods( print ) into a fresh R session 171 methods for print are available.Simon O'Hanlon
Spacedman and Simon, I've added an example. I hope this clarifies. And yes, I understand that print has MANY methods, but for a document with many tables, replacing it with "pander" would "do the trick" for me. (again, a smarter alternative would be better, if anyone has one to offer)Tal Galili
p.s: I don't understand the down-vote, I think this is a legitimate and useful question.Tal Galili

5 Answers

7
votes

You need to selectively overrule the print method for the object class you want to print with pander. Do methods(pander) to figure out what is available. Some methods are not exported, so you will have to use ::: to access them. Here is a simple example.

TEST
====

```{r cache = F, comment = NA}
print.lm <- pander:::pander.lm
lm(mpg ~ wt, data = mtcars)
```

Output

TEST
====


```r
print.lm <- pander:::pander.lm
lm(mpg ~ wt, data = mtcars)
```

```

--------------------------------------------------------------
           &nbsp;  Estimate   Std. Error   t value   Pr(>|t|) 
----------------- ---------- ------------ --------- ----------
  **(Intercept)**   37.29       1.878       19.86   8.242e-19 

           **wt**   -5.344      0.5591     -9.559   1.294e-10 
--------------------------------------------------------------

Table: Fitting linear model: mpg ~ wt
```
6
votes

For future readers -

Based on Ramnath answer, one can simply use:

require(pander)
print <- function (x, ...) UseMethod("pander")

Update: I've assembled a clear walk-through example, motivating the above question, in the following blog post - Write MS-Word document using R (with as little overhead as possible)

2
votes

I think a best option currently is to add opts_chunk$set(results="asis", render=pander). This will then render all your chunks using pander.

e.g.

```{r set_knitr_chunk_options, echo=FALSE, message=FALSE}
require(knitr)
require(pander)
opts_chunk$set(results = "asis", render=pander) # important for making sure the output will be well formatted.
```

```{r}
USJudgeRatings
```
1
votes

Another (current workaround) approach is to override the evaluate:::default_output_handler to panderize results that have a pander method, as discussed here:

https://github.com/yihui/knitr/issues/484#issuecomment-32705187

This approach, happily, does not require either 'needing to write "pander" all across the document' or 'selectively overrule the print method for the object class you want to print with pander'.

0
votes

I tried to minimise false positives and negatives building on @malcook's function.

False positives can be quite "costly": calling pander on ggplot2 objects and data.frame assignments, caused never-ending hangs without error messages, when called in knitr/rmarkdown. I put in a package.

```{r}
pander_handler = function(x, ..., row.names = FALSE, dont_transform = c("knit_asis")) {
    anyS3method = function(x) {
        classes = class(x)
        any(
            sapply(classes, FUN = function(classes) {
                !is.null(utils::getS3method('pander',classes, TRUE, environment(pander::pander)))
            })
        )
    }
    if (length(intersect(dont_transform, class(x))) == 0 && anyS3method(x)) {
        pander::pander(x, row.names = row.names, ...) # if pander has a method, we use it
    } else {
        res = withVisible(knitr::knit_print(x, ...))
        # indicate the htmlwidget result with a special class so we can attach
        # the figure caption to it later in wrap.knit_asis
        if (inherits(x, 'htmlwidget'))
            class(res$value) = c(class(res$value), 'knit_asis_htmlwidget')
        if (res$visible) res$value else invisible(res$value)
    }

}

opts_chunk$set(render = pander_handler)
```

```{r}
library(data.table)
library(pander)
library(knitr)
library(ggplot2)
qplot(1:2)
plot(1:2)
xtabs(~ mpg + cyl, data = mtcars)
table(mtcars$cyl)
"blabla"
```

```{r}
xy = data.frame(x = 1:2, y = 3:4)
xy
```


```{r}
xx = data.table(xy)
xx[, new := 3:4]
```

```{r}
pander(xtabs(~ y, data = xx), caption = "y")
```


```{r}
library(lme4)
summary(lmer(Reaction ~ Days + (Days | Subject), sleepstudy))
summary(lm(Reaction ~ Days, sleepstudy))
```