I'm trying to create an interactive document like the tutorial on Shiny's website. However, I want the plot to be a Leaflet map. Following the Leaflet tutorial, it seems like the following should work using leaflet::renderLeaflet() instead of shiny::renderPlot().
Instead, I get an error when running the document: Error: object 'input' not found. Is there a special way to expose input to leaflet when using Shiny widgets inside an interactive Rmarkdown document?
---
runtime: shiny
output: html_document
---
```{r echo = FALSE}
library(magrittr)
shiny::selectInput(
"weight", label = "Weight:",
choices = c(1, 2, 3, 4, 5), selected = 5
)
```
```{r include = FALSE}
csa <- tigris::combined_statistical_areas(class = "sf")
```
```{r echo = FALSE}
leaflet::renderLeaflet({ # <- main difference from tutorial
leaflet::leaflet() %>%
leaflet::addTiles() %>%
leaflet::addPolylines(data = csa, color = '#333', weight = input$weight)
})
```
I can't confirm your issue. Your sample interactive document runs just fine:
I've been using the following library versions on R 3.6.1
leaflet_2.0.2
rmarkdown_1.16
shiny_1.4.0
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.
I create a Leaflet widget and save it locally:
library(htmlwidgets)
library(leaflet)
library(sf)
shp = st_read("/path/to/some/shapefile.shp")
m = shp %>%
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
setView(lng = -70, lat = 40, zoom = 11)
saveWidget(m, "m.html")
Now I want to load this widget in a Rmarkdown chunk:
---
title: "Title"
author: "author"
date: "5/8/2020"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
etc etc etc
```{r}
function_that_loads_widget("m.html")
```
etc etc etc
I've tried htmltools::includeHTML() but that makes the entire HTML output one big widget. The text of the report is not displayed.
I realize I could put the the code that created the Leaflet widget directly in the Rmarkdown chunk, but I don't want to do that.
knitr::include_url() appears to be the solution. This works for my blogdown post.
```{r, out.width="100%"}
knitr::include_url("url_of_html", height="1080px")
```
I am building a new htmlwidget package called fusionchartsR (https://github.com/alexym1). I tried to embed a little piece of code to my rmarkdown report however, it doesn't work and I don't know why. I tried differents strategies without any success.
First strategy
---
title: "Stack overflow"
author: "John Doe"
date: "01/04/2020"
output: word_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## Render an htmlwidget graphic
```{r}
library(fusionchartsR)
df <- data.frame(label = c("Venezuela", "Saudi", "Canada", "Russia"), value = c(290, 260,180, 115))
fusionPlot(data = df, type = 'pie2d') %>%
fusionTheme(theme = "fusion")
```
Second strategy
# Webshot and phantomjs have been previously installed.
library(webshot)
webshot::install_phantomjs()
# Then, I loaded packages and built a little piece of code
library(fusionchartsR)
library(htmlwidgets)
df <- data.frame(label = c("Venezuela", "Saudi", "Canada", "Russia"), value = c(290, 260,180, 115))
widget <- fusionPlot(data = df, type = 'pie2d') %>%
fusionTheme(theme = "fusion")
# Save a rendered widget to an HTML file
saveWidget(widget = widget, file = "Mywidget.html")
# An error appeared: `Error: pandoc document conversion failed with error 99`
# Take a webshot
webshot(url = "Mywidget.html", file = "webshot.png")
The Mywidget.html can be found on your Documents folder.
How can I solve this problem ?
I will be very greatful !
Instead of using webshot, you should consider to try webshot2 on https://github.com/rstudio/webshot2 which doesn't suffer from this issue. I have replicated your scenario with webshot2, the issue is resolved as below screenshot. See my detailed answer to the similar case.
The code:
# Webshot and phantomjs have been previously installed.
library(webshot2)
# install.packages("remotes")
# remotes::install_github("alexym1/fusionChartsR")
# Then, I loaded packages and built a little piece of code
library(fusionchartsR)
library(htmlwidgets)
df <- data.frame(label = c("Venezuela", "Saudi", "Canada", "Russia"), value = c(290, 260,180, 115))
widget <- fusionPlot(data = df, type = 'pie2d') %>%
fusionTheme(theme = "fusion")
# Save a rendered widget to an HTML file
saveWidget(widget = widget, file = "Mywidget.html")
# An error appeared: `Error: pandoc document conversion failed with error 99`
# Take a webshot
webshot(url = "Mywidget.html", file = "webshot.png")
The output:
I'm using the bookdown package with RMarkdown to generate web-based book similar to this, likewise with the option to download a pdf-version of the book.
I've included plotly graphs in my "book" which work nicely in the html-version of the book. Being interactive, the button "build book" throws an error when including pdf output in the YAML-header.
Based on this description I've found a workaround with a regular RMarkdown File to create pdfs with plotly graphs outputs. A minimal solution (outside bookdown) looks like this:
---
title: "test"
output:
pdf_document: default
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(plotly)
Sys.setenv("plotly_username" = "username")
Sys.setenv("plotly_api_key" = "API")
```
```{r cars}
library(plotly)
p <- plot_ly(x = c(1,2,3,4), y = c(2,4,1,3), type = 'scatter', mode = 'lines')
plotly_IMAGE(p, format = "png", out_file = "output.png")
```
![Caption for the picture.](output.png)
Is there a way to include this solution within bookdown, so that the graphs are automagically interactive in the html output and static (png) in the pdf output?
Based on this blogpost I was able to come up with a solution. Note, this only works
with the "knitr" button (see this post for a workaround)
with an internet connection (1) and Plotly Account (2)
(1) See this link to export static images locally (which I didn't get to work since I failed installing PhantomJS)
(2) Plotly has a user Quota of currently 100 plots / grids per user per day
---
title: "test"
output:
html_document: default
pdf_document: default
word_document: default
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(plotly)
library(pander)
Sys.setenv("plotly_username" = "YOUR PLOTLY USERNAME")
Sys.setenv("plotly_api_key" = "API KEY")
output <- knitr::opts_knit$get("rmarkdown.pandoc.to") # html / latex / docx
```
```{r, results="asis"}
print(output)
p <- plot_ly(x = c(1,2,3,4), y = c(2,4,1,3), type = 'scatter', mode = 'lines')
filename <- "output.png"
if(output %in% c("latex","docx")){
plotly_IMAGE(p, format = "png", out_file = filename)
pandoc.image(filename)
} else if(output == "html"){
p
} else(print("No format defined for this output filetype"))
```
Outside of Rmarkdown the stand alone googleVis chart works fine, but when I plug it in the Rmarkdown file I am receiving just the Rmarkdown Code:
Viewer Output:
> TEST H 4/13/2016 require(googleVis) Loading required package:
> googleVis Welcome to googleVis version 0.5.10 Please read the Google
> API Terms of Use before you start using the package:
> https://developers.google.com/terms/
>
> Note, the plot method of googleVis will by default use the standard
> browser to display its output. See the googleVis package vignettes
> for more details, or visit http://github.com/mages/googleVis. To
> suppress this message use:
> suppressPackageStartupMessages(library(googleVis))
>
> dttm = data.frame(DT_ENTRY=Sys.Date()-1:20,variable="x",value=1:20)
> g1=gvisAnnotationChart(dttm,datevar="DT_ENTRY",numvar="value",idvar="variable")
> plot(g1) starting httpd help server ... done
Rmarkdown Code Below:
---
title: "test"
author: "H"
date: "4/13/2016"
output: html_document
highlight: tango
number_sections: yes
---
```{r}
require(googleVis)
dttm = data.frame(DT_ENTRY=Sys.Date()-1:20,variable="x",value=1:20)
g1=gvisAnnotationChart(dttm,datevar="DT_ENTRY",numvar="value",idvar="variable")
plot(g1)
```
The r chunk has to be declared as:
```{r plotg0, results='asis', tidy=FALSE, echo=FALSE}
The "asis" is important because it returns raw HTML
I am not sure if you still need an answer. However, I faced the same problem while trying to embed a sankey plot from gvisSankey onto a section on Rmarkdown. Thankfully, I found the solution on github.com/mages/googleVis (weirdly not recommended on Google Search).
Below is a reproducible example.
First, to create a sankey plot, I do this:
# install.packages("googleVis")
library(googleVis)
# Create a data.frame that is gvisSankey-conform
# i.e., has these columns: FROM - TO - WEIGHT
df <- data.frame(FROM = rep(c("A","B","C"), each = 3),
TO = rep(c("D","E","F"), times = 3),
WEIGHT = sample(1:10, 9, replace = TRUE))
sankeyplot <- gvisSankey(data = df,
from = "FROM",
to = "TO",
weight = "WEIGHT")
plot(sankeyplot)
plot(sankeyplot) will open a new tab containing the sankeyplot. Now, how do I embed the sankeyplot onto my Rmarkdown?
There are two important points:
To set self_contained:false in the YAML header
To set results='asis' in the R code chunk where the sankeyplot is embedded
---
title: "SankeyPlot_Example"
output:
html_document:
self_contained: false
date: '2022-10-21'
---
## Embed googleVis object (sankey plot) onto Rmarkdown
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(googleVis)
# Create a reproducible data.frame
df <- data.frame(FROM = rep(c("A","B","C"), each = 3),
TO = rep(c("D","E","F"), times = 3),
WEIGHT = sample(1:10, 9, replace = TRUE))
```
```{r results='asis'}
sankeyplot <- gvisSankey(data = df,
from = "FROM",
to = "TO",
weight = "WEIGHT")
print(sankeyplot, 'chart')
```