web-dev-qa-db-fra.com

Comment masquer le code dans RMarkdown, avec possibilité de le voir

J'écris un RMarkdown document dans lequel je voudrais relancer quelques morceaux (5 à 9). Il n'est pas nécessaire d'afficher à nouveau ces morceaux, j'ai donc envisagé d'utiliser

```{r echo=FALSE}

pour rendre les morceaux de réexécution invisibles, comme décrit dans un autre stackoverflow question . C'est très bien, et génère les résultats souhaités (ajustement amélioré de la deuxième itération - voir cette solution mise en œuvre ici ).

Dans un monde idéal, cependant, le code serait extensible afin que l'utilisateur puisse voir exactement ce qui se passe s'il le souhaite à des fins éducatives et de clarté (par exemple, voir le lien vers la solution Greasemonkey ici ) plutôt que caché comme dans mon deuxième exemple de rpubs. La solution peut ressembler à ceci, mais avec une boîte environnante plus courte pour éviter toute 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])

Je suis content du echo=F solution, mais serait encore plus heureux avec un extrait de code extensible.

Edit: tous les exemples RPubs sauf le premier ont maintenant été supprimés, pour éviter de colmater leur excellent système de publication avec essentiellement le même document.

30
RobinLovelace

Cela a été rendu beaucoup plus facile avec le paquet rmarkdown , qui n'existait pas il y a trois ans. Fondamentalement, vous activez simplement le "pliage de code": http://rmarkdown.rstudio.com/html_document_format.html#code_folding . Vous n'avez plus besoin d'écrire de JavaScript.

Par exemple.

---
title: "Habits"
output:
  html_document:
    code_folding: hide
---
43
Yihui Xie

Si vous ajoutez une balise html avant votre code, vous pouvez utiliser des sélecteurs CSS pour faire des choses intelligentes sur les bits de la sortie - le démarquage passe facilement le code HTML à travers:

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

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

Ici, ma règle de style CSS correspond à la première <pre> tag après un <div class=hidecode> et le rend invisible. Markdown écrit le bloc R avec deux <pre> tags - un pour le R et un pour la sortie, et ce CSS attrape le premier.

Maintenant que vous savez comment faire correspondre le code et les blocs de sortie en CSS, vous pouvez faire toutes sortes de choses intelligentes avec eux en Javascript. Vous pouvez mettre quelque chose dans le <div class=hidecode> tag et ajoutez un événement de clic qui bascule la visibilité:

<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)
```

La prochaine étape de la complexité consiste à basculer l'action, mais vous pourriez aussi bien utiliser jQuery et devenir vraiment génial. Ou utilisez cette méthode simple. Faisons-le avec un bouton, mais vous avez également besoin d'un div pour placer vos crochets dans le bloc PRE de la commande R, et la traversée devient un peu compliquée:

<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)
```

(Remarque: je pensais que vous pourriez envelopper des morceaux R dans <div> Mots clés:

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

mais cela échoue - quelqu'un sait pourquoi?)

9
Spacedman