R Flexdashboard multiple plots sizing - r

I just recently upgraded to R version 4.1.1 (from 3.6.3) and I noticed the following weird behaviour of flexdashboard:
I have a dashboard, where I plot multiple ggplots on one page (this number changes, so i do this with a loop), similarly as in the reproducible example below.
---
title: "My Reproducible Example"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: scroll
---
```{r }
library(ggplot2)
data("mtcars")
plots <- list()
for (i in 1:(ncol(mtcars) - 1)){
plots[[i]] <- ggplot(data = mtcars) +
geom_point(aes_q(x = as.name(names(mtcars)[1]),
y = as.name(names(mtcars)[1+i])))
}
for (i in 1:length(plots)){
print(plots[[i]])
}
```
When I run this with version 3.6.3 all of these plots are the same size. However, when I run this with version 4.1.1, I get one big plot, then a small plot, a big plot and a small plot, etc.
Is it also possible to create identically sized plots with a loop like this with R version 4.1.1?

Related

How to display hundreds of plots neatly in Rmarkdown?

I have a loop code that generate 100 different plots from a subset of a data. The simplified version of the code is as follow:-
for (i in 1:100) {
df <- alldata[alldata$id==i,]
plot(df)
}
The problem is I need to use R markdown to display the results. However, in the above code, the 100 plots will be display one after another in long pages, which will be very untidy.
I would like to display one plot at a time, but allow the viewer to click on the 'next page' to see the next plot. Is it possible to do so in R markdown?
Thanks and sorry if my question is too easy, as I am completely new to this (first time coding).
You can try my approach. I used html_document and tabsets ... works fine for my needs.
---
title: "Plot in loops"
output: html_document
---
# Title {.tabset .tabset-fade}
```{r, results='asis'}
for (i in 1:100) {
df <- data.frame(
x = 1:100,
y = runif(100)
)
cat( paste('## title no.', i, '\n' ) )
plot(df)
cat('\n \n')
}
```

Synchronized interactivity between two R plots (plotly and leaflet)

I’d like to synchronize the interactivity of two R plots: a plotly plot and a leaflet map. The plotly plot graphs a time series for a specific location in the leaflet map. In other words, I’d like to select a location (or group of locations) in a map and see the corresponding selection in the ploty plot and vice versa select a time series in the plotly plot and see the corresponding marker in the map highlighted. So, in both directions.
The attached file (dataset1) is a R list that contains all data. Each element of the list is a dataset (time series) for each location. The linked variable for both plots is “Codi.Estació”.
I’ve tried the crosstalk package but the authors warn that “Crosstalk currently only works for linked brushing and filtering of views that show individual data points, not aggregate or summary views”. I’m not interested in an individual data point but a whole time series.
Could anyone help me how to handle that? Tips, examples, other packages (instead of leaflet) are welcome?
Thank you very much and have a nice summer,
Download the dataset: https://drive.google.com/file/d/1PkPm1ObcEer8Lne5vJMZR6MdFTONRSvY/view?usp=sharing
Download HTML output: https://drive.google.com/open?id=1YHko4V-iAUZqZr3wNC7zGEdrMhjmykSA
The code in R Markdown (*.Rmd) (to run in Rstudio):
---
title: "Piezometers La Bisbal del Penedès "
author: "J.M. Campanera"
output:
flexdashboard::flex_dashboard:
orientation: columns
social: menu
---
```{r setup, include = FALSE}
library(plotly)
library(leaflet)
library(flexdashboard)
load("dataset1.RData")
```
Column {data-width=700}
-----------------------------------------------------------------------
### Water depth
```{r echo=FALSE}
# Plot 1
p<-plot_ly()
for (i in 1:length(dataset1)) {
p<-add_trace(p,name=dataset1[[i]]$Codi.Estació[1],x=dataset1[[i]]$Data,y=dataset1[[i]]$Valor,mode = 'scatter',type="scatter")
}
p
```
Column {data-width=300}
-----------------------------------------------------------------------
### well locations
```{r echo=FALSE}
m <- leaflet()
m<-addTiles(m)
for (i in 1:length(dataset1)) {
m<-addCircleMarkers(m,lng=dataset1[[i]]$Longitud[1], lat=dataset1[[i]]$Latitud[1],label=dataset1[[i]]$Codi.Estació[1],labelOptions = labelOptions(noHide = T, textOnly = TRUE),popup=as.character(dataset1[[i]]$Fondària.Pou..m.[1]))
}
m
```
Finally I develop a solution:
1) Interactivity in Plotly plot and highlighting in the leaflet map:
I used the funtion "event_data(event=c("plotly_click"))" and I get the inspiration from
https://plot.ly/r/shinyapp-plotly-events/
2) Interactivity in Leaflet map and highlighting in the plotly plot:
I used the funtion "input$map_marker_click" and I get the inspiration from here: https://rstudio.github.io/leaflet/shiny.html
Thank you,

Shiny Parallel Coordinates with Brushing and Linking

