Having multiple pander()s in a function - r

How do I create multiple outputs via pander() in a knitted document "asis" ?
When I have multiple calls of pander in a function, only the most recent one is shown in the HTML output. Here's an example:
tmp = function() {
pander('A')
pander('B')
pander('C')
}
tmp()
In the knitted document this gives: C
I could set panderOptions('knitr.auto.asis', FALSE) or I could use cat() so that the pander() output is written to the standard output. But then it's formatted as code, not as part of the document. As I need pander() to format a few tables for me, this does not help.

The tmp function will return only the last object -- that's why only C is printed. If you want to write each object to the stdout right away without the auto-asis convenience option, then you have to both disable the option like you did and use the relate knitr chunk option, eg:
```{r results='asis'}
library(pander)
panderOptions('knitr.auto.asis', FALSE)
tmp = function() {
pander('A')
pander('B')
pander('C')
}
tmp()
```
See more examples in the related "Using pander with knitr" vignette.

Related

Any way to set rmarkdown::paged_table() as the deafult way to printing table?

I have seen a tutorial by which one can change the way tables are printed to knitr::kable() format. Is it possible to do the same with the rmarkdown::paged_table() format, so that all tables by default will be printed in paged_table() format as in the {rmarkdown} package in R?
I had the same problem in Quarto and the solution is to use df-print: paged (note df-print not df_print) in the yaml file.
Eg.
---
title: "Untitled"
editor: visual
format:
html:
df-print: paged
---
```{r}
data.frame(
x = 1:10,
y = rnorm(10)
)
```
which results in this
In case of Rmarkdown the answer offered by #VishalKatti is IMHO the way to go. For Quarto (or RMarkdown), adapting the example in the R Markdown Cookbook one option to achieve your desired result may look like so:
---
title: Use a custom `knit_print` method to print data frames
format: html
---
First, we define a `knit_print` method, and register it:
```{r}
knit_print.data.frame = function(x, ...) {
res = rmarkdown::paged_table(x)
rmarkdown:::knit_print.data.frame(res)
}
registerS3method(
"knit_print", "data.frame", knit_print.data.frame,
envir = asNamespace("knitr")
)
```
Now we can test this custom printing method on data frames.
Note that you no longer need to call `rmarkdown::paged_table()`
explicitly.
```{r}
head(iris)
```
```{r}
head(mtcars)
```
Put this in the yaml.
output:
html_document:
df_print: paged
To complete the answer shared above, here are several ways to achieve this
Using a printing function for knitr
For paged table this would be this function: (which is used internally by rmarkdown for the df_print feature)
paged_print <- function(x, options) {
knitr::asis_output(
rmarkdown:::paged_table_html(x, options = attr(
x,
"options"
)),
meta = list(dependencies = rmarkdown::html_dependency_pagedtable())
)
}
This is similar to the function in the other answer, it is just that rmarkdown:::knit_print.data.frame does more than juts handling paged tables.
Then you could register it in a document so that it is applied by default for any data.frame printing.
registerS3method(
"knit_print", "data.frame", paged_print,
envir = asNamespace("knitr")
)
or use it on chunk basis where you need to print a data.frame in a single value chunk. (
```{r, render = paged_print}
iris
```
More on custom printing method for knitr its vignette
Using option hooks for knitr
A df_print chunk option can also be simulated this way using a option hook
knitr::opts_hooks$set(df_print = function(options) {
if (options$df_print == "paged") {
options$render = paged_print
}
options
})
this will allow something like
```{r, df_print = "paged"}
iris
```
```{r}
iris
```
First table will be shown as paged table
Second table will be show as usual data.frame

Is it possible to set chunk defaults only for a specific engine?

I am using SQL blocks in an RMarkdown document, and I want the echo option to default to FALSE for all of them – but only for sql blocks, not others.
I know I can set knitr::opts_chunk$set(echo = TRUE), but that would set it for all chunks.
As Yihui suggested in a comment, the proper way to do this is to use an option hook. The following sets echo=FALSE for sql chunks and echo=TRUE otherwise:
knitr::opts_hooks$set(echo = function(options) {
options$echo <- options$engine != "sql"
return(options)
})
I'll leave my original answer below … for entertainment. It's a workaround, required in a hypothetical parallel universe without option hooks.
You can query the current engine via opts_current$get("engine"). Based on this, you can use the following function (and extend it however you like) to determine the desired value for echo:
conditionalDefaut_echo <- function() {
return(opts_current$get("engine") != "sql")
}
The challenge is to evaluate this function whenever parsing a new chunk. This can be achieved with quote:
opts_chunk$set(echo = quote(conditionalDefaut_echo()))
To be honest, I am not sure how reliable this is – this kind of metaprogramming depends on the internal workings of knitr and might break in the future. (Maybe Yihui wants to comment on this …)
A full example with engines r and asis, where echo is FALSE for asis chunks and TRUE otherwise:
```{r}
library(knitr)
conditionalDefaut_echo <- function() {
return(opts_current$get("engine") != "asis")
}
opts_chunk$set(echo = quote(conditionalDefaut_echo()))
```
```{asis}
I'm invisible.
```
```{r}
print(1) # code visible
```

Change color of error messages in RMarkdown code output (HTML, PDF)

Is there a way to automatically make text color of errors red in R Markdown without manually editing the HTML later.
---
title: ""
---
#### Example 1
```{r e1, error = TRUE}
2 + "A"
```
#### Example 2
```{r e2, error = TRUE}
2 + 2
```
In the above code, output of Example 1 would have to be red. Currently, I edit the generated HTML (add style="color:red;" to the appropriate tag) but I am wondering if there is an automatic way. Assume that it is not known before knitting whether the code will generate error.
1. Use a knitr hook
The preferred solution is to use the output hook for errors:
```{r}
knitr::knit_hooks$set(error = function(x, options) {
paste0("<pre style=\"color: red;\"><code>", x, "</code></pre>")
})
```
Output hooks in general allow us to control the output of different parts of our R code (the whole chunk, the source code, errors, warnings, ...). For details check https://yihui.name/knitr/hooks/#output-hooks.
2. Quick and dirty solution using JS/jQuery
And this is my "quick and dirty" solution using jQuery/Javascript. Just add it beneath the YAML header.
Might not be bulletproof, since it checks for error messages using the string "Error" which might occur in other applications as well.
<script type="text/javascript">
$(document).ready(function() {
var $chks = $("pre:not(.r) > code");
$chks.each(function(key, val) {
cntnt = $(this).html();
if (cntnt.indexOf("Error") != -1) {
$(this).css('color', 'red');
}
})
})
</script>
I stumbled here because I had the same question but for PDF output rather than HTML.
It turns out combining #Martin Schmelzer's Solution with some hints from #Yihui Xie found here helps to achieve the same behavior in a PDF output.
Add \usepackage{xcolor} to your YAML header and the following chunk to your .Rmd file.
```{r}
color_block = function(color) {
function(x, options) sprintf('\\color{%s}\\begin{verbatim}%s\\end{verbatim}',
color, x)
}
knitr::knit_hooks$set(error = color_block('red'))
```
The result is red error messages like

How to syntax highlight inline R code in R Markdown?

This question is similar to consistent code html inline and in chunks with knitr. Instead of .Rhtml documents, I want to highlight inline R code in R Markdown documents, e.g., after `r "plot(cars, main = 'A scatterplot.')"` is compiled through rmarkdown, the tokens like plot should be highlighted. By default, R code chunks are syntax highlighted, but there is no way to highlight inline R code.
Here is one solution using the development version of the highr package (devtools::install_github('yihui/highr')). Basically you just define your custom LaTeX commands to highlight the tokens. highr:::cmd_pandoc_latex is a data frame of LaTeX commands that Pandoc uses to do syntax highlighting.
head(highr:::cmd_pandoc_latex)
## cmd1 cmd2
## COMMENT \\CommentTok{ }
## FUNCTION \\NormalTok{ }
## IF \\NormalTok{ }
## ELSE \\NormalTok{ }
## WHILE \\NormalTok{ }
## FOR \\NormalTok{ }
Then you can redefine the inline hook of knitr:
---
output:
pdf_document:
keep_tex: yes
---
```{r include=FALSE}
local({
hi_pandoc = function(code) {
if (knitr:::pandoc_to() != 'latex') return(code)
if (packageVersion('highr') < '0.6.1') stop('highr >= 0.6.1 is required')
res = highr::hi_latex(code, markup = highr:::cmd_pandoc_latex)
sprintf('\\texttt{%s}', res)
}
hook_inline = knitr::knit_hooks$get('inline')
knitr::knit_hooks$set(inline = function(x) {
if (is.character(x) && inherits(x, 'AsIs')) hi_pandoc(x) else hook_inline(x)
})
})
```
Test inline R code: `r I("plot(cars, main = 'A scatterplot.')")`.
Normal inline code `r pi`.
A code block:
```r
plot(cars, main = 'A scatterplot.')
1 + 2 # a comment
```
I used I() as a convenient marker to tell the character strings to be syntax highlighted from normal character strings. It is just an arbitrary choice. PDF output:
This is not a perfect solution, though. You will need to tweak it in some cases. For example, most special LaTeX characters are not escaped, such as ~. You may need to process the LaTeX code returned by hi_pandoc() by gsub().
Personally I find multiple colors in inline output distracting, so I would not syntax highlighting it, but this is entirely personal taste.
Now-a-days:
Here is some `plot(cars, main = 'A scatterplot.')`{.R} inline R code
Well, I don't know specifically about R and the way you're using it, but for most languages (pandoc uses the skylighting pkg to do this), you can do inline code blocks with the above syntax.

wrapping figure with latex environment in knitr/rmarkdown with hooks

I'd like to wrap figures created with knitr and rmarkdown in a "wrapfigure" environment using hooks. However, when running the minimal example below, the figure chunk only gets compiled into a markdown picture:
\begin{wrapfigure}{R}{0.3\textwidth}
![](test_files/figure-latex/unnamed-chunk-2-1.pdf)
\end{wrapfigure}
and not the expected:
\begin{wrapfigure}{R}{0.3\textwidth}
\includegraphics{test_files/figure-latex/unnamed-chunk-2-1.pdf}
\end{wrapfigure}
Minimal example:
---
header-includes:
- \usepackage{wrapfig}
output:
pdf_document:
keep_tex: TRUE
---
```{r}
library(knitr)
knit_hooks$set(wrapf = function(before, options, envir) {
if(before) {
"\\begin{wrapfigure}{R}{0.3\\textwidth}"
} else {
"\\end{wrapfigure}"
}
})
```
```{r, wrapf=TRUE}
library(ggplot2)
qplot(cars$speed, cars$dist)
```
pandoc is responsible for converting the markdown document to a TEX document. As pandoc doesn't touch between \begin{…} and \end{…} the markdown syntax for the image is not being converted to TEX syntax.
You could …
Hide the plot (fig.show = 'hide') and use something along the lines of cat("\includegraphics{figure/unnamed-chunk-2-1.pdf}").
Hide the plot as above and include some magic in the hook that saves the cat.
Write RNW instead of RMD if you want PDF output.
Here's an example for option 2:
knit_hooks$set(wrapf = function(before, options, envir) {
if(before) {
return("\\begin{wrapfigure}{R}{0.3\\textwidth}")
} else {
output <- vector(mode = "character", length = options$fig.num + 1)
for (i in 1:options$fig.num) {
output[i] <- sprintf("\\includegraphics{%s}", fig_path(number = i))
}
output[i+1] <- "\\end{wrapfigure}"
return(paste(output, collapse = ""))
}
})
This hook can be used with wrapf = TRUE and fig.show = "hide". (Moreover, you need to add \usepackage{graphics} to header-includes.)
But note that I would not do it! Too many things can go wrong in more complex settings. Think of cache, captions, labels, cache (again!) …
Therefore, if it is really necessary to control the typesetting of the PDF, I recommend writing RNW (option 3).

Resources