I wrote a loop that made 10 graphs in R:
library(plotly)
for (i in 1:10)
{
d_i = data.frame(x = rnorm(100,100,100), y = rnorm(100,100,100))
title_i = paste0("title_",i)
p_i = plot_ly(data = d_i, x = ~x, y = ~y) %>% layout(title = title_i)
htmlwidgets::saveWidget(as_widget(p_i), paste0("plot_",i, ".html"))
}
I have this code (Input menu contents do not overflow row box in flexdashboard) that makes a dashboard in R:
---
title: "Test Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
```
Column {data-width=100}
-----------------------------------------------------------------------
### Window 1
```{r}
selectInput("project", label = NULL, choices = c("A","B","C","D"))
```
Column {data-width=400}
-----------------------------------------------------------------------
### Chart B
```{r}
renderPlot({
plot(rnorm(1000), type = "l", main = paste("Project:",input$project, " Data:", input$data))
})
```
I would like to adapt this code so that the drop down menu allows the user to load the previously created graph/html file (e.g. from "My Documents") that is being searched for. For example, if the user searches for "plot_7", then plot_7 is displayed.
I tried the following code:
---
title: "Test Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
```
Column {data-width=100}
-----------------------------------------------------------------------
### Window 1
```{r}
plots = rep("plot", 10)
i = seq(1:100)
choice = paste0(plots, "_",i)
selectInput("project", label = NULL, choices = choice)
```
Column {data-width=400}
-----------------------------------------------------------------------
### Chart B
```{r}
renderPlot({
<object class="one" type="text/html" data="plot_i.html"></object>
})
```
But this returns the following error:
Error: <text<:2:1 unexpected '<'
1: renderPlot({
2:<
^
Can someone please show me how I can fix this? And is it possible to do this WITHOUT shiny? (i.e. only in flexdashboard)
Thank you!
This answers your next question:
Just a question: In the first answer you provided, you were able to "type in" which plot you wanted to see. In the second answer, you can only "scroll". Is there a way to add the "type in" which plot you want to see for the second answer?
Short answer: yes
... and how to do that?
I actually tried to use selectize.js in an ironic full circle of sorts, but it didn't work out...violence was considered...but it's an inanimate object...so...ya, I lost by default
This uses the JS library/package (whatever they call it for that language) select2.
flexdashboard is SUPER FUN! It really didn't want me to add this library with JS (that would have been too easy, ya know? So this puppy had to get added to the YAML.
The YAML to make this work.
---
title: "Test Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
extra_dependencies: !expr list(htmltools::htmlDependency('select2.min.js', '1.0', src = list(href = 'https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist'), script='js/select2.min.js', all_files = FALSE, style = 'css/select2.min.css'))
---
By default, it will look like this.
I figured your very next question would be about appearance... so I jumped the gun.
As far as I understand it, (I'm new to select2), when widening the search box, you have to move the dropdown arrow, which accounts for the first 3 of the entries in this CSS.
The next two are for highlighting when you mouse over in the dropdown. By default, the previous selection is highlighted grey, and the currently hovered-over is highlighted light blue. I added these so that you could change the colors if you wanted to.
The final call in CSS is setting the font family. I chose the default family in Plotly (so they matched).
```{css}
.select2-container--default .select2-selection--single{
min-height: 40px;
padding: 6px 6px;
width: 175px;
position: relative;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
right: 0px;
width: 20px;
min-height: 34px; /* parent min-height, minus top padding 40 - 6 */
position: absolute;
}
.select2-dropdown { /* the chunk requires 'important' */
width: 175px !important; /* so they're the same width */
top: 50%;
padding: 6px; 12px;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #F5F0E3;
color: black; /* in dropdown, item hovered on bg and text */
} /* default is background-color: #5897fb; default blue */
.select2-container--default .select2-results__option--selected {
background-color: #fbfaf5;
color: black; /* in dropdown, PREVIOUS selection bg and text */
} /* default background-color: #ddd; yucky grey */
option {
font-family: verdana; /* to match plotly */
}
```
Creating the plot list, the dropdown, and rendering the plots in R code didn't change.
The JS didn't change that much.
/* doesn't catch that the first plot is default; set manually */
setTimeout(function(){
$('select').select2(); /* connect to the select2 library */
plt = document.querySelectorAll('div.plotly.html-widget');
for(i = 0; i < plt.length; i++) {
if(i === 0) {
plt[i].style.display = 'block';
} else {
plt[i].style.display = 'none';
}
}
}, 200) /* run once; allow for loading*/
/* goes with the dropdown; this shows/hides plots based on dropdown */
function getPlot(opt) {
plt = document.querySelectorAll('div.plotly.html-widget');
for(i = 0; i < plt.length; i++) { /* switched to plt from opt here */
opti = opt.options[i];
if(opti.selected) {
plt[i].style.display = 'block';
} else {
plt[i].style.display = 'none'
}
}
}
That all gives you this.
All the code altogether.
---
title: "Test Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
extra_dependencies: !expr list(htmltools::htmlDependency('select2.min.js', '1.0', src = list(href = 'https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist'), script='js/select2.min.js', all_files = FALSE, style = 'css/select2.min.css'))
---
```{r setup, include=FALSE}
library(flexdashboard)
library(plotly)
library(tidyverse)
library(htmltools)
library(shinyRPG) # devtools::install_github("RinteRface/shinyRPG")
plts <- vector(mode = "list") # store plot list
for (i in 1:10) {
d_i = data.frame(x = rnorm(100,100,100), y = rnorm(100,100,100))
title_i = paste0("title_",i)
plts[[i]] <- plot_ly( # make a list of objects; no .html
data = d_i, x = ~x, y = ~y, height = 400,
mode = "markers", type = "scatter") %>%
layout(title = title_i)
}
```
```{css}
.select2-container--default .select2-selection--single{ /* outer container of dropdown */
min-height: 40px;
padding: 6px 6px;
width: 175px;
position: relative;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
right: 0px;
width: 20px;
min-height: 34px; /* parent min-height, minus top padding 40 - 6 */
position: absolute;
}
.select2-dropdown { /* the chunk requires 'important' */
width: 175px !important; /* so they're the same width */
top: 50%;
padding: 6px; 12px;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #F5F0E3;
color: black; /* in dropdown, item hovered on bg and text */
} /* default is background-color: #5897fb; default blue */
.select2-container--default .select2-results__option--selected {
background-color: #fbfaf5;
color: black; /* in dropdown, PREVIOUS selection bg and text */
} /* default background-color: #ddd; yucky grey */
option {
font-family: verdana; /* to match plotly */
}
```
Column {data-width=100}
-----------------------------------------------------------------------
### Window 1 {data-height=500}
```{r makeGoodChoices}
opts <- choice <- paste0("plot_", 1:100) # this line replaces last 3 lines
namedChoices = setNames(opts, choice)
newInput <- rpgSelect( # <----- I'm new; the dropdown
"selectBox",
NULL,
namedChoices,
multiple = F)
newInput$children[[2]]$attribs$onchange <- "getPlot(this)"
newInput # add dropdown to webpage
```
<!--- make space between dropdown and plot --->
<div id="plots" style="margin-top:3rem; margin-bottom:3rem;">
```{r dynoPlots,results='asis'}
tagList(plts) # print every plot (so they're all in the HTML)
```
</div>
```{r giveItUp,results='asis',engine='js'}
/* doesn't catch that the first plot is default, set manually */
setTimeout(function(){
$('select').select2(); /* connect to the select2 library */
plt = document.querySelectorAll('div.plotly.html-widget');
for(i = 0; i < plt.length; i++) {
if(i === 0) {
plt[i].style.display = 'block';
} else {
plt[i].style.display = 'none';
}
}
}, 200) /* run once; allow for loading*/
/* goes with the dropdown; this shows/hides plots based on dropdown */
function getPlot(opt) {
plt = document.querySelectorAll('div.plotly.html-widget');
for(i = 0; i < plt.length; i++) { /* switched to plt from opt here */
opti = opt.options[i];
if(opti.selected) {
plt[i].style.display = 'block';
} else {
plt[i].style.display = 'none'
}
}
}
```
This isn't exactly what you're looking for. This doesn't import the file. I'm still going to try to figure that part out.
I'm still trying to make the external file call work. Right now, it just wasn't to give me the literal HTML. I've tried a few approaches. I'm sure it's being a pain because this is probably not a good way to do this. For example, each plot will bring in the full HTML, which means that if there were 100 plots, you've got the entire plotly.js 100 times. (Whoa!)
If you're set on using external files and planning on rendering them in RMD, especially when using Shiny, you may want to consider an approach that keeps them R objects, like Rda or RData. That will use a LOT less memory.
In this version, I've only created the plots as objects (not saved, external files).
This is modified from your question. It creates an object for each for iteration.
---
title: "Test Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(plotly)
library(tidyverse)
library(htmltools)
for (i in 1:10) {
d_i = data.frame(x = rnorm(100,100,100), y = rnorm(100,100,100))
title_i = paste0("title_",i)
# p_i = plot_ly(data = d_i, x = ~x, y = ~y) %>% layout(title = title_i)
assign(paste0("plot_", i, ".html"), # name them plot_1.html, plot_2.html and so on
plot_ly(data = d_i, x = ~x, y = ~y, height = 400) %>%
layout(title = title_i))
# not using right now!
# htmlwidgets::saveWidget(as_widget(p_i), paste0("plot_",i, ".html"))
}
# htmlwidgets::saveWidget(as_widget(plot_1.html), "plot_1.html") # created for testing
```
I've modified your called to selectInput, as well. I made this a named vector, so that you would have plot_1.html called when the user picked plot_1.
I've kept your code in there, so you can see what's changed.
```{r makeGoodChoices}
# plots = rep("plot", 10)
# i = seq(1:100)
# choice = paste0(plots, "_",i)
choice = paste0("plot_", 1:100) # this line replaces last 3 lines
opts <- paste0(choice, ".html")
namedChoices = setNames(opts, choice)
# selectInput("project", label = NULL, choices = choice) # originally
selectInput("project", label = NULL, choices = namedChoices)
```
Since this is an R object (not an external file), this is how you would call the plots from the dropdown.
```{r dynoPlots}
renderPlotly(get(input$project)) # show me!
```
The RMarkdown altogether
---
title: "Test Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(plotly)
library(tidyverse)
library(htmltools)
for (i in 1:10) {
d_i = data.frame(x = rnorm(100,100,100), y = rnorm(100,100,100))
title_i = paste0("title_",i)
# p_i = plot_ly(data = d_i, x = ~x, y = ~y) %>% layout(title = title_i)
assign(paste0("plot_", i, ".html"), # name them plot_1.html, plot_2.html and so on
plot_ly(data = d_i, x = ~x, y = ~y, height = 400) %>%
layout(title = title_i))
# not using right now!
# htmlwidgets::saveWidget(as_widget(p_i), paste0("plot_",i, ".html"))
}
# htmlwidgets::saveWidget(as_widget(plot_1.html), "plot_1.html") # created for testing
```
Column {data-width=100}
-----------------------------------------------------------------------
### Window 1 {data-height=500}
```{r makeGoodChoices}
# plots = rep("plot", 10)
# i = seq(1:100)
# choice = paste0(plots, "_",i)
choice = paste0("plot_", 1:100) # this line replaces last 3 lines
opts <- paste0(choice, ".html")
namedChoices = setNames(opts, choice)
# selectInput("project", label = NULL, choices = choice) # originally
selectInput("project", label = NULL, choices = namedChoices)
```
```{r dynoPlots}
renderPlotly(get(input$project)) # show me!
```
I decided to make this an entirely different answer because it really is a different question.
This is based on the assumption that you won't import external files. This does not use Shiny runtime, but does the same thing as above.
BTW, I didn't check if selectInput would work, I went with shinyRPG because I knew it would work.
Here's a summary of changes from the answer to your original question:
dropped shiny: runtime from YAML
dropped library(shiny)
added library(shinyRPG)
dropped plot names (they're in a list now)
added list to store plots; sent plots to list when created
dropped .html from dropdown option names (they can be anything you want now)
rpgSelect replaced selectInput
added JS to connect plots to the dropdown
Here's what the bare bones looks like (almost exactly the same)
All of the code to make this happen with notes in the code for explanation. If anything is unclear, let me know.
---
title: "Test Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
---
```{r setup, include=FALSE}
library(flexdashboard)
library(plotly)
library(tidyverse)
library(htmltools)
library(shinyRPG) # devtools::install_github("RinteRface/shinyRPG")
plts <- vector(mode = "list") # stores plots
for (i in 1:10) {
d_i = data.frame(x = rnorm(100,100,100), y = rnorm(100,100,100))
title_i = paste0("title_",i)
plts[[i]] <- plot_ly( # make a list of objects
data = d_i, x = ~x, y = ~y, height = 400,
mode = "markers", type = "scatter") %>%
layout(title = title_i)
}
```
Column {data-width=100}
-----------------------------------------------------------------------
### Window 1 {data-height=500}
```{r makeGoodChoices}
opts <- choice <- paste0("plot_", 1:100) # this line replaces last 3 lines
namedChoices = setNames(opts, choice)
newInput <- rpgSelect( # <----- I'm new; the drop down (used same args)
"selectBox",
NULL,
namedChoices,
multiple = F)
newInput$children[[2]]$attribs$onchange <- "getPlot(this)"
newInput # add dropdown to webpage
```
<!--- make space between dropdown and plot --->
<div id="plots" style="margin-top:3rem; margin-bottom:3rem;">
```{r dynoPlots,results='asis'}
tagList(plts) # print every plot (so they're all in the HTML)
```
</div>
```{r giveItUp,results='asis',engine='js'}
/* doesn't catch that the first plot is default, set manually */
setTimeout(function(){
plt = document.querySelectorAll('div.plotly.html-widget');
for(i = 0; i < plt.length; i++) {
if(i === 0) {
plt[i].style.display = 'block';
} else {
plt[i].style.display = 'none';
}
}
}, 200) /* run once; allow for loading*/
/* goes with the drop down; this shows/hides plots based on drop down */
function getPlot(opt) {
plt = document.querySelectorAll('div.plotly.html-widget');
for(i = 0; i < opt.length; i++) {
opti = opt.options[i];
if(opti.selected) {
plt[i].style.display = 'block';
} else {
plt[i].style.display = 'none'
}
}
}
```
Related
I am trying generating series of small plotly plots based on a group in a data.frame and then using plotly::subplot() to bind them together. I would like to then use a dropdown filter to only display some of the subplots.
So far (using the plotly docs https://plotly.com/r/map-subplots-and-small-multiples/ and this answer https://stackoverflow.com/a/66205810/1498485) I can create the plots and the buttons and show and hide the contents of the subplots.
But I cannot figure out how to hide/reset the axis so only the selected subplot is displayed. Below is a minimised example of what I am doing.
# create data
df <- expand.grid(group = LETTERS[1:4],
type = factor(c('high','med','low'), levels = c('high','med','low')),
date = seq(as.Date('2020-01-01'), Sys.Date(), 'month')) %>%
mutate(value = abs(rnorm(nrow(.)))) %>%
group_by(group)
# define plot function
create_plots <- function(dat){
legend <- unique(dat$group) == 'A'
plot_ly(dat, x = ~date) |>
add_lines(y = ~value, color = ~type, legendgroup = ~type, showlegend = legend) %>%
add_annotations(
text = ~unique(group),
x = 0.1,
y = 0.9,
yref = "paper",
xref = "paper",
xanchor = "middle",
yanchor = "top",
showarrow = FALSE,
font = list(size = 15)
)
}
# create buttons to filter by group (based on https://stackoverflow.com/a/66205810/1498485)
buttons <- LETTERS[1:4] |>
lapply(function(x){
list(label = x,
method = 'update',
args = list(list(
name = c('high', 'med', 'low'),
visible = unlist(Map(rep, x == LETTERS[1:4], each = 3))
)))
})
# generate subplots
df %>%
do(mafig = create_plots(.)) %>%
subplot(nrows = 2) %>%
layout(
updatemenus = list(
list(y = 0.8,
buttons = buttons))
)
Yes, but as far as I know, you'll have to go beyond the Plotly package. This solution uses the libraries htmltools and shinyRPG. (It is not a Shiny app!)
I don't think that shinyRPG is a cran package. (It wasn't when I obtained it.) To download this package use this.
devtools::install_github("RinteRface/shinyRPG")
I'm using this library to make the selection box. Instead of a dropdown, I used a multiple selection box (you can select one to many plots at the same time).
The first thing I did was comment out the layout options for the plots and assign them to an object.
# generate subplots
so <- df %>%
do(mafig = create_plots(.)) %>%
subplot(nrows = 2) #%>%
# layout(
# updatemenus = list(
# list(y = 0.8,
# buttons = buttons))
# )
The only other change I made to the original subplot object was to change the default height. I used this percentage because the selection box is given 15% of the space (width-wise).
so[["sizingPolicy"]][["defaultHeight"]] <- "80%"
Next is the selection box.
When it comes to the options, I have c(setNames(1:4, LETTERS[1:4])) This reflects as A, B, C, and D in the selection options, because you have that labeled on the graphs. You can change this to anything. The matching names have no bearing on connecting the selection to the plot. However, the values 1:4 do. If you change this, it will impact the selection success.
tagSel <- rpgSelect(
"selectBox",
"Selections:",
c(setNames(1:4, LETTERS[1:4])), # left is values, right is labels
multiple = T)
tagSel$attribs$class <- 'select'
tagSel$children[[2]]$attribs$class <- "mutli-select"
tagSel$children[[2]]$attribs$onchange <- "getOps(this)"
With browsable, I combined the selection box, the Javascript, and the JQuery that connects the selection with the plots visibility, some styling options, and the subplots.
If it seems like a lot, the vast majority is actually for beautification. (That's almost everything in the style tags.)
I added a lot of comments in the JS, but if something's unclear, let me know.
browsable(tagList(list(
tags$head(
tags$script(HTML("function getOps(sel) { /* activate select */
$plts = $('svg g.cartesianlayer').find('g.subplot'); /* find plots */
$labs = $('svg g.infolayer').find('g.annotation'); /* find plot labels */
$plts.addClass('plotter'); /* add opacity to plots */
$labs.addClass('plotter'); /* add opacity to subplot labels */
for(i = 0; i < sel.length; i++) { /* look through options */
opt = sel.options[i];
j = opt.value;
if ( opt.selected ) {
$plts.filter(':nth-child(' + j + ')').removeClass('plotter-inact');
$labs[i].firstChild.classList.remove('plotter-inact');
} else {
$plts.filter(':nth-child(' + j + ')').addClass('plotter-inact');
$labs[i].firstChild.classList.add('plotter-inact');
}
}
}")),
tags$style(".plotter {opacity: 1;}
.plotter-inact {opacity: 0;}
.select {
position: relative; width: 13ch;
border: 2px solid #003b70;
margin: 0 2px; cursor: pointer;
border-radius: 5px; font-size: 1.1em;
text-align: center; line-height: 1.25em;
}
#selectBox {
background-color: #003b70;
width: 10ch; text-align: center;
color: white; font-weight: bold;
line-height: 1.25em;
}
.yaLeft {
position: relative;
float: left; width: 85%;
height: 100vh;
}
.yaRight {
float: right; width: 15%;
}")),
div(div(class = "yaLeft", so),
div(class = "yaRight", tagSel)))))
I'm trying to present two pie plots, one beside another, in HTML report that I create using Rmarkdown.
The problem is, that the labels are being cut in the HTML file.
I know how to solve it when I save the ggarange object into file, but not here...
I also tried to use plot_grid instead, it didn't solve it.
Thank you!
My code:
piePlot <- function(table,title)
{
colnames(table) <- c("group","numOfSamples")
table <- table %>% mutate(per = percent(numOfSamples / sum(Info$numOfSamples)))
ggpie(table, "numOfSamples", fill = "group", color = "group",legend='none',
label = paste(table$group,table$per,"\n","(",table$numOfSamples,")"),
label.size=0.05,
palette = rainbow(length(table$group), s = 0.4)) + coord_polar(theta = "y", clip = "off") +
ggtitle(title) + theme(plot.title = element_text(hjust = 0.5))
}
fruits <- data.frame(c("Apples","Bannana","Orange","Grapes", "lemon", "cherry"),c(12,34,67,23,54,36))
vegetables <- data.frame(c("Onion","Garlic","Tomato","Potato","Carrot", "cucumber"),c(6,3,51,12,16,9))
fruitsPlot <- piePlot(fruits, "fruits")
vegPlot <- piePlot(vegetables, "vegetables")
final <- ggarrange(fruitsPlot, vegPlot)
rmarkdown::render(
input = "RMD_input.Rmd",
output_file = stringr::str_glue("htmloutput.html"),
output_format = "html_document",
params = list(final = final))
rmarkdown file:
---
title: "test0_analysis_run"
author: "Gil"
date: "6/19/2022"
params:
final: "no graph"
output: pdf_document
---
<style type="text/css">
.main-container {
max-width: 1800px;
margin-left: auto;
margin-right: auto;
}
</style>
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)```
## R Markdown
```{r echo=FALSE}
plot(final)```
And my results: (as you can see, the cherry label is being cut)
Happy Easter!
I wonder if there is any smart programming for looping value boxes (or even better: whole r-markdown-code) in R-flexdashboards using R-shiny.
My problem is:
I have data, which is updated every day.
Every day I can display several keyfigueres.
I do this with value-boxes, becaus it is very easy to add special colors for different treshholds.
I want to show the data of the last week (7-days), see image, widch show the data for 4 days:
Is there a possibility to loop my code day by day?
My executable code example is only for two days an the valuebox for date (1st column in the image):
---
title: "Test for Loop value boxes"
author: StatistiVolker
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
require(shiny)
require(flexdashboard)
require(tidyverse)
```
<!-- C19J_Summary.Rmd -->
Testcode
=======================================================================
Sidebar {.sidebar}
-----------------------------------------------------------------------
### Settings
```{r}
sliderInput("sliderSumDate",
"Datum",
min = as.Date("2020-03-01"), #min(C19JKInz()$datI),
max = Sys.Date()-1,
value = Sys.Date()-1,
animate = TRUE)
```
```{r}
# Date
selSumDate <- reactive({
input$sliderSumDate
})
```
<!-- Is it possible to loop this Code? -->
Row
-----------------------------------------------------------------------
<!-- actual day -->
### {.value-box}
```{r}
# Emit the download count
renderValueBox({
valueBox(format(as.Date(selSumDate()-0),"%d.%m.%Y (%a)"),
caption = "Datum",
# icon = "fa-calendar",
color = "cornflowerblue")
})
```
<!-- Next Code is almost the same as above, except one day earlier -->
<!-- Is it possible to loop this Code? -->
Row
-----------------------------------------------------------------------
<!-- day before -->
### {.value-box}
```{r}
# Emit the download count
renderValueBox({
valueBox(format(as.Date(selSumDate()-1),"%d.%m.%Y (%a)"),
caption = "Datum",
# icon = "fa-calendar",
color = "cornflowerblue")
})
```
Thank you for any idea to solve my problem.
PS: This was not useful, because it is not possible to control the colors for different treshholds
you have found an Easter egg:
---
title: "Test for Loop value boxes"
author: StatistiVolker
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
require(shiny)
require(flexdashboard)
require(tidyverse)
```
<!-- C19J_Summary.Rmd -->
# Sidebar {.sidebar data-width=350}
### Settings
```{r}
sliderInput("sliderSumDate",
"Datum",
min = as.Date("2020-03-01"), #min(C19JKInz()$datI),
max = Sys.Date()-1,
value = Sys.Date()-1,
animate = TRUE)
```
```{r}
# Date
selSumDate <- reactive({
input$sliderSumDate
})
```
<!-- Is it possible to loop this Code? -->
```{r}
myValueBox <- function(title, caption="", color="cornflowerblue", myicon="", fontsize="25px"){
div(
class = "value-box level3",
style = glue::glue(
'
background-color: #{color}#;
height: 106px;
width: 18%;
display: inline-block;
overflow: hidden;
word-break: keep-all;
text-overflow: ellipsis;
', .open = '#{', .close = '}#'
),
div(
class = "inner",
p(class = "value", title, style = glue::glue("font-size:{fontsize}")),
p(class = "caption", caption)
),
div(class = "icon", myicon)
)
}
```
Testcode
=======================================================================
<!-- actual day -->
```{r}
uiOutput("el")
```
```{r}
# Emit the download count
colors = c("#8b0000", "#000000", "#228b22", "#ffd700")
output$el <- renderUI({
lapply(0:-6, function(x) {
div(
myValueBox(format(as.Date(selSumDate()-x),"%d.%m.%Y (%a)"), "Datum", myicon = icon("calendar")),
myValueBox(sample(1000, 1), "Infizierte", color = sample(colors, 1)),
myValueBox(sample(1000, 1), "Aktiv erkrankt", color = sample(colors, 1)),
myValueBox(sample(1000, 1), "Genesene", color = sample(colors, 1)),
myValueBox(sample(1000, 1), "Verstorbene", color = sample(colors, 1))
)
})
})
```
Impossible to create what you want with original {flexdashboard} package, no way to control row/column layout automatically. However, we can create our own value box.
Works the best on bigger screens (> 1000px width), also works on mobile (<670px), different styles will apply on small screens. Medium screens (670-1000) may have some problems, try to change width: 18%; to a number you want.
overflow text due to screen size issues are trimmed off. Change the
fontsize argument may also help.
Bigger screen
Mobile
Following the conversation here, is there a way to organize the output dygraphs in a grid? To Have one or more graph in a row.
The code below would generate 4 dygraphs arranged vertically.
Is there a way to organize them in a 4x4 grid?
I tried using tags$div but it wraps all the graphs in one div.
Is there a way to apply a CSS property such as display: inline-block; to each dygraph widget? or any other better method?
```{r}
library(dygraphs)
library(htmltools)
makeGraphs = function(i){
dygraph(lungDeaths[, i], width = 300, height = 300, group = "lung-deaths")%>%
dyOptions(strokeWidth = 3) %>%
dyRangeSelector(height = 20)
}
lungDeaths <- cbind(mdeaths, fdeaths, ldeaths, mdeaths)
res <- lapply(1:4, makeGraphs )
htmltools::tagList(tags$div(res, style = "width: 620px; padding: 1em; border: solid; background-color:#e9e9e9"))
```
Current output screenshot:
I think I figured it out, not sure its the best solution, but adding a wrapper div with a display:inline-block; property seems to work quite well.
I just added this line to the function that generates each dygraph:
htmltools::tags$div(theGraph, style = "padding:10px; width: 250px; border: solid; background-color:#e9e9e9; display:inline-block;")
so the updated code looks like this:
```{r graphs}
library(dygraphs)
library(htmltools)
makeGraphs = function(i){
theGraph <- dygraph(lungDeaths[, i], width = 400, height = 300, group = "lung-deaths")%>%
dyOptions(strokeWidth = 3) %>%
dyRangeSelector(height = 20)
htmltools::tags$div(theGraph, style = "padding:10px; width: 450px; border: solid; background-color:#e9e9e9; display:inline-block;")
}
lungDeaths <- cbind(mdeaths, fdeaths, ldeaths, mdeaths)
res <- lapply(1:4, makeGraphs )
htmltools::tagList(res)
```
Output Screenshot:
I have an rmarkdownfile with a chunck that has a loop that creates many pages. Below is a toy example. See the "loop_chunk" code chunk. The "loop_chunk" has fig.width=9, fig.height=6, results="asis" and I am running into a problem where i need to reduce the size of a plot inside loop_chunk. All plots are 9x6 but I need to adjust one plot. I found the codee below: http://michaeljw.com/blog/post/subchunkify/
and I tried using it below but when you run the code you can see that there are 2 plots on pages 3 and 5 and there should not be. it is somehow not keeping the \newpages. There should be 1 plot on pages 2,3,4 and 5. There should only be 5 pages.
Any idea how to fix this?
---
title: "Untitled"
output: pdf_document
toc: yes
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE , comment = NA, message= FALSE, warning = TRUE)
subchunkify <- function(g, fig_height=7, fig_width=5) {
g_deparsed <- paste0(deparse(
function() {g}
), collapse = '')
sub_chunk <- paste0("
`","``{r sub_chunk_", floor(runif(1) * 10000), ", fig.height=", fig_height, ", fig.width=", fig_width, ", echo=FALSE}",
"\n(",
g_deparsed
, ")()",
"\n`","``
")
cat(knitr::knit(text = knitr::knit_expand(text = sub_chunk), quiet = TRUE))
}
data = data.frame(group= c("A","A"), value = c(1,3))
```
```{r loop_chunk, fig.width=9, fig.height=6, results="asis", message= FALSE, warning = FALSE}
for(i in 1:nrow(data)){
cat(paste0("\\newpage\n # Page ", i ," \n"))
plot(data$value[i])
cat("\n\n")
cat(paste0("\\newpage\n ## page with smaller plot \n\n"))
cat("Here is some text on this page for the smaller plot.")
cat("\n\n")
data2 = data.frame(x = 7, y = 900)
library(ggplot2)
myplot = ggplot(data2, aes(x = x, y = y ))+geom_point()
subchunkify(myplot , 4,4 )
# print(myplot) -> IS there a way to just reduce the height and width with print()?
cat("\n\n")
}
```
Using your subchunkify() function for the graphics::plot call outputs those plots to the intended pages. Replacing plot(data$value[i]) in your second chunk with
subchunkify(plot(data$value[i]), 5, 5)
outputs the 5 pages with plots as intended (where height & width are set to 5/can be edited to conditionally set dimensions for a specific plot).