edit
This issue is not (necessarily) only related to {htmlTable}. The same happens when rendering a html table which has been styled with the {kableExtra} package (see also this thread).
original question
I'm working in RMarkdown, trying to render a document with htmltables from the htmlTable package in a loop. When I push the "Knit" button in RStudio, everything works great. But when I use the render() function, the htmltables in the loop don't get printed, but the table just before the loop does.
I read that "knit" button and the render function does the same, so I don't understand whats wrong?
This is a working example of a .Rmd file with a hmtlTables:
---
output: html_document
---
## htmlTables
```{r, results='asis'}
library(data.table)
library(htmlTable)
library(ggplot2)
a <- data.table(matrix(seq(1, 100, 5), ncol = 2))
htmlTable(a)
for (i in 10:11) {
cat( paste('## title no.', i, '\n' ) )
print(ggplot(a*i, aes(x = V1, y = V2)) + geom_point())
print(htmlTable(a*i))
cat('\n')
}
```
I need to generate many reports automatically with different parameters, so I need to get this working with render().
htmlTable has defined a print method, which appears to print the table in a new window, change print() to writeLines() will do the trick:
---
output: html_document
---
## htmlTables
```{r, results='asis'}
library(data.table)
library(htmlTable)
library(ggplot2)
a <- data.table(matrix(seq(1, 100, 5), ncol = 2))
htmlTable(a)
for (i in 10:11) {
cat( paste('## title no.', i, '\n' ) )
print(ggplot(a*i, aes(x = V1, y = V2)) + geom_point())
writeLines(htmlTable(a*i))
cat('\n')
}
```
However it still seems a bit strange to me because I believe that the knit button uses rmarkdown::render() under the hood but they have different behaviors in this case.
This depends on how the viewer is detected.
To check this :
---
title: "Check viewer"
output: html_document
---
```{r viewer, echo=FALSE}
getOption("viewer")
```
With knit button:
Check viewer
## NULL
With rmarkdown::render:
Check viewer
## function (url, height = NULL)
## {
## if (!is.character(url) || (length(url) != 1))
## stop("url must be a single element character vector.",
## call. = FALSE)
## if (identical(height, "maximize"))
## height <- -1
## if (!is.null(height) && (!is.numeric(height) || (length(height) !=
## 1)))
## stop("height must be a single element numeric vector or 'maximize'.",
## call. = FALSE)
## invisible(.Call("rs_viewer", url, height, PACKAGE = "(embedding)"))
## }
## <environment: 0x0000020ccb7f26d8>
knit button executes rendering in an environment without defined viewer, whereas rmardown::render in RStudio console uses interactive viewer.
htmlTable allows to set options(htmlTable.cat = TRUE), so that print works, ie doesn't use interactive viewer, see ?htmlTable::htmlTable.
The print-function relies on the [base::interactive()] function
for determining if the output should be sent to a browser or to the terminal.
In vignettes and other directly knitted documents you may need to either set
useViewer = FALSE alternatively set options(htmlTable.cat = TRUE).
---
output: html_document
---
## htmlTables
```{r, results='asis'}
options(htmlTable.cat = TRUE)
library(data.table)
library(htmlTable)
library(ggplot2)
a <- data.table(matrix(seq(1, 100, 5), ncol = 2))
htmlTable(a)
for (i in 10:11) {
cat( paste('## title no.', i, '\n' ) )
print(ggplot(a*i, aes(x = V1, y = V2)) + geom_point())
print(htmlTable(a*i))
cat('\n')
}
```
Related
EDIT: Because I had set the format options in a global function, I have to set either latex_options or bootstrap_options in the kable_styling() call. I was using bootstrap_options which wasn't being read by the latex. My work-around is to make the tables twice, once in a chunk for html, and once in a chunk for latex. Not great, but it works if I click the Knit button and choose Knit to PDF. However, it throws the original error when I try to run it in the shiny app.
I have created a test version (MiniTest) of my project. What I need to do is have a shiny app run with a tab that will produce an html file for a user-chosen (reactive) Country, and provide an Excel download (I have that working so kept it out of this example), and a PDF download. I knit in an .Rmd which chooses the format and allows for parameterization. (The shiny part was set up by someone else, from whom I took over this project when they left before finishing it.)
I use kable and kableExtra to create and format tables, as I heard it words for both html and LaTeX output. The HTML is more as less as I want it. I can knit either html or PDF, and it runs, BUT when in the shiny app, only the html portion works. I think I have narrowed down the PDF issue(s) to column_spec crashing the download. If I comment out the column_spec lines in t01 and t02, the Download PDF runs. But I need that formatting. I'm sorry, but I've lost track of all the sites I have searched.
In global.R, I set:
countries <- c("ABC", "DEF", "GHI", "JKL")
In the .Rmd, I have YAML set up (with two-space indents for Country and output types):
params:
Country: ABC
output:
pdf_document: default
html_document: default
Relevant .Rmd chunks and inline code include:
knitr::opts_chunk$set(echo = FALSE)
options(knitr.table.format = function() {
if (knitr::is_latex_output()) "latex" else "html"
})
library(shiny)
library(htmlwidgets)
library(shinythemes)
library(shinydashboard)
library(shinyjs)
library(shinycssloaders)
library(markdown)
library(tidyr)
library(tidyverse)
library(janitor)
library(kableExtra)
options(scipen = 999)
mini <- mtcars %>%
tibble::rownames_to_column(var = "car") %>%
mutate(Country = c(rep("ABC", 8), rep("DEF", 8), rep("GHI", 8), rep("JKL", 8)))
## https://bookdown.org/yihui/rmarkdown-cookbook/font-color.html
colorize <- function(x, color) {
if (knitr::is_latex_output()) {
## hack setting color='blue' instead of a hexcode with # that breaks the LaTeX code
sprintf("\\textcolor{%s}{%s}", color = 'blue', x) ## works, but isn't right blue
} else if (knitr::is_html_output()) {
sprintf("<span style='color: %s;'>%s</span>", color, x)
} else x
}
## make two tables with `kable` and `kableExtra`
new_title <- paste0("Dynamically Changing Country Name in column", params$Country)
t01 <- mini %>%
filter(Country == params$Country) %>%
select(car, mpg:hp) %>%
rename({{new_title}} := car) %>%
kable(align = c("l", "c", "c", "c", "c")) %>%
kable_styling(full_width = FALSE, position = "left", bootstrap_options = c("striped", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
column_spec(2:3, width = "5em") %>%
row_spec(0, color = "#2A64AB") %>%
row_spec(6, bold = TRUE)
t02_title <- paste0(params$Country, " Table with Dollar Signs in Var Names")
t02 <- mini %>%
filter(Country == params$Country) %>%
select(car, drat, wt) %>%
mutate(car = case_when(car == "Mazda RX4" ~ "Mazda RX4 (US\\$)*", TRUE ~ as.character(car))) %>%
## want to blank out column names - removing them entirely would be best, but it fails
kable(align = c("l", "r", "c"), escape = TRUE, col.names = c("", "", "")) %>%
kable_styling(full_width = FALSE, position = "left", bootstrap_options = c("striped", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
column_spec(2, width = "10em") %>%
footnote(general = "*Never smart to start with an asterisk, but here we are", general_title = "")
## make two charts with `ggplot2`
chart1 <- mini %>%
filter(Country == params$Country) %>%
select(car, mpg:hp) %>%
ggplot2::ggplot(mapping = aes(x = mpg)) +
geom_col(aes(y = `cyl`, fill = "cyl"), color = "black")
c1_title <- paste0("Some fab title here for ", params$Country)
chart2 <- mini %>%
filter(Country == params$Country) %>%
select(car, vs:carb) %>%
ggplot2::ggplot(mapping = aes(x = carb)) +
geom_col(aes(y = `gear`, fill = "gear"), color = "black")
c2_title <- paste0("Another chart, ", params$Country)
## make a "tiny" LaTeX environment that is only generated for LaTeX output, with chunk setting `include = knitr::is_latex_output()`.
knitr::asis_output('\n\n\\begin{tiny}')
## Table 1
t01
I expect a PDF to pop up, but instead a Save File box pops up asking to save "DownloadPDF" with no file extension. The ui.R is supposed to name it as "FactCountryName.pdf" where "CountryName" is input from the Country the user chose in the drop-down list. Regardless of whether I choose Save (nothing happens) or Cancel, my R throws the following error:
```
! LaTeX Error: Illegal character in array arg.
```
If I comment out the line column_spec(1, bold = TRUE) %>%, the error changes to:
```
! Use of \#array doesn't match its definition.
\new#ifnextchar ...served#d = #1\def \reserved#a {
#2}\def \reserved#b {#3}\f...
l.74 ...m}|>{\centering\arraybackslash}p{5em}|c|c}
```
Please help!
Turns out that using the Knit button in R automatically loads the required LaTeX packages, such as booktabs. Running the file in the Shiny app was not loading all the packages needed. All I had to do was specifically call the extra packages in the YAML (which I found by looking at the .tex file made from the PDF through Knit button).
---
params:
Country: ABC
header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage{wrapfig}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage{pdflscape}
- \usepackage{tabu}
- \usepackage{threeparttable}
- \usepackage{threeparttablex}
output:
pdf_document:
keep_tex: true
html_document: default
---
Question about knitting RMarkdown.
I am having issues when knitting a Rmarkdown file to HTML/pdf. When I run my chunks of code in the Rmarkdown file everything runs smoothly (and I get my graphs made with ggplot) but when knitting I get an output with no graphs and errors (error in eval, error in ggplot, error in print).
Does anyone have experience with this?
The errors:
Error in eval(lhs, parent): object ‘iso3166’ not found
Error in ggplot(inci_100k, aes(long, lat, map.id=mapname,fill=inci)): object ‘inci_100k’ not found
Error in print(INCIPLOT): object ‘INCIPLOT’ not found
The code:
---
title: "R Markdown MAP"
author: "Alexandra V"
date: "1/4/2020"
output:
html_document: default
pdf_document: default
word_document: default
---
```{r,echo = FALSE, warning = FALSE, message=FALSE, error=TRUE}
knitr::opts_chunk$set(cache=TRUE)
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(error = TRUE)
```
Loading the packages we will need for the following analysis.
```{r echo=FALSE, warning=FALSE}
library(tidyverse)
library(lubridate)
library(ggmap)
library(countrycode)
library(grid)
library(gridExtra)
```
To only keep the data needed to make a worldmap of TB incidences, only the relevant data will be taken from the TB_burden_countries_2020-01-04.csv file. Column 1: country names, column 3: iso3 (country codes), column 6: years, column 8: e_inc_100k (estimated incidence all TB forms per 100.000). To make the file easier to work with the names of the columns will be changed to: country, code, year and inci respectively.
```{r, message=FALSE}
TB.burden <- read.csv("TB_burden_countries_2020-01-04.csv")
TBworldINC.map <- as.data.frame(TB.burden[,c(1,3,6,8)], drop=false)
write.csv(TBworldINC.map, 'TBworldINC.map.csv', row.names = FALSE)
tb.INC <- read_csv("TBworldINC.map.csv") %>%
setNames(c("country", "code", "year", "inci"))
```
```{r}
world <- map_data("world")
tb_some_years <- tb.INC %>%
filter(year %in% c(2005, 2010, 2015, 2018))
inci_100k <- tb_some_years %>%
inner_join(iso3166 %>% select(a3, mapname), by = c(code = "a3")) %>%
left_join(world, by = c(country = "region"))
INCIPLOT <- ggplot(inci_100k, aes(long, lat, map_id = mapname,
fill = inci)) +
geom_map(map = world) +
scale_fill_gradient(low = "blue", high = "yellow") +
theme_void() +
coord_map(xlim = c(-180, 180)) +
labs(fill = "Incidence per year") +
facet_wrap(~ year, ncol = 2)
print(INCIPLOT)
```
picture of the output I get in Rstudio
I have had similar issues when making maps in R. One work around is to create your graphs and to save it locally and including the images. The syntax for adding images in R Markdown is ![alt text](path to image)
I have created quite a long and complicated shiny app, which produces tables and plots based on various user inputs. I want to create a 'download report' button which will display the charts and plots currently visible on the app.
However, I cannot seem to produce a report that works. I have used an example shiny app which contains my problem, hoping that there is a simple solution. When I click 'download report', it asks me to select the save location and produces a report called 'report'. However, it is not an HTML format. It does not have any format actually, so I cannot open it and view the results
Shiny app:
#install.packages("shiny")
library(shiny)
library(ggplot2)
ui <- fluidPage(
title = 'Example application',
sidebarLayout(
sidebarPanel(
helpText(),
selectInput('x', 'Build a regression model of mpg against:',
choices = names(mtcars)[-1]),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
plotOutput('regPlot')
)
)
)
server <- function(input, output) {
chart1 <- reactive({
ggplot(data = mtcars, aes(x=input$x, y=mpg))+geom_point()
})
output$regPlot <- renderPlot({
chart1()
})
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
))
},
content = function(file) {
src <- normalizePath('report.Rmd')
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd', overwrite = TRUE)
library(rmarkdown)
out <- render('report.Rmd', switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
)
}
shinyApp(ui=ui, server=server)
R Markdown file:
---
title: "Download report"
author: "Test"
date: "24 October 2017"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(ggplot2)
library(shiny)
library(rmarkdown)
```
## Output plot
Should output plot, here:
```{r test plot, echo=FALSE}
chart1()
```
I must be missing something simple here!
The solution was very simple, but might help others.
The default setting in my Shiny app was to 'Run in Window' when used. However, simply changing this to 'Run External' allowed me to download reports as desired.
Hope this helps someone!
Based on this link I tried to include a table of contents in an HTML rmarkdown output. This works fine if I just knit it in RStudio, but when I try the same in Shiny, the table of contents doesn't show up. Am I doing something wrong or is this simply not possible? I also tried some custom css but that also doesn't seem to work. I need this because my users need to set some inputs and download an interactive document themselves with a toc. Please find an example below.
server.r
library(shiny)
library(rmarkdown)
library(htmltools)
library(knitr)
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$Generate_PDF_Document <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = paste0("Highchart Document",format(Sys.Date(),"%d%m%Y"),".html"),
content = function(file) {
# # Copy the report file to a temporary directory before processing it, in
# # case we don't have write permissions to the current working dir (which
# # can happen when deployed).
tempReport <- normalizePath('Test.Rmd')
file.copy(tempReport, "Test.Rmd", overwrite = FALSE)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
out <- render('Test.Rmd', html_document())
file.rename(out,file)
})
})
ui.r
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
downloadButton('Generate_PDF_Document','Generate a PDF Report')
)
)
))
rmarkdown doc:
---
title: "Test"
output:
html_document:
toc: true
toc_depth: 3
toc_float: true
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
Remove html_document() from render. I have not studied the details, but it looks like it forces override of the yaml front matter.
I am unable to get a desired HTML from running the code below. I attached the resulting "Output" file as a snapshot. The controls are empty and there is no plot. What am I doing wrong?
Thank you.
Rmarkdown code:
---
title: "Test"
output: html_document
---
```{r, echo=FALSE, results='asis', cache=FALSE}
#install.packages("devtools")
require(devtools)
install_github("ramnathv/rCharts")
install_github("yihui/knitr")
library(rCharts)
library(knitr)
n1 <- rPlot(mpg ~ wt, data = mtcars, color = "gear", type = "point")
n1$addControls("x", value = "wt", values = names(mtcars))
n1$addControls("y", value = "wt", values = names(mtcars))
n1$addControls("color", value = "gear", values = names(mtcars))
n1$show('iframesrc', cdn = TRUE)
```
My setup:
Windows 7 Pro, 64 bit.
RStudio version 0.99.892.
Note to install devtools when running the code attached.
I click on "Knit HTML" in RStudio to build.