Render ggplot2 plot in HTML template within RMarkdown - html

I've built a function in rmarkdown to produce some HTML output with given values, but I want it to work if one of the passed values references a ggplot object.
Basically, knitr renders this perfectly:
x <- [R computation]
y <- [ggplot figure]
<div id="some_number">`r x`</div>
<div id="some_figure">
```{r}
y
```
</div>
But I don't want to have to rewrite that every time I use that particular chunk of html with different x and y. So I wrote the following function:
html_func <- function(x,y) {
template <- "
<div id=\"some_num\">{x}</div>
<div id=\"some_fig\">{y}</div>
"
instance <- glue::glue(template)
output <- knitr::asis_output(instance)
return(output)
}
number <- [R computation]
figure <- [ggplot figure]
html_func(number, figure)
The rendered page shows the "number" computed correctly within the div, but doesn't render the plot.
How can I get it to produce the plot within the HTML container?
UPDATE: Commenter suggested using live data so here we go.
This works:
```{r}
library(ggplot2)
data(mtcars)
number <- mean(mtcars$mpg)
figure <- ggplot2::ggplot(mtcars, aes(x=hp, y=mpg)) +
geom_point()
```
<div id="some_number">`r number`</div>
<div id="some_figure">
```{r echo=FALSE}
figure
```
</div>
But this does not. The computation outputs fine, but the plot does not render.
```{r}
library(ggplot2)
data(mtcars)
number <- mean(mtcars$mpg)
figure <- ggplot2::ggplot(mtcars, aes(x=hp, y=mpg)) +
geom_point()
html_func <- function(x,y) {
template <- "
<div id=\"some_num\">{x}</div>
<div id=\"some_fig\">{y}</div>
"
instance <- glue::glue(template)
output <- knitr::asis_output(instance)
return(output)
}
html_func(number, figure)
```
Here's a screenshot comparing the two.

So this is a BAD solution.
```{r}
html_func_open <- function(x) {
template <- "
<div id=\"some_num\">{x}</div>
<div id=\"some_fig\">
"
instance <- glue::glue(template)
output <- knitr::asis_output(instance)
return(output)
}
html_func_close <- function() {
template <- "
</div>
"
instance <- glue::glue(template)
output <- knitr::asis_output(instance)
return(output)
}
html_func_open(number)
figure
html_func_close()
```
I get the output I want by doing the plot outside of the HTML template, then closing up the HTML in a second function. This allows the HTML on either side of the figure to be as complex as I want. But it's not really an ideal solution, since It requires multiple lines every time I want to add in a new figure, which limits the complexity with which I can build HTML containers.
So still seeking a better solution where I can just pass the figure to the function and have it render properly.

Related

Using R code to scrape data from a webpage into an Excel file

I have written a code in R which is supposed to retrieve certain information from a website and import it into an Excel file. I have used it for one website and it works, but for this particular website, it has an issue, it returns N/A values in excel, and I don't know why.
library(tidyverse)
library(rvest)
library(string)
library(rebus)
library(lubridate)
library(xlsx)
library(reader)
setwd("C:/Users/user/Desktop/Tenders")
getwd()
ran=seq(300100,300000,-1)
result = data.frame(matrix(nrow = length(ran), ncol = 1))
colnames(result) <- c("111")
for (i in ran){
url <- paste0("http://tenders.procurement.gov.ge/public/?go=", i)
download.file(url, destfile = "scrapedpage.html", quiet=TRUE)
content <- read_html("scrapedpage.html")
#111
status=content %>% html_nodes("#print_area tr:nth-child(1) td + td")%>% html_text()
status[length(status) == 0] <- NA
status=as.data.frame(status)
status=(if (nrow(status)>1){
a=as.matrix(paste(unlist(status), collapse =" "))
} else {as.matrix(status)
})
result[i, 1]=status
}
s=as.data.frame(ran)
final=result[-c(1:s[nrow(s),]),]
#Excel
write.xlsx(final,"C:/Users/user/Desktop/Tenders.xlsx", sheetName = "111")
I am using selector gadget tool, which is a chrome extension for identifying HTML parts that the code is supposed to use to gather the information (for example, in the code above it is "#print_area tr:nth-child(1) td + td", which is the first entry in the link).
Can someone help me find out what the issue might be?

Web Scrape an Image with rvest R

I'm having a problem when trying to scrape an image from this page. My code is as follow:
library(rvest)
url <- read_html("https://covid-19vis.cmm.uchile.cl/chart")
m <- '/html/body/div/div/div[4]/main/div/div/div/div/div/div[2]/div[1]'
grafico_cmm <- html_node(url, xpath = m) %>% html_attr('src')
When I run the above code, the result is NA. Does someone know how can I scrape the plot or maybe the data from the page?
Thanks a lot
It not an image, it is an interactive chart. For an image, you would need to scrape the data points and re-create as a chart and then convert to an image. Xpath is also invalid.
The data comes from an API call. I checked the values against the chart and this is the correct endpoint.
library(jsonlite)
data <- jsonlite::read_json('https://covid-19vis.cmm.uchile.cl/api/data?scope=0&indicatorId=57', simplifyVector = T)
The chart needs some tidying but here is a basic plot of the r values:
data$date <- data$date %>% as.Date()
library("ggplot2")
ggplot(data=data,
aes(x=date, y=value, colour ='red')) +
geom_line() +
scale_color_discrete(name = "R Efectivo", labels = c("Chile"))
print tail(data)

