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.
Related
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.
I have a R Markdown child-file, which should produce different output based on a R-condition .
My code (sorry it is not reproducible):
{r results='asis', echo = FALSE}
if (class(robject) == "character") {
cat("**R object is empty!**") # This text should appear in RED in the Output (HTML) file.
} else {
cat("### Data columns\n")
cat("\n")
kable(robject)
cat("\n")
}
What the code does:
If my robject is not a data.frame it is set to an empty string (robject <- ""). With this "trick" it is possible to if_else about robject.
In my R Markdown file it should be printed either "R object is empty!" or a summary of the dataset (which is a data.frame again). If the dataset is empty, the text should appear in RED!
Two questions:
How to print the text in RED (or every other color) using the cat command as in the example above?
(I tried text_spec from kableextra as mentioned here, I tried crayron-Package as well and I tried to enter html_tags with print/cat . Neither worked!)
Maybe it is better to if else outside the R Chunk. Unfortunately this approach did not work either enter link description here
Thank you for any help.
If you need some further information, please ask me for it. Thanks!
For HTML you can wrap the text in <span> and use CSS to set the color. If you need to do this more than a couple of times, you can wrap it up in a simple function.
```{r results='asis', echo = FALSE}
cat_color <- function(message, color = "black") cat(sprintf("<span style = \"color: %s;\">%s</span>\n\n", color, message))
robject <- "some text"
if (class(robject) == "character") {
cat_color("**R object is empty!**" , "red") # This text should appear in RED in the Output (HTML) file.
} else {
cat("### Data columns\n")
cat("\n")
kable(robject)
cat("\n")
}
```
I'm using knitr to knit RMarkdown, and there have been multiple times where I have wanted to add code chunks programmatically, but failed to find a way to do so satisfactorily. Say I want to have knitr play a sound when a file has finished knitting. My way around this problem has been like so:
beep_on_knit <- function(beep_sound=3, sleep=3) {
library(beepr)
last_label <- tail(knitr::all_labels(),n=1)[[1]]
knitr::knit_hooks$set(
.beep_on_last_chunk =
function(before, options) {
if (options$label == last_label & !before) {
beepr::beep(beep_sound)
Sys.sleep(sleep)
invisible(NULL)
}
})
# Sets the options for every chunk so the hook will be run on them
knitr::opts_chunk$set(.beep_on_last_chunk = TRUE)
}
However, having to edit the chunk properties of every single chunk (i.e., knitr::opts_chunk$set(.beep_on_last_chunk = TRUE) means that if I add this function to a document, it invalidates the cache of every previously cached chunk.
Is there a way to set the options of a specific chunk beforehand?
I don't know why you need to set knitr::opts_chunk$set(.beep_on_last_chunk = TRUE) globally for the document. Is it possible for you to set .beep_on_last_chunk = TRUE only on the last chunk as a local chunk option? If this is possible, you won't need to test if (options$label == last_label) in the hook.
Alternatively, you may consider using the document hook, which is executed after the whole document has been knitted, e.g.,
knitr::knit_hooks$set(document = function(x) {
beepr::beep(3)
x
})
So I'm trying to write an html R markdown document with interactive shiny bits that allow the user to edit a graph and then download the results to a pdf. However, there is something catastrophically wrong with the way that I'm trying to do this because as soon as the html starts, it overwrites the original markdown file with the contents of the pdf - turning it into complete gibberish right in the editor.
I doubt that I've found a completely new way to fail at R but I haven't been able to find where anybody else has had this issue. Additionally, I've looked over the shiny reference material and I'm just going in circles at this point, so any help would be greatly appreciated.
I'm using Rstudio 1.0.44, rmarkdown 1.2 and shiny 0.14.2. A small (not)working example:
---
title: "Minimum Failing Example"
author: "wittyalias"
date: "December 5, 2016"
output: html_document
runtime: shiny
---
```{r echo = FALSE}
library(ggplot2)
today <- Sys.Date()
inputPanel(downloadButton("dnld", label = "Download pdf"))
renderPlot({
# Example code from http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)/
p1 <<- ggplot(ChickWeight, aes(x=Time, y=weight, colour=Diet, group=Chick)) +
geom_line() +
ggtitle("Growth curve for individual chicks")
p1
})
reactive({
fname <- paste0("Chick Weight - ", today, ".pdf")
output$dnld <- downloadHandler(filename = fname,
content = makethepdf(file))
makethepdf <- function(fname) {
pdf(fname,
width = 14,
height = 8.5)
p1
dev.off()
}
})
```
EDIT: To be clear: I want the user to be able to download multiple pages of graphs, some of which will have different formatting. The user won't be downloading just a pdf version of the markdown document.
This happens because reasons I weren't able to identify makethepdf runs with the file = [name of the file]. Insert a print(fname) to see. The download handler isn't supposed to be inside an observer though. You need to have it outside on its own. I also failed to make pdf() dev.off() combination work for some reason so here's a working version below.
output$dnld = downloadHandler(filename = paste0("Chick Weight - ", today, ".pdf"),
content = function(file){
ggsave(file, plot = p1, width = 14, height = 8.5)
})
Use tempfile() and tempdir() to create a temporary file:
output$downloadReport = downloadHandler(
filename = function() {
normalizePath(tempfile("report_", fileext = ".docx"), winslash = "/")
},
content = function(file) {
out = rmarkdown::render("./report.Rmd",
output_file = file,
output_dir = tempdir(),
output_format = "pdf_document",
intermediates_dir = tempdir(),
envir = new.env(),
params = list( fontSize = 10)
)
})
I usually use a separate .Rmd template for my downloaded reports as the layout and text are usually similar but not identical to what works in an app.
I also find using parameters is a convenient way to pass input settings from my app to my report. See this RStudio post for details
Alright, so there are a number of problems with my code, but using some of the suggestions in the other answers I've been able to work it out.
The primary problem with this little document is that content in the downloadHandler is a function, but in my code I set content equal to the result of a function call. It looks like when the shiny app is first run it compiles content, thinking that it is a function, but actually ends up calling the function. It sends file as an arguement, which doesn't seem to exist except as a base function. Calling makethepdf with just file throws an error when I use it in the console, but for whatever reason in this app it just goes with the call, apparently with file = [name of the .Rmd] (just as OganM said).
To fix, change this:
output$dnld <- downloadHandler(filename = fname,
content = makethepdf(file))
to
output$dnld <- downloadHandler(filename = fname,
content = makethepdf)
To be clear: this code does not overwrite the .Rmd file if content calls makethepdf with any argument other than file. For instance, content = makethepdf(fnm)) causes the download button to display an object not found error and content = makethepdf(fname)) causes the download button to throw an attempt to apply non-function error when pressed.
Knitr has a rather neat animation feature which can produce animations in Markdown and HTML via FFMPEG and WebM, and in PDF using the animate LaTeX package. However, support for PDFs for the later is limited to Adobe Reader (and possibly PDF XChangeViewer). I'm thinking of implementing my own animation functionality which would produce an MP4 video from a series of plots and use the LaTeX package media9 to embed the video. This has wider support, including by Okular and at least one iOS PDF reader. Is there another way to do this that's already out there either within knitr or in another package? It seems it would have general applicability if implemented well.
Note I've posted a worked example of animation using rgl as an answer to this question. It works fine in Adobe Reader but relies on scripting support.
I've got something working that converts a series of pngs to mp4 and then embeds it using the media9 package. It plays back fine in Adobe Reader on Windows, but for some reason doesn't work on Okular running on Linux Mate. Having said that, nor do any other pdfs I've tried with embedded movies, so it seems to be an issue on the reader side.
Here's the .Rnw:
\documentclass{article}
\usepackage{media9}
\usepackage{graphicx, xcolor}
<< label = setup, include = FALSE>>=
library("rgl")
library("car")
library("knitr")
hook_rgl_spin_mp4 <- function(before, options, envir) {
if (!before) {
par3d(windowRect = 100 + options$dpi *
c(0, 0, options$fig.width,
options$fig.height))
if (!is.null(options$spin3d.axis)) {
spin3d.axis <- options$spin3d.axis
} else {
spin3d.axis <- c(0, 0, 1)
}
if (!is.null(options$spin3d.rpm)) {
spin3d.rpm <- options$spin3d.rpm
} else {
spin3d.rpm <- c(0, 0, 1)
}
spinFunc <- spin3d(axis = spin3d.axis, rpm = spin3d.rpm)
for(i in 1:options$fig.num) {
par3d(spinFunc(i * options$interval))
Sys.sleep(0.05)
rgl.snapshot(fig_path(".png", number = i), fmt = "png")
}
system(paste0('ffmpeg -y -r 10 -i "', sub("-1\\.", "-%d\\.", fig_path(".png", number = 1)),
'" -pix_fmt yuv420p "', vid_path <- fig_path(".mp4", number = 1), '"'))
options$fig.num <- 0
options$fig.show <- "hide"
paste0("\\includemedia[width=", options$out.width, ",height=", options$out.height,
",activate=pageopen,addresource=",
vid_path, ",flashvars={source=", vid_path, "}]{}{VPlayer.swf}")
}
}
knit_hooks$set(rgl = hook_rgl_spin_mp4)
#
\begin{document}
<< label=rgl1, rgl=TRUE, fig.show='animate', fig.width=5, fig.height=5, out.width='.6\\linewidth', out.height='.6\\linewidth', dev='png', fig.num = 40, interval=0.1, spin3d.axis=c(0, 0, 1), spin3d.rpm=20, results='asis'>>=
scatter3d(prestige ~ income + education, data=Duncan)
#
\end{document}
Note it has to have the results='asis' to work, but otherwise everything is done in the hook.