embed shiny app into Rmarkdown html document - html

I am able to create an Rmarkdown file and I'm trying to embed a shiny app into the html output. The interactive graph shows if I run the code in the Rmarkdown file. But in the html output it only shows a blank box. Can anybody help fix it?
Run the code in Rmarkdown file:
In the html output:
My Rmarkdown file (please add the three code sign at the end yourself somehow i cannot do here):
---
title: "Data Science - Tagging"
pagetitle: "Data Science - Style Tagging"
author:
name: "yyy"
params:
creation_date: "`r format(Sys.time(), c('%Y%m%d', '%h:%m'))`"
runtime: shiny
---
```{r plt.suppVSauto.week.EB, out.width = '100%'}
data <- data.frame(BclgID = c('US','US','US','UK','UK','UK','DE','DE','DE'),
week = as.Date(c('2020-06-28', '2020-06-21', '2020-06-14', '2020-06-28', '2020-06-21', '2020-06-14', '2020-06-28', '2020-06-21', '2020-06-14')),
value = c(1,2,3,1,2,2,3,1,1))
shinyApp(
ui <- fluidPage(
radioButtons(inputId = 'BclgID', label = 'Catalog',
choices = type.convert(unique(plot$BclgID), as.is = TRUE),
selected = 'US'),
plotOutput("myplot")
),
server <- function(input, output) {
mychoice <- reactive({
subset(data, BclgID %in% input$BclgID)
})
output$myplot <- renderPlot({
if (length(row.names(mychoice())) == 0) {
print("Values are not available")
}
p <- ggplot(mychoice(), aes(x=as.factor(week), y=value)) +
geom_line() +
labs(title = "test",
subtitle = "",
y="Value",
x ="Date") +
theme(axis.text.x = element_text(angle = 90)) +
facet_wrap( ~ BclgID, ncol = 1)
print(p)
}, height = 450, width = 450)
}
)

EDIT:
Coming back another year later in case anyone still finds this useful. Having done some more work with both shiny and rmarkdown so I understand both better, there isn't really a reason to use them together. Rmarkdown's advantage is being able to come up with a somewhat static pdf that is readable, where shiny is dynamic and requires input.
While my answer below works, if you're using shiny for a GUI, consider removing the rmarkdown portion of what you are writing. It probably isn't adding much/anything, and trying to use the two together can cause headaches.
Original answer below:
I see this was asked a long time ago, so you've probably moved on, but I ran into the same problem and this came up first, so I'll answer it in case anyone else runs into this problem.
I found the answer on this page:
https://community.rstudio.com/t/embedding-shiny-with-inline-not-rendering-with-html-output/41175
The short of it is shiny documents need to be run and not rendered. Rather than calling:
>rmarkdown::render("filename.rmd")
we need to call:
>rmarkdown::run("filename.rmd")
If you are inside Rstudio, it seems the "knit" function changes from render to run when using shiny in RMD.

Related

Search Menus in R Markdown?

Using a loop in R, I generated 100 random datasets and made a plot for each of these 100 datasets:
library(ggplot2)
results = list()
for (i in 1:100)
{
my_data_i = data.frame(var_1 = rnorm(100,10,10), var_2 = rnorm(100,10,10))
plot_i = ggplot(my_data_i, aes(x=var_1, y=var_2)) + geom_point() + ggtitle(paste0("graph", i))
results[[i]] = plot_i
}
list2env(setNames(results,paste0("plot",seq(results))),envir = .GlobalEnv)
What I am now trying to do, is make a Rmarkdown/flexdashboard that can be saved as an HTML file, and:
Contains all these plots
Allows the user to search for these plots (e.g. type in "plot76")
In a previous question (How to create a dropdown menu in flexdashboard?) I learned how to do something similar.
But I am still trying to figure out how I can get something like this to work. I would like there to be a single page with a search bar, and you can type in which graph you want to see.
Can someone please help me out with this? Are there any online tutorials that someone could recommend?
Thank you!
This is a close solution depending on how much you need the type feature. First in the YAML specify toc and theme as below. This will create a table of contents and allow the users to click each anchor in the list and it will bring them to the appropriate figure. Second use knit_expand() and knit() to dynamically create html blocks in your code. I did 5 plots here but it should scale to 100.
---
title: "plots"
author: "Michael"
output:
html_document:
toc: true
theme: united
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(ggplot2)
library(glue)
library(knitr)
```
```{r,echo=FALSE, results = 'asis'}
my_data_i = data.frame(var_1 = rnorm(100,10,10), var_2 = rnorm(100,10,10))
out = NULL
out2 = NULL
plot_i = NULL
for (i in 1:5)
{
cat('\n## Plot = ', i, '\n')
plot_i = ggplot(my_data_i, aes(x=var_1, y=var_2)) + geom_point() + ggtitle(paste0("graph", i))
out2 = c(out2, knit_expand(text = "{{print(plot_i)}}" ))
cat('\n')
}
```
`r knit(text = out2)`