I'm creating a flexdashboard / Shiny app in R using Rstudio and am trying to create a dashboard with two components: a parallel coordinates graph on top and a table below the graph.
I'm trying to use Brushing and Linking to select specific axis in the parallel coordinate graph to affect and filter data in the table.
Below is my code (adapted from https://jjallaire.shinyapps.io/shiny-ggplot2-brushing/):
---
title: "ggplot2 Brushing"
output:
flexdashboard::flex_dashboard:
orientation: columns
social: menu
source_code: embed
runtime: shiny
---
```{r global, include=FALSE}
# load data in 'global' chunk so it can be shared by all users of the dashboard
library(datasets)
mtcars2 <- mtcars[, c("mpg", "cyl", "wt")]
```
```{r}
# Reactive that returns the whole dataset if there is no brush
selectedData <- reactive({
data <- brushedPoints(mtcars2, input$plot1_brush)
if (nrow(data) == 0)
data <- mtcars2
data
})
```
Column {data-width=650}
-----------------------------------------------------------------------
### Miles Per Gallon vs. Weight {data-width=600}
```{r}
library(ggplot2)
library(GGally)
plotOutput("plot1", brush = brushOpts(id = "plot1_brush"))
output$plot1 <- renderPlot({
ggparcoord(mtcars2) + geom_line()
})
```
### Car Details {data-width=400}
```{r}
renderTable({
selectedData()
}, rownames = TRUE)
```
As you can see, brushing and linking are not working. What am I missing here? I've read a few questions about the topic and particularly around XY variables and only working for scatterplots, etc. But certainly there is a way around this and I can't seem to find a solution. Does anybody have an idea on how to make brushing and linking work with parallel coordinates in Shiny?
I have tried to find solution to Your problem but actually it is not possible at this moment to retrieve the data using brush from any parallel coordinates plot (neither plotly or ggplot2). You can easily use the brush in plotly, but You will not be able to get the data out of it (in Your case it is selectedData()). Maybe You should try another plot type.

tableGrob alignment and spacing in Rmarkdown/knitr-HTML document

I have the following issues when using the nice feature tableGrob() from gridExtra package to plot a table in an html document produced by Rmarkdown and knitr.
Here is a reproducible example:
library(datasets)
library(dplyr)
mtcars$cyl <- as.factor(mtcars$carb)
carb.mpg <- mtcars %>%
select(carb,mpg) %>%
group_by(carb) %>%
summarise_each(funs(sum(.,na.rm=TRUE)),-carb) %>%
arrange(desc(mpg))
##plot the table
tab <- tableGrob(carb.mpg, cols=c("carb","mpg"),
theme=ttheme_minimal())
grid.arrange(tab, top=textGrob("Cars MPG per CARB",gp=gpar(fontsize=16,font=1)) )
For knitr general chunk options:
title: "Test with cars"
output:
html_document:
keep_md: true
{r setoptions, echo=FALSE}
library(knitr)
opts_chunk$set(message=FALSE,warning=FALSE)
The issue as can been seen from the attached snapshot is the huge space between the table and its title and legend. It would be also nice if I could left-align the table in the document.
Any help would be much appreciated.
you could try this
tg <- textGrob("Cars MPG per CARB", gp=gpar(fontsize=16,font=1))
grid.arrange(tg, tab, heights=unit.c(grobHeight(tg), sum(tab$heights)),
vp=viewport(x=unit(0,"npc") +
0.5*unit.pmax(grobWidth(tg),
sum(tab$widths))))
After some tweaking, I found that the position of the table can be controlled using viewport (x and y); width/height seem obsolete.
#plot the table
tab <- tableGrob(carb.mpg, cols=c("carb","mpg"),
theme=ttheme_minimal())
grid.newpage()
vp <- viewport(width=0.90,height=0.90,x=0.10,y=0.80,clip="on")
pushViewport(vp)
grid.draw(tab)
This solves the problem only partially: the huge vertical space is still there.
Perhaps this gives some direction to resolving the issue?
EDIT: one way that worked for me to control the white spaces/margins was to reduce the figure size parameters in knitr chunk options, i.e.,
{r plot mpg cars, fig.height=value, fig.width=value}

Controlling the size and number of graphs per pdf page generated by ggplot loop in R markdown

I would like to generate a pdf document, using R markdown, to display a series of plots made using ggplot in a for loop. Is it possible to control number of plots on each page so there is, for example, a 2 X 2 grid of plots per page?
I'd like to maintain the flexibility so that I can change the total number of graphs, so that it splits across the appropriate number of pages.
My attempt using ggplot2 and gridExtra packages is below, but I can't control the number of graphs per page, it seems to want to squeeze them on to a sinlge page only. I've tried changing the ncol,nrow,heights,widths arguments in grid.arrange but it doesn't seem to help.
---
title: "ggplot Layout"
output: pdf_document
---
```{r,figure2 fig.height=8, fig.width=6,echo=FALSE,message=FALSE}
library(ggplot2)
library(gridExtra)
graphlist<-list()
count <- 1
colnums<-c(1,5,6,7,8,9,10)
for (i in colnums) {
plot.x.name<-names(diamonds[i])
p <- ggplot(data=diamonds,aes_string(x = plot.x.name)) + geom_histogram()
graphlist[[count]]<-p
count <- count+1
}
do.call("grid.arrange",c(graphlist,ncol=2))
```
The type of thing I'm looking for is demonstrated by this code (adapted from
http://kbroman.github.io/knitr_knutshell/pages/figs_tables.html), but this doesn't work with ggplot, unfortunately.
---
title: "Example Layout"
output: pdf_document
---
```{r bunch_o_figs,fig.height=8, fig.width=6, message=FALSE,echo=FALSE}
n <- 100
x <- rnorm(n)
par(mfrow=c(2,2), las=1)
for(i in 1:20) {
y <- i*x + rnorm(n)
plot(x, y, main=i)
}
``
You could try marrangeGrob
---
title: "ggplot Layout"
output: pdf_document
---
```{r figure2 , fig.height=8, fig.width=6,echo=FALSE,message=FALSE}
library(ggplot2)
library(gridExtra)
graphlist <- replicate(10, qplot(1,1), simplify = FALSE)
do.call("marrangeGrob",c(graphlist,ncol=2,nrow=2))
```

Resources