Combine storyboard and .no-mobile in flexdashboard? - r

In flexdashboard, it is easy to create a dashboard with a storyboard, see here:
https://rstudio.github.io/flexdashboard/articles/using.html#storyboards-1
Also, it is easy to have a specific output depending on mobile/not mobile;
https://pkgs.rstudio.com/flexdashboard/articles/using.html#mobile-css
But how can I combine the two? Whenever I do that, the mobile version is just shown either way, (with a blank page)
---
title: "Storyboard"
output:
flexdashboard::flex_dashboard:
storyboard: true
---
### Chart 1
```{r}
print("non-mobile")
```
### Chart 1 {.mobile}
```{r}
print("mobile")
```
Running the code just displays 2 tabs with the names Chart 1, Chart 1

You haven't respected the indented nature of additional specifications for the output in your YAML. It will not work with it.
---
title: "Test"
output:
flexdashboard::flex_dashboard:
storyboard: true
---
Update: This was not fun. However, it's pretty gratifying when I figure something like this out!
Alright, so here's the thing, the mobile version is listening, but the storyboard-not-so-mobile is ignoring you.
I did find comments in flexdashboard.js that mobility depends on whether or not the layout is set to fill. Storyboards are inherently more than one page, so they don't meet this requirement. So, I've made a workaround.
I want to caveat and state that I can't possibly envision the many ways you might label your ### sections, nor how flexdashboard will translate the nearly infinite possible labels. This code should work with any combination of letters, numbers, and spaces. It might require adjustments for ### with special characters.
For each of your sections (###) label it with either {.mobile} or {.no-mobile}. For availability in both, no label. (See my code to see what I mean. This is what you did.
For each R chunk's output options, add class="mobile" or class="no-mobile". Again, no class is needed when used in both. Make sure that the capitalization is uniform in these labels. Don't add white space around the = in the chunk options.
Along with the YAML in your questions:
### Let the charting begin {.no-mobile}
```{r showMePlease, class="no-mobile"}
plot(x = 1:100, y = 100:1)
```
### Chart 2 {.mobile}
```{r errrr, class="mobile"}
plot(x = 1, y = 3)
```
### Chart 3 {.mobile}
```{r meow,class="mobile"}
plot(x = 3, y = 3)
```
### Chart 4 {.no-mobile}
```{r pppplotttt, class="no-mobile"}
plot(x = 10, y = 30)
```
This next chunk can go anywhere in your RMD, but it needs to be there. If you try to run this chunk without knitting, it won't do anything. (Javascript only works when knit in RMD.)
```{r grrr,results="as-is",engine="js"}
grrr = document.body; // there is no DOM! (sigh)
setTimeout(function(){
gimme = grrr.querySelectorAll('div.mobile');
for(i = 0; i < gimme.length; i++) {
// with each of the elements, collect the id labels
// these labels match the storyboards
gId = gimme[i].getAttribute('id');
gId = gId.replace("-", " "); // all heading spaces get hyphens
// need to prepare for matching
// find the storyboards
showMe = grrr.querySelectorAll('ul > li');
for(j = 0; j < showMe.length; j++) {
//if the story board matches a mobile plot, get rid of it
if(showMe[j].textContent.toLowerCase() === gId) {
showMe[j].style.display = "none";
}
}
}
}, 100); //delay!!
```
Here are the storyboard and mobile versions.

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

How can I hide code blocks in xaringan presentation?

I'm running some plot code in markdown to generate a plot in a xaringan presentation. The code works but is a little long and so takes up the whole presentation slide forcing the actual plot off the edge (see img).
How can I hide the code block generating the plot?
Also how can I compress the code block with a scroll bar?
```{r}
r_exp.fun <- function(r = 0.05, N_pop = 10, t = 150)
{
N <- vector("numeric", length = t)
N[1] <- N_pop
for (i in 2:t)
{
N[i] <- N[i-1] + (N[i-1] * r)
}
return(N)
}
args_list <- list(0.045, 0.055, 0.06)
matplot(
mapply(
r_exp.fun,
r = args_list
)
,type = "l")
abline(h = list(7052, 29150, 59000))
```
The alternative is of course to save as an image but if possible I would prefer to be able keep the code as a resource for anyone with the link.
Thanks!
As alistaire already mentioned in the comments, RMarkdown has various chunk options to customize the output.
For your problem the option echo needs to be set to FALSE.
The other options (from https://rmarkdown.rstudio.com/lesson-3.html):
include = FALSE
prevents code and results from appearing in the finished file. R Markdown still runs the code in the chunk, and the results can be used by other chunks.
echo = FALSE
prevents code, but not the results from appearing in the finished file. This is a useful way to embed figures.
message = FALSE
prevents messages that are generated by code from appearing in the finished file.
warning = FALSE
prevents warnings that are generated by code from appearing in the finished.
fig.cap = "..."
adds a caption to graphical results.

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 write multi-level (bullet) lists in a table using rmarkdown and pandoc

I am looking to create a table in a PDF document using rmarkdown, knitr and pander. I am able to create a simple bullet list but now require another level in that list. In the table shown below, I require the "Rave reviews" bullet to be a sub-bullet of the "Offers workshops..." bullet.
The issue I'm having pertains to the line of code below in the mytable dataframe in the Description column. Although I attempt to create the 4 spaces required for a sub-bullet using \x20[1], those spaces do not appear - and hence no sub-bullets (although no error is shown). I also tried the most obvious way of simply adding in 4 spaces in the code to no avail. Also attempted to set my R options to include strip.white = FALSE, but that has also not proven helpful (see below).
---
title: "xxx"
author: "xxx"
output:
pdf_document:
fig_height: 4
fig_width: 10
highlight: tango
word_document: default
geometry: margin=3cm
---
```{r global_options, include=FALSE, echo=FALSE}
require(knitr)
opts_chunk$set(fig.width=8, fig.height=4, fig.path='figs/', dpi=500,
echo=FALSE, warning=FALSE, message=FALSE, results='hide', strip.white = FALSE)
```
```{r pandoc_options, include=FALSE, echo=FALSE}
require(pander)
panderOptions('digits', 3)
panderOptions('round', 3)
panderOptions('keep.trailing.zeros', TRUE)
panderOptions('keep.line.breaks', TRUE)
```
```{r concepts, echo=FALSE}
mytable = data.frame(
Concept = c("Decoded", "XXX"),
Description = c("* Founded in 2011\ \n* Offers workshops to take people from zero skills and knowledge in programming through to coding a multi-platform app using HTML, CSS and Javascript in a single day\ \n\x20\x20\x20\x20+ Rave reviews", "XXX"),
Website = c("http://decoded.com/uk/","XXX"))
```
``` {r concepts_descriptions, results = 'asis'}
pander::pander(mytable, keep.line.breaks = TRUE, style = 'grid', justify = 'left')
```
References
[1] I got the \x20 hint from here, after attempting \\s, \s, \ \s, \\\s, etc. to no avail (suggested here).
You can nest the items inside the bullet:
```{r concepts, echo=FALSE}
mytable = data.frame(
Concept = c("Decoded", "XXX"),
Description = c("* Founded in 2011\ \n
* Offers workshops to take people from zero skills and knowledge in programming through to coding a multi-platform app using HTML, CSS and Javascript in a single day\ \n
\\begin{itemize}
\\item Rave reviews \n
\\item e.t.c
\\end{itemize}", "XXX"),
Website = c("http://decoded.com/uk/","XXX"))
```
Edit: I didn't realize you were using a pdf, but here is an html solution
I would use a matrix
I would use the htmlTable package which allows for much more advanced tables than kable or pander
First make a wrapper for your lists
make_list <- function(...) {
paste0("<ul>", sprintf('<li>%s</li>', substitute(...())), '</ul>', collapse = '')
}
make_list(one, two, three)
# [1] "<ul><li>one</li></ul><ul><li>two</li></ul><ul><li>three</li></ul>"
library('htmlTable')
mytable <- matrix(c("Decoded", "XXX",
make_list('Founded in 2011', 'Offers workshops to take people from zero skills and knowledge in programming through to coding a multi-platform app using HTML, CSS and Javascript in a single day','Rave reviews'),
"XXX",
"http://decoded.com/uk/","XXX"), 2,
dimnames = list(NULL, c('Concept','Description','Website')))
htmlTable(mytable, align = 'lll')
This is fine but the vertical align is bad and the boxes are too wide. But we can fix with one of the css parameters of htmlTable. vertical align pushes the text to the top rather than center, max-width sets the text wrapping, and auto width lets each have its own width
htmlTable(mytable, align = 'lll', align.header = 'lll',
css.cell = "width: auto; max-width: 250px; vertical-align: top;")

set fig.cap to options$label

How can I programmatically set a figure caption in a knitr hook?
I'd like to set the figure caption, if not explicitly defined, to the chunk label. I've read the knitr docs on options, options, and hooks, and though I think I understand the mechanisms at play, I can't get it to work.
My use-case that perhaps justifies this behavior: my work-flow recently adapted to start my data and visualization exploration in Rmd files. I'll use chunks for cleaning, subsetting, etc, and then a sample chunk for each visualization. This is quick and dirty, meaning minimal markdown. When I look over the report (typically rendered into PDF), I'll look at a figure and want to go straight to the source for it. Though text before/after the figure can provide insight, due to LaTeX figure rules it is not a sure thing. Counting figure numbers is feasible, but not "easy" (and becomes problematic with many figures). Captions are always with the figure, so it'd be great if I can default to filling the caption with the chunk label. (Yes, it's a little lazy of me.)
The MWE is below.
The hook code ran just fine; the returned strings in the hook appeared correctly. However, the figure caption did not change. Exception: when there is a chunk with an undefined fig.cap, all subsequent chunks have their caption set to the first un-captioned chunk name; this doesn't surprise me due to the global nature of opts_chunk, so that's out.
I suspect it might be related to "output hooks" vice "chunk hooks," but this really is a per-chunk thing and I do not want to modify the plot, just set the caption.
MWE:
---
title: "Document Title"
author: "My Name"
output:
pdf_document:
fig_caption: yes
---
# Header
```{r setup}
knit_hooks$set(autocap = function(before, options, envir) {
if (before) {
if (is.null(options$fig.cap)) {
options$fig.cap <- options$label
knitr::opts_current$set(fig.cap = options$label)
knitr::opts_chunk$set(fig.cap = options$label) # wrong!
paste('Set: `', options$label, '`, `',
knitr::opts_current$get('fig.cap'), '`', sep = '')
} else {
paste('Kept: `', options$fig.cap, '`', sep = '')
}
}
})
opts_chunk$set(autocap = TRUE)
```
## No Plot
```{r textOnly}
1+1
```
## Caption Already Set
```{r someplot, fig.cap='someplot caption'}
plot(0)
```
## Caption Not Set
```{r anotherPlot}
plot(1)
```
Is it ok like this ? I simply modify the knitr internal function .img.cap function which can be found here.
```{r}
.img.cap = function(options) {
if(is.null(options$fig.cap)) options$label else options$fig.cap
}
assignInNamespace(".img.cap", .img.cap, ns="knitr")
```
Does it help ?
```{r}
library(knitr)
knit_hooks$set(htmlcap = function(before, options, envir) {
if(!before) {
caption <- ifelse(is.character(options$htmlcap), options$htmlcap, options$label)
paste('<p class="caption">', caption, "</p>", sep="")
}
})
```
```{r Hello, htmlcap=TRUE}
library(ggplot2)
ggplot(diamonds,aes(price,carat)) + geom_point()
```
```{r, htmlcap="Hello again"}
ggplot(diamonds,aes(price,carat)) + geom_point()
```

Resources