How to hide code in RMarkdown, with option to see it
Asked Answered
O

2

44

I'm writing an RMarkdown document in which I'd like to re-run some chunks (5 to 9). There's no need to display these chunks again, so I considered using

```{r echo=FALSE}

to make the rerun chunks invisible, as described in another stackoverflow question. This is fine, and outputs the desired results (improved fit of second iteration - see this solution implemented here).

In an ideal world, however, the code would be expandable so the user could see exactly what's going on if they want to for educational purposes and clarity (e.g. see link to Greasemonkey solution here) rather than hidden as in my second rpubs example. The solution may look something like this, but with a shorter surrounding box to avoid distraction:

for (i in 1:nrow(all.msim)){ # Loop creating aggregate values (to be repeated later)
  USd.agg[i,]   <- colSums(USd.cat * weights0[,i])
}

for (j in 1:nrow(all.msim)){
weights1[which(USd$age <= 30),j] <- all.msim[j,1] /USd.agg[j,1] 
weights1[which(USd$age >= 31 & USd$age <= 50),j] <- all.msim[j,2] /USd.agg[j,2] 
weights1[which(USd$age >= 51),j] <- all.msim[j,3] /USd.agg[j,3] ## 
}
# Aggregate the results for each zone
for (i in 1:nrow(all.msim)){
  USd.agg1[i,]   <- colSums(USd.cat * weights0[,i] * weights1[,i])
}
# Test results 
for (j in 1:nrow(all.msim)){
weights2[which(USd$sex == "m"),j] <- all.msim[j,4] /USd.agg1[j,4]  
weights2[which(USd$sex == "f"),j] <- all.msim[j,5] /USd.agg1[j,5] 
}

for (i in 1:nrow(all.msim)){
USd.agg2[i,]   <- colSums(USd.cat * weights0[,i] * weights1[,i] * weights2[,i])
}

for (j in 1:nrow(all.msim)){
weights3[which(USd$mode == "bicycle"),j] <- all.msim[j,6] /USd.agg2[j,6]  
weights3[which(USd$mode == "bus"),j] <- all.msim[j,7] /USd.agg2[j,7] 
weights3[which(USd$mode == "car.d"),j] <- all.msim[j,8] /USd.agg2[j,8]  
weights3[which(USd$mode == "car.p"),j] <- all.msim[j,9] /USd.agg2[j,9]
weights3[which(USd$mode == "walk"),j] <- all.msim[j,10] /USd.agg2[j,10]
}
weights4 <- weights0 * weights1 * weights2 * weights3
for (i in 1:nrow(all.msim)){
USd.agg3[i,]   <- colSums(USd.cat * weights4[,i])
}
# Test results 
plot(as.vector(as.matrix(all.msim)), as.vector(as.matrix(USd.agg3)),
     xlab = "Constraints", ylab = "Model output")
abline(a=0, b=1)
cor(as.vector(as.matrix(all.msim)), as.vector(as.matrix(USd.agg3)))
#rowSums(USd.agg3[,1:3]) # The total population modelled for each zone, constraint 1
#rowSums(USd.agg3[,4:5])
#rowSums(USd.agg3[,6:10])

I'm happy with the echo=F solution, but would be even happier with an expandable code snippet one.

Edit: all RPubs examples except the first have now been removed, to avoid clogging their excellent publication system with essentially the same document.

Orbicular answered 2/1, 2013 at 18:38 Comment(2)
Assuming you're outputting to HTML you can use javascript. jQuery, being a popular toolset would be good to learn. Here's an example: w3schools.com/jquery/jquery_hide_show.aspBullbat
That would do it - definitely seems worth learning. The only downside is that it involves delving into the bulky (600 line) html file: pastebin.com/WsLt1Hjx . Given the purpose of RMarkdown is to reduce code down to the bare minimum, was hoping to find a solution internal to RMarkdown. The other problem in this case is that rpubs does not seem to allow the html the Rmd file outputs to be edited directly.Orbicular
H
79

This has been made much easier with the rmarkdown package, which did not exist three years ago. Basically you just turn on "code folding": https://bookdown.org/yihui/rmarkdown/html-document.html#code-folding. You no longer have to write any JavaScript.

E.g.

---
title: "Habits"
output:
  html_document:
    code_folding: hide
---

Also see https://bookdown.org/yihui/rmarkdown-cookbook/fold-show.html for more control over which code blocks to be fold or unfold.

Hyaloplasm answered 4/4, 2016 at 16:30 Comment(5)
Although this technology wasn't available when the original Q&A were posted, it has now clearly become the best answer to the original question. Thanks, Yihui!Fund
from where can I get 2.0? install.packages("rmarkdown") installs 1.4. Any idea?Ballistics
This works for Slidy or ioslides output formats too?Chev
@Chev No, it doesn't.Hyaloplasm
@YihuiXie you think this would be nice?Chev
G
10

If you add an html tag before your code you can use CSS selectors to do clever things to bits of the output - markdown handily passes the HTML through:

<style>
div.hidecode + pre {display: none}
</style>

<div class="hidecode"></div>
```{r}
summary(cars)
```

Here my CSS style rule matches the first <pre> tag after a <div class=hidecode> and sets it to be invisible. Markdown writes the R chunk with two <pre> tags - one for the R and one for the output, and this CSS catches the first one.

Now you know how to match the code and output blocks in CSS, you can do all sorts of clever things with them in Javascript. You could put something in the <div class=hidecode> tag and add a click event that toggles the visibility:

<style>
div.hidecode + pre {display: none}
</style>
<script>
doclick=function(e){
e.nextSibling.nextSibling.style.display="block";
}
</script>

<div class="hidecode" onclick="doclick(this);">[Show Code]</div>
```{r}
summary(cars)
```

The next step in complexity is to make the action toggle, but then you might as well use jQuery and get real funky. Or use this simple method. Let's do it with a button, but you also need a div to get your hooks into the R command PRE block, and the traversal gets a bit complicated:

<style>
div.hideme + pre {display: none}
</style>
<script>
doclick=function(e){
code = e.parentNode.nextSibling.nextSibling.nextSibling.nextSibling
if(code.style.display=="block"){
 code.style.display='none';
 e.textContent="Show Code"
}else{
 code.style.display="block";
 e.textContent="Hide Code"
}
}
</script>

<button class="hidecode" onclick="doclick(this);">Show Code</button>
<div class="hideme"></div>
```{r}
summary(cars)
```

( Note: I thought you could wrap R chunks in <div> tags:

<div class="dosomething">
```{r}
summary(cars) 
``` 
</div>

but that fails - anyone know why?)

Guff answered 2/1, 2013 at 20:40 Comment(8)
Sounds great. Tried to make the hiding of the code toggle-able using <button>Toggle</button> described by Brandon: (<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script> <script> $(document).ready(function(){ $("button").click(function(){ $("p").toggle(); }); }); </script>) at beginning or .Rmd file. Unfortunately (due to my poor JS skills) this has just resulted in a one-way toggle to remove all paragraphs! rpubs.com/RobinLovelace/3384 . Guess: I need to replace "p" with something else, (tried "```{r} to no avail), right?Orbicular
You need to figure out CSS selectors to get from your button to the block that has the code in. In my example, the R code is in a PRE block that is the next thing after the DIV, so I use the + sign in CSS and some nextSibling calls. Install Firebug, learn a little JS and CSS. Actually I didn't think of using BUTTON tags...Guff
Note my selectors fail when you have multiple R lines each with their own output blocks. If you output more than one thing in a chunk it will only hide the first. Working on it...Guff
That's no big problem in my example: just comment out the commands that have output. You can suppress output in R too. So I've got the basic toggle sorted which is awesome: rpubs.com/RobinLovelace/3385 . Final problem is dead simple - set default toggle state to hidden. Sure there's a single argument that makes this possible, but cannot find it buried in the haystack that is a google search! google.co.uk/search?q=.toggle+default+hiddenOrbicular
Your new example works a treat. One quirk: it's default state is to show the code, even though the button's default state is "show": rpubs.com/RobinLovelace/3386Orbicular
Its very dependent on the exact output from the markdown to HTML process, and maybe that's different depending on your exact package version. Hard to tell without seeing your output.Guff
Raw markdown (.md) dropbox.com/s/rvum7l4viry69zq/microsimulation-eg-new-toggle.md and html dropbox.com/s/e3kl85linsbee2d/… files, if interested!Orbicular
I tried to use your example but the button doesn't do anything for me. Here I copied your css at the top of the document and put the html at the bottom: rpubs.com/stanstrup/47153 Any ideas? I have tried every fiddle with general hide/show feature for divs but nothing seems to work in the markdown.Valadez

© 2022 - 2024 — McMap. All rights reserved.