i am new to R and recently started working on a Shiny App. While I've managed to fix most of the problems in the project, I've been struggling with a menu issue for a while. Specifically, over the two inputs that I want to use I want to plot an image that depends on the first input (selectInput). I do this through a renderImage function, but the problem is that when plotting these images a space is generated that I cannot eliminate. I have tried using renderPlot and renderText, but the problem is not solved or they do not give the desired results. Is there a way to eliminate or reduce this space? I am attaching a simplified version of my code and an image of the problem.
---
title: "TEST"
output:
flexdashboard::flex_dashboard:
orientation: rows
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r paquetes, include=FALSE}
{
library(data.table)
library(dplyr)
library(plyr)
library(highcharter)
library(flextable)
library(officer)
library(readxl)
library(gridExtra)
library(plotly)
library(ggrepel)
library(kableExtra)
library(knitr)
library(scales)
library(flexdashboard)
}
```
Sidebar {.sidebar data-width=300}
=====================================
<center>
```{r echo = FALSE}
renderImage({
filename <- paste0("images/",input$countryInput,".png")
list(src = filename, height = 100)
})
```
</center>
```{r input01, echo=FALSE}
selectInput("countryInput", "REGIÓN",
choices = c("NACIONAL","XV ARICA Y PARINACOTA","I TARAPACÁ","II ANTOFAGASTA",
"III ATACAMA","IV COQUIMBO","V VALPARAÍSO","XIII METROPOLITANA",
"VI O´HIGGINS","VII MAULE","XVI ÑUBLE","VIII BÍO BÍO",
"IX ARAUCANÍA","XIV LOS RÍOS","X LOS LAGOS","XI AYSÉN","XII MAGALLANES"))
```
```{r input02, echo=FALSE}
dateRangeInput("dateInput", "TRIMESTRES",
language = "es",
format = "yyyy/mm/dd",
min = as.Date("2018-01-01"),
max = as.Date("2020-07-01"),
start = as.Date("2019-07-01"),
end = as.Date("2020-07-01"),
separator = "hasta")
```
Página
====================================
Row
-----------------------------
###
Problem photo
This is my first post on the forum, so any help is appreciated and I apologize in case I forgot to add information.
Use imageOutput to control the height of the div containing the image:
output[["image"]] <- renderImage({
filename <- paste0("images/",input$countryInput,".png")
list(src = filename, height = 100)
})
imageOutput("image", height = "100px")
Related
I'm new to R/Shiny and I'm trying to build a dashboard that needs to render specific RMD scripts depending on which 'indicator' radio button is selected.
The aim is to have a fluidpage where an indicator is selected using radio buttons, which renders the associated chart.rmd to present the chart. I can render a specific chart.rmd manually but I encounter an issue when trying to get it reactive to the 'indicator' selection.
I have an excel lookup that contains a list of indicators and the names of the RMD files I want to render when the indicator is selected.
I'm using a reactive element that uses the indicator input to filter the lookup file and print out the name of the RMD I want to render.
Below is my code for the main dashboard RMD and the chart RMDs.
Main Dashboard RMD
---
output:
html_document:
runtime: shiny
---
```{r mainlibrary, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
# Load packages
library(shinythemes)
library(shinyWidgets)
library(shiny)
library(shinydashboard)
library(readxl)
library(dplyr)
library(shinyjs)
library(knitr)
library(withr)
library(rmarkdown)
# Function to render in RMD scripts
render_child <- function(path) {
withr::local_options(list(htmltools.preserve.raw = FALSE))
markdown(knitr::knit_child(path, quiet = TRUE,envir = knit_global()))
}
```
```{r data, include=FALSE}
# Read in chart lookup table
lookup <- read_xlsx("Lookup.xlsx")
```
```{r code, echo=FALSE}
Chart_output <- reactive({
req(input$Indicator_choice)
Chart_output <-lookup %>%
filter(Indicator == input$Indicator_choice)
Chart_output <- as.character(Chart_output[2])
#renderUI(Chart_output)
})
Chart_output
```
```{r Page, echo=FALSE}
fluidPage(
sidebarLayout(
sidebarPanel(
radioButtons(
inputId = "Indicator_choice",
label = "Select indicator",
choices = unique(lookup$Indicator),
selected = "One"
)
),
mainPanel(
HTML(render_child({Chart_output()}))
#renderText({Chart_output()}),
)
)
# End of fluidpage
)
```
Chart 1 RMD
---
title: "Chart 1"
output:
html_document:
runtime: shiny
---
```{r chart1_test, echo=FALSE}
print("Chart 1 RMD")
```
Chart 2 RMD
---
title: "Chart 2"
output:
html_document:
runtime: shiny
---
```{r chart2_test, echo=FALSE}
print("Chart 2 RMD")
```
Chart 3 RMD
---
title: "Chart 3"
output:
html_document:
runtime: shiny
---
```{r chart3_test, echo=FALSE}
print("Chart 3 RMD")
```
When I try running the dashboard I get this error:
*Error: Operation not allowed without an active reactive context.
You tried to do something that can only be done from within a reactive consumer.
The closest I’ve got is printing out the name of the RMD I want to render using a reactive element, but I am unable to use that in the main panel of the fluidpage to render the RMD.
I've managed to get the dashboard working by using a different method that renders each chart into its own object. I can then use render UI to load specific chart RMDs depending on what indicator is selected. Although this method works, I'm concerned the loading time will be too long as the final dashboard will contain 30 chart RMDs that will need to be read in at the beginning of the script.
Working Main Dashboard RMD
---
output: html_document
runtime: shiny
---
```{r mainlibrary, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
# Load packages
library(shinythemes)
library(shinyWidgets)
library(shiny)
library(shinydashboard)
library(readxl)
library(dplyr)
library(shinyjs)
library(knitr)
library(withr)
# Function to render in RMD scripts
render_child <- function(path) {
withr::local_options(list(htmltools.preserve.raw = FALSE))
markdown(knitr::knit_child(path, quiet = TRUE,envir = knit_global()))
}
```
```{r, echo = FALSE}
# Store the rendered files as
Chart_1 <- HTML(render_child("Chart_Rmd_1.Rmd"))
Chart_2 <- HTML(render_child("Chart_Rmd_2.Rmd"))
Chart_3 <- HTML(render_child("Chart_Rmd_3.Rmd"))
fluidPage(
radioButtons(
inputId = "Indicator_choice",
label = "Select indicator",
# choices = unique(lookup$Indicator),
choices = c("One", "Two", "Three"),
selected = "One"
),
uiOutput("test_output")
)
output$test_output <- renderUI({
req(input$Indicator_choice)
switch(input$Indicator_choice,
"One" = Chart_1,
"Two" = Chart_2,
"Three" = Chart_3)
})
```
Ideally, I would to use the first method but I'm not sure how to solve the issue or know if it's even possible. Any advice would be appreciated.
this recently came up with the gt:: package but I also remember this from kableExtra as well iirc.
I'm trying to both use the packages title option but also RMarkdowns fig.cap.
Is there a way to enable both or do I have to work around it, for example with {{captioneer}} ?
edit: this question has been solved using gt::gt(caption = "xy")
Next: is it possible to place this caption at the bottom of the table?
Thanks!
---
title: "gt caption"
author: ""
date: "10 5 2022"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Header
```{r, fig.cap="I also want this fig.cap", echo = FALSE}
tab <- gt::gt(pressure, caption = "xy")
tab <- gt::tab_header(tab,
title = gt::md(
"Title via tab_header"))
tab
```
You could replace the caption argument in gt() with gt::tab_footnote()
tab <- gt::gt(pressure)
tab <- gt::tab_footnote(tab, footnote = "xy")
tab <- gt::tab_header(tab,
title = gt::md(
"Title via tab_header"))
tab
In this example each kable is produced on one slide, even though the slide is large enough for 2.
---
title: "Untitled"
author: ""
date: "2/2/2022"
output: powerpoint_presentation
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE, fig.height=5, fig.width=10)
```
## Slide with R Output
```{r}
knitr::kable(head(summary(cars),2))
```
```{r}
knitr::kable(head(summary(cars),2))
```
gives the output:
How do I make both kable on one slide one after the other.
You can use the gridExtra package https://cran.r-project.org/web/packages/gridExtra/vignettes/tableGrob.html
The documentation provides additional details about controlling formatting. I provided one example for illustration.
library(tidyverse)
library(gridExtra)
t1 <-
head(summary(cars),2) %>%
tableGrob(theme = ttheme_minimal(), rows = NULL)
tt3 <- ttheme_minimal(
core=list(bg_params = list(fill = blues9[1],
col=NA),
fg_params=list(fontface=3)),
colhead=list(fg_params=list(col="navyblue", fontface=4L)))
t2 <-
head(summary(cars),2) %>%
tableGrob(theme = tt3, rows = NULL)
grid.arrange(t1 , t2)
I'm trying to incorporate an Rmd I have been using into a flexdashboard. I'm curious if it is possible to isolate an uploaded file and use it as-is rather than writing a bunch of reactive functions. If this is my template, is it possible to get a static object named df that the child document can go ahead and run with?
---
title: "help"
runtime: shiny
output:
flexdashboard::flex_dashboard:
orientation: columns
---
```{r}
fileInput("data", "select data")
df <- isolate(input$data)
```
```{r, child="some_code.Rmd"}
```
My real example does something completely different but let's say some_code.Rmd looks like this:
---
title: "some code"
output: html_document
---
```{r packages, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE)
library(tidyverse)
```
The data looks like this:
```{r}
as_tibble(df)
```
The numeric data can be summarized with the following means
```{r}
df |>
summarise(across(where(is.numeric), mean)) |>
gather()
```
This ended up working:
knitr::knit() + markdown::markdownToHTML() + HTML() ---> renderUI()
---
title: "help"
runtime: shiny
output:
flexdashboard::flex_dashboard:
orientation: rows
---
Sidebar {.sidebar}
==============================================
```{r file-input}
fileInput("data", "select data")
```
Row
==============================================
```{r knit-child}
observeEvent(input$data, {
df <- isolate(read.csv(input$data$datapath))
new_env <- list2env(list(df = df))
output$res <- renderUI({
knitr::knit("some_code.Rmd", quiet = TRUE, envir = new_env) |>
markdown::markdownToHTML() |>
HTML()
})
})
uiOutput("res")
```
I have added a download button to my flexdashboard in the sidebar panel, but it appears in the main panel when I knit the .RMD. Can you please guide me as to how I can fix it?
Here's a minimal example of what I'm trying to accomplish
---
title: "Download Button in Wrong Panel"
output:
flexdashboard::flex_dashboard:
vertical_layout: scroll
runtime: shiny
---
```{r setup, include=FALSE}
## Setting up required libraries
library(flexdashboard)
library(dplyr)
library(shiny)
library(knitr)
dataset <- read.csv(somefile)
```
Inputs {.sidebar}
-----------------------------------------------------------------------
### Input Filters
```{r input}
## Metric 1
selectInput('metric',
'Choose Metric',
names(dataset %>% select(-default_column)),
selected = "default_metric")
## Download Button
downloadButton('downloadData','Download Result Set')
```
Outputs
-----------------------------------------------------------------------
### List of Customers
```{r output}
subset_dataset <- reactive({
dataset[,c("default_column",input$metric)]
})
renderTable({
subset_dataset()
},
include.rownames = FALSE)
downloadHandler(filename = function() {
paste('resultset-', Sys.Date(), '.csv', sep='')
},
content = function(file) {
write.csv(subset_dataset(), file, row.names = FALSE)
}
)
```
A screenshot of the dashboard is as follows
Thanks!
Never mind, I fixed it and it was rather silly of me to have not tried it before posting the question, but if someone ever faces a similar problem, the solution is here.
The download handler function must simply be placed in the sidebar panel as well and that does it.
Inputs {.sidebar}
-----------------------------------------------------------------------
### Input Filters
```{r input}
## Metric 1
selectInput('metric',
'Choose Metric',
names(dataset %>% select(-default_column)),
selected = "default_metric")
## Download Button
downloadButton('downloadData','Download Result Set')
downloadHandler(filename = function() {
paste('resultset-', Sys.Date(), '.csv', sep='')
},
content = function(file) {
write.csv(subset_dataset(), file, row.names = FALSE)
}
)