Loop through multiple links from an Excel file, open and download the corresponding webpages

I downloaded from MediaCloud an Excel file with 1719 links to different newspaper articles. I am trying to use R to loop through each link, open it and download all the corresponding online articles in a single searchable file (HTML, CSV, TXT, PDF - doesn't matter) that I can read and analyze later.
I went through all similar questions on Stack Overflow and a number of tutorials for downloading files and managed to assemble this code (I am very new to R):
express <-read.csv("C://Users//julir//Documents//Data//express.csv")
library(curl)
for (express$url in 2:1720)
destfile <- paste0("C://Users//julir//Documents//Data//results.csv")
download.file(express$url, destfile, method = "auto", quiet = TRUE, cacheOK=TRUE)
Whenever I try to run it though I get the following error:
Error in download.file(express$url, destfile = express$url, method = "auto", : 'url' must be a length-one character vector
I tried also this alternative method suggested online:
library(httr)
url <- express$url
response <- GET(express$url)
html_document <- content(response, type = "text", encoding = "UTF-8")
But I get the same mistake:
Error in parse_url(url) : length(url) == 1 is not TRUE
So I guess there is a problem with how the URLs are stored - but I can't understand how to fix it.
I am also not certain about the downloading process - I would ideally want all text on the HTML page - it seems unpractical to use selectors and rvest in this case - but I might be very wrong.
You need to look through the url's and read/parse each individually. You are essentially passing an array of urls into one request, which is why you see that error.
I don't know your content/urls, but here's an example of how you would approach this:
library(xml2)
library(jsonlite)
library(dplyr)
df <- data.frame(page_n = 1:5, urls = sprintf('https://www.politifact.com/factchecks/list/?page=%s', 1:5))
result_info <- lapply(df$urls, function(i){
raw <- read_html(i)
a_tags <- raw %>% xml_find_all(".//a[contains(#href,'factchecks/2021')]")
urls <- xml2::url_absolute(xml_attr(a_tags, "href"),xml_url(raw))
titles <- xml_text(a_tags) %>% stri_trim_both()
data.frame(title = titles, links = urls)
}) %>% rbind_pages()
result_info %>% head()
title
links
Says of UW-Madison, "It cost the university $50k (your tax dollars) to remove" a rock considered by some a symbol of racism.
https://www.politifact.com/factchecks/2021/aug/14/rachel-campos-duffy/no-taxpayer-funds-were-not-used-remove-rock-deemed/
“Rand Paul’s medical license was just revoked!”
https://www.politifact.com/factchecks/2021/aug/13/facebook-posts/no-rand-pauls-medical-license-wasnt-revoked/
Every time outgoing New York Gov. Andrew Cuomo “says the firearm industry ‘is immune from lawsuits,’ it's false.”
https://www.politifact.com/factchecks/2021/aug/13/elise-stefanik/refereeing-andrew-cuomo-elise-stefanik-firearm-ind/
The United States' southern border is "basically open" and is "a super spreader event.”
https://www.politifact.com/factchecks/2021/aug/13/gary-sides/north-carolina-school-leader-repeats-false-claims-/
There is a “0.05% chance of dying from COVID.”
https://www.politifact.com/factchecks/2021/aug/13/tiktok-posts/experts-break-down-numbers-catching-or-dying-covid/
The Biden administration is “not even testing these people” being released by Border Patrol into the U.S.
https://www.politifact.com/factchecks/2021/aug/13/ken-paxton/biden-administration-not-even-testing-migrants-rel/

RShiny integration with google sites

I would like to be able to add interactive shiny elements into a website. My HTML skills are not up to speed to make fancy websites from scratch. Google allows you to make nice slick well functioning websites fast, using sites.google.com.
I was wondering if it is possible to add R Shiny elements into a sites.google.com site.
For example, it is possible to put
library(plotly)
trace_0 <- rnorm(100, mean = 5)
trace_1 <- rnorm(100, mean = 0)
trace_2 <- rnorm(100, mean = -5)
x <- c(1:100)
data <- data.frame(x, trace_0, trace_1, trace_2)
p <- plot_ly(data, x = ~x, y = ~trace_0, name = 'trace 0', type = 'scatter', mode = 'lines') %>%
add_trace(y = ~trace_1, name = 'trace 1', mode = 'lines+markers') %>%
add_trace(y = ~trace_2, name = 'trace 2', mode = 'markers')
into https://sites.google.com/view/shinytest ?
EDIT: I read that in Shiny you can build a 'raw' HTML UI instead of a ShinyUI (shiny.rstudio.com/articles/html-ui.html). Would it be possible to extract the HTML from an existing site (e.g. the sites.google site from the example and keep all its functionality) and start using that as a base HTML UI in which Shiny elements can be added (and thususing the server part as back-end)?

Edit map with "R for leaflet"

I have a script which allows me to generate a map with with "R for leaflet" :
library(htmlwidgets)
library(raster)
library(leaflet)
# PATHS TO INPUT / OUTPUT FILES
projectPath = "path"
#imgPath = paste(projectPath,"data/cea.tif", sep = "")
#imgPath = paste(projectPath,"data/o41078a1.tif", sep = "") # bigger than standard max size (15431804 bytes is greater than maximum 4194304 bytes)
imgPath = paste(projectPath,"/test.tif", sep = "")
outPath = paste(projectPath, "/leaflethtmlgen.html", sep="")
# load raster image file
r <- raster(imgPath)
# reproject the image, if necessary
#crs(r) <- sp::CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
# color palette, which is interpolated ?
pal <- colorNumeric(c("#FF0000", "#666666", "#FFFFFF"), values(r),
na.color = "transparent")
# create the leaflet widget
m <- leaflet() %>%
addTiles() %>%
addRasterImage(r, colors=pal, opacity = 0.9, maxBytes = 123123123) %>%
addLegend(pal = pal, values = values(r), title = "Test")
# save the generated widget to html
# contains the leaflet widget AND the image.
saveWidget(m, file = outPath, selfcontained = FALSE, libdir = 'leafletwidget_libs')
My problem is that this is generating a html file and I need this map to be dyanamic. For example, when a user click on some html button which is not integrate on the map, I want to add a rectangle on the map. Any solutions would be welcome...
Leaflet itself does not provide the interactive functionality you are looking for. One solution is to use shiny, which is a web application framework for R. From simple R code, it generates a web page, and runs R on the server-side to respond to user interaction. It is well documented, has a gallery of examples, and a tutorial to get new users started.
It works well with leaflet. One of the examples on the shiny web site uses it, and also includes a link to the source code.
Update
Actually, if simple showing/hiding of elements is enough, leaflet alone will suffice with the use of groups. From the question it's not very clear how dynamic you need it to be.

Generate an HTML report based on user interactions in shiny

I have a shiny application that allows my user to explore a dataset. The idea is that the user explores the dataset, and any interesting things the user finds he will share with his client via email. I don't know in advance how many things the user will find interesting. So, next to each table or chart I have an "add this item to the report" button, which isolates the current view and adds it to a reactiveValues list.
Now, what I want to do is the following:
Loop through all the items in the reactiveValues list,
Generate some explanatory text describing the item (This text should preferably be formatted HTML/markdown, rather than code comments)
Display the item
Capture the output of this loop as HTML
Display this HTML in Shiny as a preview
write this HTML to a file
knitr seems to do exactly the reverse of what I want - where knitr allows me to add interactive shiny components in an otherwise static document, I want to generate HTML in shiny (maybe using knitr, I don't know) based on static values the user has created.
I've constructed a minimum not-working example below to try to indicate what I would like to do. It doesn't work, it's just for demonstration purposes.
ui = shinyUI(fluidPage(
title = "Report generator",
sidebarLayout(
sidebarPanel(textInput("numberinput","Add a number", value = 5),
actionButton("addthischart", "Add the current chart to the report")),
mainPanel(plotOutput("numberplot"),
htmlOutput("report"))
)
))
server = shinyServer(function(input, output, session){
#ensure I can plot
library(ggplot2)
#make a holder for my stored data
values = reactiveValues()
values$Report = list()
#generate the plot
myplot = reactive({
df = data.frame(x = 1:input$numberinput, y = (1:input$numberinput)^2)
p = ggplot(df, aes(x = x, y = y)) + geom_line()
return(p)
})
#display the plot
output$numberplot = renderPlot(myplot())
# when the user clicks a button, add the current plot to the report
observeEvent(input$addthischart,{
chart = isolate(myplot)
isolate(values$Report <- c(values$Report,list(chart)))
})
#make the report
myreport = eventReactive(input$addthischart,{
reporthtml = character()
if(length(values$Report)>0){
for(i in 1:length(values$Report)){
explanatorytext = tags$h3(paste(" Now please direct your attention to plot number",i,"\n"))
chart = values$Report[[i]]()
theplot = HTML(chart) # this does not work - this is the crux of my question - what should i do here?
reporthtml = c(reporthtml, explanatorytext, theplot)
# ideally, at this point, the output would be an HTML file that includes some header text, as well as a plot
# I made this example to show what I hoped would work. Clearly, it does not work. I'm asking for advice on an alternative approach.
}
}
return(reporthtml)
})
# display the report
output$report = renderUI({
myreport()
})
})
runApp(list(ui = ui, server = server))
You could capture the HTML of your page using html2canvas and then save the captured portion of the DOM as a image using this answer, this way your client can embed this in any HTML document without worrying about the origin of the page contents