I was wondering if it is possible to hide a graph with a button like you can do this with a code chunk using code-fold: true. Is there a similar way for graphs? Here is a reproducible example:
---
title: "How to hide graph by button"
format:
html:
code-fold: true
engine: knitr
---
Example code:
```{r}
library(ggplot2)
ggplot(mtcars, aes(x = qsec, y = mpg)) + geom_point()
```
Output:
As you can see you can use a button called "Code" to hide the code chunk. Is there a way to do this only for the graph in Quarto?
Using a little bit of javascript we can achieve this in Quarto.
---
title: "How to hide graph by button"
format:
html:
code-fold: true
include-after-body: graph_fold.html
engine: knitr
---
Example code:
```{r}
library(ggplot2)
ggplot(mtcars, aes(x = qsec, y = mpg)) + geom_point()
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point()
print("Its not a graph")
```
graph_fold.html
<script>
function graph_fold() {
cells = document.querySelectorAll(".cell:has(img)");
cells.forEach(cell => {
imgs = cell.querySelectorAll(".cell-output-display:has(p img)");
imgs.forEach(img => {
det = document.createElement("details");
sum = document.createElement("summary");
det.appendChild(sum);
det.children[0].innerText = "Graph";
img_clone = img.cloneNode(true);
det.appendChild(img_clone);
cell.replaceChild(det, img);
});
});
}
window.onload = graph_fold();
</script>
How do I tell to knitr to use theme_classic if I export my Rmd notebook to PDF and use dark_theme_gray from ggdark package if I export my Rmd notebook to HTML?
Try this. (Sorry. I had no ggdark installed. So I just used theme_gray for HTML output). knitr provides helper functions to check for is_html_output or is_latex_output.
---
title: "test"
output:
pdf_document: default
html_document: default
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Plot
```{r}
library(ggplot2)
p <- ggplot(mtcars, aes(hp, mpg)) +
geom_point()
if (knitr::is_html_output()) {
p + theme_gray()
} else if (knitr::is_latex_output()) {
p + theme_classic()
}
```
In the following RMarkdown, I would like to have each barplot print so that the text size and box width are the same in each plot, and the height adjusts accordingly.
What is happening is that in the plots with few bars the bars are extremely wide, and in the plots with many bars the bars are thin and the labels squished.
---
title: "chunk plot height"
number_sections: yes
output: html_notebook
---
# Load Libraries
\```{r}
library(tidyverse)
library(magrittr)
library(rmarkdown)
\```
# Set Knitr Options
\```{r}
knitr::opts_chunk$set(
echo=TRUE,
dpi=300,
fig.width=12
)
\```
# Plot
\```{r}
for (n in seq(10,50,10))
{
knitr::opts_chunk$set(out.height=n)
data = data.frame(
X=sapply(c(letters, LETTERS)[1:n], function(x) rep(x,3) %>% paste0(collapse=''), USE.NAMES = F),
Y=rnorm(n)
)
plt =
data %>%
ggplot(aes(x=X, y=Y)) +
geom_col(position=position_dodge(width=1, preserve='single')) +
coord_flip()
print(plt)
}
\```
Within Rstudio, I try to dynamically render plotly plots into an HTML report using knitr render from a .R source file. knitr renders the plotly plots as long as they are not within a lapply loop. But once I try to output them from within a lapply loop they are note rendered. I need to use a loop because I need to programatically build my HTML reports with various numbers of plots with various names.
Here is the command that I execute in the console to create the HTML report from my plotlytest.R source file :
render("plotlytest.R")
and here is my example source file called plotlytest.R :
#'---
#'author: "pokyah"
#'output:
#' html_document:
#' theme: flatly
#' toc: true
#' toc_depth: 6
#' toc_float:
#' collapsed: false
#' smooth_scroll: true
#'title: "Plotly test"
#'date: \`r format(Sys.Date(), " %d-%m-%Y")`\
#'---
#'
#
#+ ---------------------------------
#' ## Loading libraries
library(plotly)
library(ggplot2)
#+ ---------------------------------
#' ## plotly example
#+ plotly,echo=FALSE,warning=FALSE,message=FALSE,error=FALSE,results='asis', plotly=TRUE
mtcars.p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point() +
labs(colour = "Cylinders")
iris.p <- ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) + geom_point() +
labs(colour = "Cylinders")
myPlots.l <- list(mtcars.p, iris.p)
names(myPlots.l) <- c("mtcars", "iris")
printPlots <- function(p, plots){
cat("\n")
cat("###", names(plots[p]))
cat("\n")
ggplotly(plots[[p]]) # this is not rendered
cat("\n")
print (plots[[p]]) # this is rendered, but of course this is not an interactive plot
cat("\n")
}
cat("\n")
cat("## printing out of lapply -> plotly working")
cat("\n")
ggplotly(myPlots.l$mtcars) # this is rendered
cat("\n")
ggplotly(myPlots.l$iris) # this is also rendered
cat("\n")
cat("\n")
cat("## printing inside of lapply -> plotly not working")
cat("\n")
lapply(seq_along(myPlots.l), printPlots, myPlots.l )
The closer question to my problem is this one but I'm still stuck with this problem. Any idea how to solve this ?
here is my config :
R version 3.3.1 (2016-06-21)
Platform: x86_64-suse-linux-gnu (64-bit)
Running under: openSUSE Leap 42.2
Here's a solution. You need to call knit_print() on "ggplotly" object (it's an htmlwidget object).
htmlwidgets needs to be attached.
The only problem I couldn't resolve is ggplotly width/height: I have to explicit these values.
#'---
#'author: "pokyah"
#'output:
#' html_document:
#' theme: flatly
#' toc: true
#' toc_depth: 6
#' toc_float:
#' collapsed: false
#' smooth_scroll: true
#'title: "Plotly test"
#'date: \`r format(Sys.Date(), " %d-%m-%Y")`\
#'---
#'
#
#+ ---------------------------------
#' ## Loading libraries
library(plotly)
library(ggplot2)
library(htmlwidgets)
library(knitr)
#+ ---------------------------------
#' ## plotly example
#+ plotly,echo=FALSE,warning=FALSE,message=FALSE,error=FALSE,results='asis', plotly=TRUE
mtcars.p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point() +
labs(colour = "Cylinders")
iris.p <- ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) + geom_point() +
labs(colour = "Cylinders")
myPlots.l <- list(mtcars.p, iris.p)
names(myPlots.l) <- c("mtcars", "iris")
printPlots <- function(p, plots){
cat("\n")
cat("###", names(plots[p]))
cat("\n")
#ggplotly(plots[[p]]) # this is not rendered. Of course, no "print" method is called.
# This line only returns an htmlwidget object that is lost because inside a function.
cat(knit_print(ggplotly(plots[[p]], width = 672, height = 480))) # This works.
cat("\n")
print(plots[[p]]) # this is rendered, but of course this is not an interactive plot
cat("\n")
}
cat("\n")
cat("## printing out of lapply -> plotly working")
cat("\n")
ggplotly(myPlots.l$mtcars) # this is rendered
cat("\n")
ggplotly(myPlots.l$iris) # this is also rendered
cat("\n")
cat("\n")
cat("## printing inside of lapply -> plotly not working")
cat("\n")
lapply(seq_along(myPlots.l), printPlots, myPlots.l)
I don't think there is a function render within knitr. However, if you want to produce a document with a mix of HTML and standard R plots, you could use an RMarkdown document such as the one below. You could then knit this and it will produce the desired output.
Also, regarding why the plotly plots are not showing? You need to call print on them in order for them to show, since you are calling ggplotly within a function.
---
author: "pokyah"
output:
html_document:
theme: flatly
toc: true
toc_depth: 6
toc_float:
collapsed: false
smooth_scroll: true
title: "Plotly test"
date: \`r format(Sys.Date(), " %d-%m-%Y")`\
---
# ---------------------------------
#' ## Loading libraries
#+ ---------------------------------
#' ## plotly example
```{r}
library(plotly)
library(ggplot2)
mtcars.p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point() +
labs(colour = "Cylinders")
iris.p <- ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) + geom_point() +
labs(colour = "Cylinders")
myPlots.l <- list(mtcars.p, iris.p)
names(myPlots.l) <- c("mtcars", "iris")
printPlots <- function(p, plots){
cat("\n")
cat("###", names(plots[p]))
cat("\n")
print(ggplotly(plots[[p]])) # this is not rendered
cat("\n")
print (plots[[p]]) # this is rendered, but of course this is not an interactive plot
cat("\n")
}
cat("\n")
cat("## printing out of lapply -> plotly working")
cat("\n")
ggplotly(myPlots.l$mtcars) # this is rendered
cat("\n")
ggplotly(myPlots.l$iris) # this is also rendered
cat("\n")
cat("\n")
cat("## printing inside of lapply -> plotly not working")
cat("\n")
lapply(seq_along(myPlots.l), printPlots, myPlots.l )
```
I use the knitr::opts_chunk$set(fig.align = "center") at the beginning of the rmarkdown document to set the alignment of figures. When I output HTML files, the static figures are aligned to the center, but the HTML widgets, such as outputs from leaflet() and ggplotly() have the default alignment (to the left). Is there an option to force the HTML widgets to the center?
EDIT: example given below.
---
title: "test"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.align = "center")
library(ggplot2)
library(plotly)
```
```{r static plot}
# This is aligned to center
g <- ggplot(mtcars, aes(mpg, cyl)) +
geom_point()
g
```
```{r html widget}
# html output isn't aligned
p <- ggplotly(g)
p
```
You could resize the plot to the default width of the document and then use some CSS:
---
title: "Untitled"
output: html_document
---
<style>
/* resize the widget container */
.plotly {
width: 100% !important;
}
/* center the widget */
div.svg-container {
margin: auto !important;
}
</style>
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.align = "center")
library(ggplot2)
library(plotly)
```
```{r static plot}
# This is aligned to center
g <- ggplot(mtcars, aes(mpg, cyl)) +
geom_point()
g
```
```{r html widget}
p <- ggplotly(g, browser.fill = F) %>%
layout(autosize = F, width = '100%', height = '100%')
p
```