R package rvest() working, but not giving the result of filling out the HTML form

I'm stumped, not sure what I'm doing wrong (using rvest()):
url <- "http://library.uaf.edu"
a_session <- session(url)
a_form <- html_form(a_session)
filled_form <- html_form_set(a_form[[1]],ebscohostsearchtext="SQL")
#
a_returned_info <- html_form_submit(filled_form)
returned_page <- rawToChar(a_returned_info$content)
big_pile_of_html <- read_html(returned_page)
#writeLines(text=returned_page,con=file(FILENAMEHERE))
PROBLEM: When I look at the output from the last line in a browser, I see the original page (obtained by 'url'), and not the page that should be created when the SQL is submitted to the field. Otherwise, output is reasonable HTML. Also, the status code for a_returned_info is 200, which should be a success.

Scraping html table and its href Links in R

I am trying to download a table that contains text and links. I can successfully download the table with the link text "Pass". However, instead of the text, I would like to capture the actual href URL.
library(dplyr)
library(rvest)
library(XML)
library(httr)
library(stringr)
link <- "http://www.qimedical.com/resources/method-suitability/"
qi_webpage <- read_html(link)
qi_table <- html_nodes(qi_webpage, 'table')
qi <- html_table(qi_table, header = TRUE)[[1]]
qi <- qi[,-1]
Above gives a nice dataframe. However the last column only contains the text "Pass" when I would like to have the link associated with it. I have tried to use the following to add the links, but they do not correspond to the correct
row:
qi_get <- GET("http://www.qimedical.com/resources/method-suitability/")
qi_html <- htmlParse(content(qi_get, as="text"))
qi.urls <- xpathSApply(qi_html, "//*/td[7]/a", xmlAttrs, "href")
qi.urls <- qi.urls[1,]
qi <- mutate(qi, "MSTLink" = (ifelse(qi$`Study Protocol(click to download certification)` == "Pass", (t(qi.urls)), "")))
I know little about html, css, etc, so I am not sure what I am missing to accomplish this properly.
Thanks!!
You're looking for a elements inside of table cells, td. Then you want the value of the href attribute. So here's one way, which will return a vector with all the URLs for the PDF downloads:
qi_webpage %>%
html_nodes(xpath = "//td/a") %>%
html_attr("href")

Displaying a vector of values wrapping at screen width [Shiny]

I have a vector of values and each value is associated with a name; length of vector changes as per the user input. Although I used table related commands, I like to know other ways to display this kind of data, which is essentially a vector (a single row) of values with names). The problem shows up when selected sample size produces the output that is greater than screen width. Scrolling horizontally allows flexibility to glance over the data, but I am looking for a solution that wraps up the data at the screen width and prints in multiple rows without the need to scroll. Here is the code to play:
ui <- fluidPage(
tabPanel("Test",
numericInput("samsize","specify sample size",4,1,52),
tableOutput('table')
))
server <- function(input, output) {
data <- reactive({
# create a vector of lower- and upper- case alphabets
# create a vector assigning numbers to alphabets
alphabets <- c(letters,LETTERS)
Index <- seq(1,length(alphabets),1)
names(Index) <- alphabets
# sample values
SampleIndex <- sample(Index,input$samsize)
# convert it into a matrix
data <- matrix(SampleIndex,nrow=1)
colnames(data)=names(SampleIndex)
data
})
output$table <- renderTable(data(),digits = 0)
}
shinyApp(ui, server)
As you see in the below picture, for a sample size '36' one need to scroll the page horizontally to see all the values. width in renderTable did not offer any solution Converting data into a html object/text might be one option, but not sure how to retain the names.
You can use renderUI together with uiOutput to create yourself the HTML object you want to display for example using div:
library(shiny)
ui <- fluidPage(
tabPanel("Test",
numericInput("samsize","specify sample size",4,1,52),
uiOutput('myTable')
))
server <- function(input, output) {
data <- reactive({
alphabets <- c(letters,LETTERS)
Index <- seq(1,length(alphabets),1)
names(Index) <- alphabets
# Notice I don't put the vector in a one row matrix as in you example
sample(Index,input$samsize)
})
library(purrr) # map is a nice alternative to lapply
output$myTable <- renderUI(map(names(data()),~div(strong(.),
div(data()[.]),
style="float:left;padding:10px 20px;")))
}
shinyApp(ui, server)