R markdown: datable within collapsible section - r
Below is a R-markdown document with <details> tags to create collapsible sections.
Can you help me to render the datatable from section 2 in the html output?
Minimal reproducible example
### Section 1
<details> <summary>Click to expand</summary>
```{r, echo=FALSE}
head(iris)
```
</details>
### Section 2
<details> <summary>Click to expand</summary>
```{r, echo=FALSE}
DT::datatable(iris)
```
</details>
This is not really an answer, but slightly too long to be a comment, so I've included it here. Hopefuly someone can use it to work out an actual answer:
The good new is that it is definitely "possible". The bad news is "it is not easy". With my limited knowledge of web-dev the problem seems to be, that DT::datatable (or more correctly htmlwidgets:::print.html_widget) creates an entire html-webpage in a temporary file, and this is the default method for visualizing DT::datatable. The file itself looks something like
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<style>body{background-color:white;}</style>
<script src="lib/htmlwidgets-1.5.3/htmlwidgets.js"></script>
<script src="lib/jquery-1.12.4/jquery.min.js"></script>
<link href="lib/datatables-css-0.0.0/datatables-crosstalk.css" rel="stylesheet" />
<script src="lib/datatables-binding-0.16/datatables.js"></script>
<link href="lib/dt-core-1.10.20/css/jquery.dataTables.min.css" rel="stylesheet" />
<link href="lib/dt-core-1.10.20/css/jquery.dataTables.extra.css" rel="stylesheet" />
<script src="lib/dt-core-1.10.20/js/jquery.dataTables.min.js"></script>
<link href="lib/crosstalk-1.1.0.1/css/crosstalk.css" rel="stylesheet" />
<script src="lib/crosstalk-1.1.0.1/js/crosstalk.min.js"></script>
</head>
<body>
<div id="htmlwidget_container">
<div id="htmlwidget-cd5f37d21433eb2088ae" style="width:960px;height:500px;" class="datatables html-widget"></div>
</div>
<script type="application/json" data-for="htmlwidget-cd5f37d21433eb2088ae">{"x":{"filter":"none","data":[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70","71","72","73","74","75","76","77","78","79","80","81","82","83","84","85","86","87","88","89","90","91","92","93","94","95","96","97","98","99","100","101","102","103","104","105","106","107","108","109","110","111","112","113","114","115","116","117","118","119","120","121","122","123","124","125","126","127","128","129","130","131","132","133","134","135","136","137","138","139","140","141","142","143","144","145","146","147","148","149","150"],[5.1,4.9,4.7,4.6,5,5.4,4.6,5,4.4,4.9,5.4,4.8,4.8,4.3,5.8,5.7,5.4,5.1,5.7,5.1,5.4,5.1,4.6,5.1,4.8,5,5,5.2,5.2,4.7,4.8,5.4,5.2,5.5,4.9,5,5.5,4.9,4.4,5.1,5,4.5,4.4,5,5.1,4.8,5.1,4.6,5.3,5,7,6.4,6.9,5.5,6.5,5.7,6.3,4.9,6.6,5.2,5,5.9,6,6.1,5.6,6.7,5.6,5.8,6.2,5.6,5.9,6.1,6.3,6.1,6.4,6.6,6.8,6.7,6,5.7,5.5,5.5,5.8,6,5.4,6,6.7,6.3,5.6,5.5,5.5,6.1,5.8,5,5.6,5.7,5.7,6.2,5.1,5.7,6.3,5.8,7.1,6.3,6.5,7.6,4.9,7.3,6.7,7.2,6.5,6.4,6.8,5.7,5.8,6.4,6.5,7.7,7.7,6,6.9,5.6,7.7,6.3,6.7,7.2,6.2,6.1,6.4,7.2,7.4,7.9,6.4,6.3,6.1,7.7,6.3,6.4,6,6.9,6.7,6.9,5.8,6.8,6.7,6.7,6.3,6.5,6.2,5.9],[3.5,3,3.2,3.1,3.6,3.9,3.4,3.4,2.9,3.1,3.7,3.4,3,3,4,4.4,3.9,3.5,3.8,3.8,3.4,3.7,3.6,3.3,3.4,3,3.4,3.5,3.4,3.2,3.1,3.4,4.1,4.2,3.1,3.2,3.5,3.6,3,3.4,3.5,2.3,3.2,3.5,3.8,3,3.8,3.2,3.7,3.3,3.2,3.2,3.1,2.3,2.8,2.8,3.3,2.4,2.9,2.7,2,3,2.2,2.9,2.9,3.1,3,2.7,2.2,2.5,3.2,2.8,2.5,2.8,2.9,3,2.8,3,2.9,2.6,2.4,2.4,2.7,2.7,3,3.4,3.1,2.3,3,2.5,2.6,3,2.6,2.3,2.7,3,2.9,2.9,2.5,2.8,3.3,2.7,3,2.9,3,3,2.5,2.9,2.5,3.6,3.2,2.7,3,2.5,2.8,3.2,3,3.8,2.6,2.2,3.2,2.8,2.8,2.7,3.3,3.2,2.8,3,2.8,3,2.8,3.8,2.8,2.8,2.6,3,3.4,3.1,3,3.1,3.1,3.1,2.7,3.2,3.3,3,2.5,3,3.4,3],[1.4,1.4,1.3,1.5,1.4,1.7,1.4,1.5,1.4,1.5,1.5,1.6,1.4,1.1,1.2,1.5,1.3,1.4,1.7,1.5,1.7,1.5,1,1.7,1.9,1.6,1.6,1.5,1.4,1.6,1.6,1.5,1.5,1.4,1.5,1.2,1.3,1.4,1.3,1.5,1.3,1.3,1.3,1.6,1.9,1.4,1.6,1.4,1.5,1.4,4.7,4.5,4.9,4,4.6,4.5,4.7,3.3,4.6,3.9,3.5,4.2,4,4.7,3.6,4.4,4.5,4.1,4.5,3.9,4.8,4,4.9,4.7,4.3,4.4,4.8,5,4.5,3.5,3.8,3.7,3.9,5.1,4.5,4.5,4.7,4.4,4.1,4,4.4,4.6,4,3.3,4.2,4.2,4.2,4.3,3,4.1,6,5.1,5.9,5.6,5.8,6.6,4.5,6.3,5.8,6.1,5.1,5.3,5.5,5,5.1,5.3,5.5,6.7,6.9,5,5.7,4.9,6.7,4.9,5.7,6,4.8,4.9,5.6,5.8,6.1,6.4,5.6,5.1,5.6,6.1,5.6,5.5,4.8,5.4,5.6,5.1,5.1,5.9,5.7,5.2,5,5.2,5.4,5.1],[0.2,0.2,0.2,0.2,0.2,0.4,0.3,0.2,0.2,0.1,0.2,0.2,0.1,0.1,0.2,0.4,0.4,0.3,0.3,0.3,0.2,0.4,0.2,0.5,0.2,0.2,0.4,0.2,0.2,0.2,0.2,0.4,0.1,0.2,0.2,0.2,0.2,0.1,0.2,0.2,0.3,0.3,0.2,0.6,0.4,0.3,0.2,0.2,0.2,0.2,1.4,1.5,1.5,1.3,1.5,1.3,1.6,1,1.3,1.4,1,1.5,1,1.4,1.3,1.4,1.5,1,1.5,1.1,1.8,1.3,1.5,1.2,1.3,1.4,1.4,1.7,1.5,1,1.1,1,1.2,1.6,1.5,1.6,1.5,1.3,1.3,1.3,1.2,1.4,1.2,1,1.3,1.2,1.3,1.3,1.1,1.3,2.5,1.9,2.1,1.8,2.2,2.1,1.7,1.8,1.8,2.5,2,1.9,2.1,2,2.4,2.3,1.8,2.2,2.3,1.5,2.3,2,2,1.8,2.1,1.8,1.8,1.8,2.1,1.6,1.9,2,2.2,1.5,1.4,2.3,2.4,1.8,1.8,2.1,2.4,2.3,1.9,2.3,2.5,2.3,1.9,2,2.3,1.8],["setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","setosa","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","versicolor","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica","virginica"]],"container":"<table class=\"display\">\n <thead>\n <tr>\n <th> <\/th>\n <th>Sepal.Length<\/th>\n <th>Sepal.Width<\/th>\n <th>Petal.Length<\/th>\n <th>Petal.Width<\/th>\n <th>Species<\/th>\n <\/tr>\n <\/thead>\n<\/table>","options":{"columnDefs":[{"className":"dt-right","targets":[1,2,3,4]},{"orderable":false,"targets":0}],"order":[],"autoWidth":false,"orderClasses":false}},"evals":[],"jsHooks":[]}</script>
<script type="application/htmlwidget-sizing" data-for="htmlwidget-cd5f37d21433eb2088ae">{"viewer":{"width":450,"height":350,"padding":15,"fill":true},"browser":{"width":960,"height":500,"padding":40,"fill":false}}</script>
</body>
</html>
with data and header being obviously variable depending on the data.
Now if we inspect and edit the page while it is active by
In Rstudio call DT::datatable(iris) to show the table
Click the "show in new window" to open it in your preferred browser
Right-click anywhere on the page and click "Inspect element (Q)"
Right-click on "body" and click "Edit as HTML"
Finally add the <details> / </details> at the start and end of <body>
Then we can actually see that it works as we would expect (closed first):
(open now):
So this is a clear conclusion that "it is possible". The problem is extracting the code. Walking down into DT::datatable you will eventually find that it calls htmlwidgets:::print.html_widget to open the actual html-page. This lets us recreate a script and extract the actual html code used in the widget:
#' Generate html and make dependencies available in directory for a DT::datatable
#'
#' #param x a data.frame or DT::datatable
#' #param dir the (root) directory for the project/dependencies. See details
#' #param background background for the html widget
#' #param libdir directory to export dependencies to
#'
#' #details This function generates the html that is usually generated when
#' printing DT::datatable, and exports dependencies to a given directory, making
#' it useful for embedding the html into a markdown file or shiny script, either
#' running and saving this in the pre-amble/header or interactively. "Dir"
#' can be used to specify the project root, with "libdir" specifying the path
#' relative from "dir" to place dependencies. Note that this likely enforces
#' the html file to be placed in the project root, and not a sub-folder of the
#' project.
datatable_html <- function(x, dir = getwd(), background = "white", libdir = 'lib'){
if(is.data.frame(x))
x <- DT::datatable(x)
#from htmlwidgets:::print.html_widgets
x <- htmltools::as.tags(x, standalone = TRUE)
#from htmltools::save_html (called by print.html_widgets
x <- htmltools::renderTags(x)
deps <- lapply(x$dependencies, function(dep) {
dep <- htmltools::copyDependencyToDir(dep,
libdir,
FALSE)
dep <- htmltools::makeDependencyRelative(dep, dir, FALSE)
dep
})
bodyBegin <- if (!isTRUE(grepl("<body\\b", x$html[1],
ignore.case = TRUE))) {
"<body>"
}
bodyEnd <- if (!is.null(bodyBegin)) {
"</body>"
}
c("<!DOCTYPE html>", "<html>", "<head>",
"<meta charset=\"utf-8\"/>", sprintf("<style>body{background-color:%s;}</style>",
htmltools::htmlEscape(background)),
htmltools::renderDependencies(deps, c("href", "file")), x$head, "</head>",
bodyBegin, # <=== body starts here, maybe remove?
x$html,
bodyEnd, # <=== Body ends here, maybe remove?
"</html>")
}
dt_html <- datatable_html(DT::datatable(iris))
# print (very large output):
cat(dt_html)
now dt_html contains the html segments in a vector, and the dependencies are copied to {dir}/{libdir} which should be a folder under the root of the markdown project. A few things to note: The html vector has the dependencies in dt_html[6] (may have to be included in the markdown pre-amble?) and the htmlscript itself is in dt_html[10] with body tags in dt_html[9] and dt_html[11] respectively.
I am not skilled enough with html embedding in Rmarkdown to be sure where to go from here, but I am certain that there will be some efficionados out there that has the proficiency to abuse this and providing the final part of the answer. I am assuming a combination of document dependencies for the header and then using the html segment in dt_html somehow should do the job.
Out of the box, reactable will work with similar output and configurations.
Within an Rmd document:
<details><summary>Click to expand</summary>
```{r}
library(reactable)
reactable(mtcars)
```
</details>
Which renders to:
This should work:
# Section 3
```{r}
library(shiny)
library(DT) # make sure you load DT *after* shiny
# Render
renderDataTable({
datatable(iris) %>% formatStyle(
'Sepal.Width',
backgroundColor = styleInterval(3.4, c('gray', 'yellow'))
)
})
```
It really bugged me that I couldn't figure it out, so I googled a bit and this should help you: https://blog.rstudio.com/2015/06/24/dt-an-r-interface-to-the-datatables-library/
The results is:
Related
Pass body of Rmarkdown chunk as argument to child document
I've designed an expandable info box for my blog (which is rendered from Rmarkdown) which I want to use as a template. At the momentan I just write more or less plain HTML in the main Rmarkdown document, as below: <div class="info" markdown="1"> <details> <summary class="info-header" markdown="1"> Title <i class="fas fa-info-circle"></i> </summary> <p class="info-details"> Here goes the body </p> </details> </div> With some CSS this renders nicely: Ideally I would like to replace the HTML above by using some kind of child document which has a title argument to specify the title, and (and this is the tricky part) which passes the whole body of the Rmarkdown chunk to the body section of the child document. So ideally the above HTML could be written as. ```{r, child = "info_box.Rmd", title = "My Title"} Here goes the body ``` Is this possible? I understand how to insert a child document, also with arguments, and when looking at rmarkdown::hmtl_document() I do get a glimpse of how the use real arguments like title, but can we pass the body of the Rmarkdown chunk down to the child so that it is used at a specific place? Do we need a custom output format for this and how would it look like? Any help appreciated. I'm also open for other solutions, but it would be more than great if the ideal approach above would work.
I am giving another answer which is based on knitr output hooks and Pandoc Lua filter that also works fine for rmarkdown::html_document (and probably a better approach than the previous one). Pass the child document path to the chunk option child_into_box and specify the box title to option box_title. One very important detail to note is that you must at least insert a comment in that chunk, otherwise for an empty chunk the redefined knitr source hook does not work. --- title: Passing Child document Text to Info box. output: html_document: pandoc_args: - --lua-filter=box_wrap.lua --- ## Rmarkdown Some text ```{r} #| echo: false library(knitr) default_source_hook <- knit_hooks$get('source') knit_hooks$set( source = function(x, options) { if(is.null(options$child_into_box)) default_source_hook(x, options) else { res <- knitr::knit_child(input = options$child_into_box, envir = environment(), quiet = TRUE) div_start = paste0("::: {wrap-box=true box-title='", options$box_title, "'}") paste0(div_start, "\n", unlist(res), "\n", "\n:::\n") } } ) ``` Some more text ```{r} #| child_into_box: info_box.Rmd #| box_title: my info test box # comment ``` box_wrap.lua local str = pandoc.utils.stringify local template_info_box_p1 = [[ <div class="note" markdown="1"> <details> <summary class="note-header" markdown="1"> %s<i class="fas fa-info-circle"></i> </summary> <div class="note-details"> ]] local template_info_box_p2 = [[ </div> </details> </div> ]] function Div(el) if el.attributes['wrap-box'] then local title = str(el.attributes['box-title']) local info_box = string.format(template_info_box_p1, title) local info_box_rb1 = pandoc.RawBlock('html', info_box) local info_box_rb2 = pandoc.RawBlock('html', template_info_box_p2) el.content:insert(1, info_box_rb1) el.content:insert(info_box_rb2) return el end end
Since the output format is HTML, a possible solution based on pandoc lua filter and Javascript is as follows, main.Rmd --- title: Passing Child document Text to Info box. output: html_document: includes: after_body: infoBox.html pandoc_args: - --lua-filter=info_box.lua --- ## Rmarkdown ::: {.info-box title="My new Title" #first} ::: ::: {.add-to-info #first} ```{r} #| child: info_box.Rmd ``` Also some random text to be inserted into that info box ::: ::: {.info-box title="More info box" #second} ::: ::: {.add-to-info #second} ```{r} #| child: info_box.Rmd ``` Also some random text to be inserted into that info box ::: So to add contents from child-document to the info box you need to do two thing. Firstly, create a pandoc div (using :::) with class .info-box, give it title that you want and give a unique id (suppose, #first) so that we could use it to insert the content of a child document to this specific info box. secondly, wrap the code chunk with the child option with another pandoc div associated with class .add-to-info and use the id of the info box to where you want the content of this child document to be. Now following these two steps you can generate as many as info box you want. info_box.Rmd Lorem ipsum dolor sit amet, eget, etiam, a metus purus sit quisque elit, suscipit. ```{r} 1 + 1 ``` ```{r} plot(1:10) ``` ```{r} head(mtcars) ``` (no need to use title or output for the child document, it simply contains the body text) info_box.lua local template_info_box_p1 = [[ <div class="info" markdown="1"> <details> <summary class="info-header" markdown="1"> %s <i class="fas fa-info-circle"></i> </summary> <p class="info-details" id="%s"> ]] local template_info_box_p2 = [[ </p> </details> </div> ]] function Div(el) if el.classes:includes('info-box') then local title = el.attributes['title'] local id = el.identifier local info_box_p1 = string.format(template_info_box_p1, title, id) local info_box_html_p1 = pandoc.RawBlock('html', info_box_p1) local child_content = el.content local info_box_html_p2 = pandoc.RawBlock('html', template_info_box_p2) return pandoc.Div({info_box_html_p1, info_box_html_p2}) end end infoBox.html <script> function add_to_info() { let childs = document.querySelectorAll("div.add-to-info"); let info_box = document.querySelectorAll('p.info-details'); childs.forEach(el => { info_box.forEach(box => { if (el.id === box.id) { box.appendChild(el); } }); }); } window.onload = add_to_info(); </script> A portion of the rendered ouput Note that, this output lacks the necessary CSS styles along with fontawesome icon, which you can handle accordingly using the embedded classes info-header and info-details.
I found a first answer looking at this SO post: I could create a template info_box.Rmd like: --- title: "" output: rmarkdown::html_document --- <div class="note" markdown="1"> <details> <summary class="note-header" markdown="1"> `r title`<i class="fas fa-info-circle"></i> </summary> <p class="note-details"> `r body` </p> </details> </div> And then replace the intial HTML from my post with: ```{r, echo = FALSE, results='asis'} title <- "My new Title" body <- "The new body" cat( knitr::knit_child("info_box.Rmd", envir = environment(), quiet = TRUE) ) ``` And it works: However, I'd still prefer a solution looking like this: ```{r, child = "info_box.Rmd", title = "My Title"} Here goes the body ```
How can I adjust the style of the output from a .Rmd chunk?
Here is an example code chunk and it's output. `{r example, message = F} for (i in 1:5) { print(i) } ` I would like this to render in my output file without the border box, and without the leading ## [1]. Is that possible?
This solution also removes the border box. Use the r chunk comment option to remove the ## character. Use cat() instead of print() to display the output without the R formatting [1]. You need to specify in cat() that you want newlines added. One method to remove the border box would be to use css. You can use an external css file, or make a dedicated hidden chunk to specify it. I noticed the code chunks and output chunks were both specified by the <pre> tag, with the code chunk being of class .r, and the output chunk being .hljs. These might change with different themes, but this selector worked for me. pre.hljs might work alternatively as a selector. Below is a complete .Rmd file that can be knit to an html document --- title: example.Rmd output: html_document --- ```{css, echo = FALSE} pre:not(.r) { border: 0px; } ``` ```{r, comment = ""} for (i in 1:5) { cat(i, "\n") } ```
Use the following code {r example, message = FALSE, comment = ''} for (i in 1:5) { cat(i, '\n') }
Define a class of slides with inverse background in revealjs/Quarto
I would like to have some of the slides inverse. Notably, I would like to have the level 1 slides (these with, by default <h1> level 1 headers) inverse colors: white on black, for example. This can be achieved as follows: define a class .inverse, and specify the background color and the .inverse class in the header of the slide For example, include this in the style.scss file associated with the presentation: .inverse h1 { color: white; } And use the following to make the slide inversed # Level 1 header {.inverse background-color="black"} This works. However, it requires a manual specification of background and class for each slide which I would like to be inversed. Is there a way of setting it up globally, such that the contents of the curly brackets are not necessary and all level 1 slides are inverted automatically?
You can use Pandoc Lua filters to use the inverse class and background-color="black" for all level 1 headers automatically. MWE --- title: "Level 1 header" format: revealjs keep-md: true filters: [bg_style.lua] --- ```{css, include=FALSE} .inverse h1 { color: white; } ``` ## Quarto Quarto enables you to weave together content and executable code into a finished presentation. To learn more about Quarto presentations see <https://quarto.org/docs/presentations/>. # Level 1 header ## Bullets When you click the **Render** button a document will be generated that includes: - Content authored with markdown - Output from executable code # Level 1 header ## Code When you click the **Render** button a presentation will be generated that includes both content and the output of embedded code. You can embed code like this: ```{r} 1 + 1 ``` bg_style.lua function Header(el) if el.level == 1 then table.insert(el.classes, "inverse") el.attributes["data-background-color"] = 'black' return el end end
Preventing <code> tags within <pre>
I am writing documentation using R Markdown. After "knitting", the resulting markdown source might look like this: The variables `x` and `p` are related as follows: ```r x <- 1 c(x = x, p = pnorm(x)) ``` ```out x p 1.0000000 0.8413447 ``` ... which when converted using pandoc (with syntax highlighting disabled), results in: The variables <code>x</code> and <code>p</code> are related as follows: <pre class="r"><code>x <- 1 c(x = x, p = pnorm(x))</code></pre> <pre class="out"><code> x p 1.0000000 0.8413447</code></pre> The problem is that the <code> tag is used, unclassed, in both the body text and the pre-formatted sections. In my case, I would like to write a CSS file that styles the code and output chunks (the R code with class r and the output with class out) with different colors, and also displays in-text code in a different color than other body text. I can define colors for the r and out classes; but if I also define a color for the code tag (which I think is very helpful for readability of the text), it overrides those colors in the code and output chunks. If the <code> tags weren't in the <pre> sections (they seem unnecessary), I'd be fine. Is there a way to get pandoc to omit the <code> tags in the pre-formatted sections? (Or alternatively, to add my classes to the <code> tags instead of <pre>?) I don't want to use syntax highlighting; just the context highlighting I have described.
OK, duh... After further reading on CSS selectors, I can specify that code inherits its color for certain classes. So in my .css file, I now have: code { color: #400000; } .r {color: #800000; } .r code { color: inherit; } .out { color: #008000; } .out code { color: inherit; } ... and now I can get 3 different font colors for those situations.
Saving html to pdf in chrome
I am using rmarkdown to generate an HTML report. I am on a restricted machine, can't install tex. So, I was trying to generate an HTML document and then convert/print it to a pdf. The example markdown document is: --- title: "trials" author: "Foo Bar" date: "15 December 2016" output: html_document --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` ```{r cars, echo=FALSE, cache=FALSE, message=FALSE} library(dplyr, quietly = TRUE) library(abind, quietly = TRUE) virginica <- iris %>% filter(Species == "virginica") %>% head() %>% select(-Species) setosa <- iris %>% filter(Species == "setosa") %>% head() %>% select(-Species) diff_mat <- virginica - setosa diff_mat[diff_mat<0] <- '<font color="green">⇓ </font>' diff_mat[diff_mat>0] <- '<font color="red">⇑ </font>' diff_mat[diff_mat == 0] <- '<font color="blue">⇔ </font>' datArray <- abind::abind(virginica, diff_mat, along=3) fin_dat <- apply(datArray,1:2, function(x)paste(x[1],x[2], sep = " ")) knitr::kable(fin_dat, format = "html", escape = FALSE, table.attr = "border=1", caption = "Changes across species") ``` I can't knit to word either as the formatting is lost as discussed in HTML formatted tables in rmarkdown word document. The HTML produced is exactly what I wanted. HTML to word using save as in word works mostly fine with some issues and I can print pdf but it is not as good as directly printed from pdf. when I try to save it as pdf in chrome the colour is lost. There is no issues in print options Other pages such as this question in our beloved site Replace NA's using data from Multiple Columns prints fine Do you have any pointers where I am missing a point or where the issue is.
Add this right after the YAML header: <style> #media print { font[color="green"] { color: #00ff00!important; -webkit-print-color-adjust:exact; } font[color="red"] { color: #ff0000!important; -webkit-print-color-adjust:exact; } } </style> The problem is that RStudio's default R markdown templates use Bootstrap and their version of bootstrap.min.css has: #media print { *, *:before, *:after { color: #000 !important; text-shadow: none !important; background: transparent !important; -webkit-box-shadow: none !important; box-shadow: none !important; } in it. That's a pretty "destructive" media query as the *'s cause those settings to be applied to all tags and color: #000 !important; means "no color for YOU!" when you print a document. I grok the sentiment behind that (saving the planet + toner/ink costs) but if you're printing to PDF it makes no sense whatsoever. Unfortunately, there are no hyper-targeted media queries for printing to PDF, so the generic "print" ones get applied when you print web pages to PDFs and these mindless, catch-all media queries take over. The problem for you is that you'll need to be very specific in targeting any other tags to override these settings. Which means adding your own CSS classes to anything you generate in Rmds or getting cozy with "Inspect Element" until you catch'em all. However, if you're feeling adventurous you can modify the YAML header to be: output: html_document: self_contained: false When you render to HTML it'll create a directory with subdirectories for the various components vs base64-encode them into one big document. I named my document forso.Rmd which means it made a directory called forso_files and put subdirs under it. Open up the main HTML file and scroll down until you see something like: <script src="forso_files/jquery-1.11.3/jquery.min.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link href="forso_files/bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet" /> <script src="forso_files/bootstrap-3.3.5/js/bootstrap.min.js"></script> <script src="forso_files/bootstrap-3.3.5/shim/html5shiv.min.js"></script> <script src="forso_files/bootstrap-3.3.5/shim/respond.min.js"></script> <script src="forso_files/navigation-1.1/tabsets.js"></script> Change this: <link href="forso_files/bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet" /> to: <link href="forso_files/bootstrap-3.3.5/css/bootstrap.css" rel="stylesheet" /> Edit bootstrap.css, remove the color: #000 !important; line and add the -webkit-print-color-adjust:exact; line. SAVE A COPY OF bootstrap.css ELSEWHERE as it'll get squashed on future renders (i.e. you'll need to copy it back on every render). You can't just link to a separate CSS file with a less brain dead print media query since the color: #000 !important; impacts all tags thanks to the * target and you can't just reset it to initial or inherit` because that will just turn them black as well. Your final (and probably best) option is to make your own R Markdown template (see https://github.com/hrbrmstr/markdowntemplates for more info) and avoid placing over-arching print media queries in it.