gt table alignment in tufte Rmarkdown - r

I am including gt tables in a Rmarkdown Tufte-style HTML. I want to align the gt tables in the center of the main column, rather than in the center of the HTML spanning both the main column and margin. I have tried using the fig.align knitr option as well as tab.align command. Here is a repo with an rmd that shows the problem: https://github.com/cassidybargell/gt-tufte. The gt table spans the main column as well as the margin.
Example code of a gt table being used in the Tufte-HTML:
tibble(subject = "Joe",
ytreat = "13",
ycontrol = "9",
ydiff = "+4") %>%
gt()

Make your own css file is one way to fix it. Here are the lines of code:
.gt_table {
margin-left: 0 !important;
margin-right: 0 !important;
width: 55% !important;
}
Thank you to Yaodong Yu for the help!!

An alternative is to define a hook function:
knitr::knit_hooks$set(gtbl = function(before, options){
if (before) {
paste( '<style> .gt_table {width: 100% !important;} </style>',
'<div class="figure"><p class="caption marginnote shownote">',
options$fig.cap,
'</p>',
sep="")
} else { "</div>" }
})
inside a chunk. Then the chunk option gtbl can be used when a gt table is required as for example:
```{r gtbl=TRUE, fig.cap="*Table 1* Energy Trends"}
tblTrends()
```
where fig.cap supplies the caption right-aligned.
Hook functions are documented in the rmarkdown cookbook

Related

How can I add arbitrary elements to the Table of Contents in Bookdown?

I am making a book via bookdown.
I know it is possible to omit headings from the Table of Contents by adding the attributes {.unlisted .unnumbered}, as shown in Section 4.18 of the R Markdown Cookbook.
However, how can I add arbitrary content to the Table of Contents?
If I only needed to add this for the PDF output, I could use (e.g.) the LaTeX command \addcontentsline, but I need this to show in the HTML contents sidebar as well.
For example, if you set up a new default bookdown project from RStudio, it includes the file 01-intro.Rmd.
The first few lines are
# Introduction {#intro}
You can label chapter and section titles using `{#label}` after them, e.g., we can reference Chapter \#ref(intro). If you do not manually label them, there will be automatic labels anyway, e.g., Chapter \#ref(methods).
Figures and tables with captions will be placed in `figure` and `table` environments, respectively.
I need to be able to create arbitrary divs that are added to the table of contents, like so:
# Introduction {#intro}
You can label chapter and section titles using `{#label}` after them, e.g., we can reference Chapter \#ref(intro). If you do not manually label them, there will be automatic labels anyway, e.g., Chapter \#ref(methods).
::: {#arbitrary-header <some other attribute?>}
Figures and tables with captions will be placed in `figure` and `table` environments, respectively.
:::
Which would add the sentence "Figures and tables with captions will be placed in figure and table environments, respectively." in both the LaTeX Table of Contents and the sidebar on the HTML output.
The context of this problem is that I need to place a header inside another custom div that formats the content within a colorbox to make it stand out.
Otherwise, I could of course just add another heading via ## before the sentence above.
We could use an R function that prints a colored box and adds the title to the TOC depending on the output format. For gitbook output, this is easily done using HTML and markdown. For pdf_book we may use a LaTeX environment for colored boxes like tcolorbox.
Here is the function (define in a code block in .Rmd file):
block_toc <- function(title, level, content, output) {
if(output == "html") {
title <- paste(paste(rep("#", level), collapse = ""), title, "{-}")
cat('<div class = "myblock">', title, '<p>', content, '</p>\n</div>', sep = "\n")
} else {
level <- c("part", "chapter", "section")[level]
cat('\\addcontentsline{toc}{', level, '}{', title, '}',
'\n\\begin{mybox}\n\\textbf{\\noindent ', title, '}\n\\medskip\n\n', content,
'\n\n\\end{mybox}', sep = "")
}
}
Depending on the output format, block_toc() concatenates and prints the code for the blocks and, of course, also ensures that the title is added to the TOC. You can set the level of the TOC where the box title is added using level.
Use block_toc() like this in a chunk:
```{r, results='asis', echo=F, eval=T}
block_toc(
title = "Central Limit Theorem",
level = 2
content = "The CLT states that, as $n$ goes to infinity,
the sample average $\\bar{X}$ converges in distribution
to $\\mathcal{N}(\\mu,\\sigma^2/n)$.",
output = knitr::opts_knit$get("rmarkdown.pandoc.to")
)
```
output = knitr::opts_knit$get("rmarkdown.pandoc.to") will get and pass the current output format to the function when building the book.
Some styles for appealing boxes
Add to preamble.tex (for colored box in PDF output -- include file in YAML header). This will define a tcolorbox environment for generating blue boxes.
\usepackage{tcolorbox}
\definecolor{blue}{HTML}{D7DDEF}
\definecolor{darkblue}{HTML}{2B4E70}
\newtcolorbox{mybox}{colback=blue, colframe=darkblue}
Add to style.css (styles for HTML colored box) or include in a ```{css} code chunk:
.myblock {
background-color: #d7ddef;
border: solid #2b4e70;
border-radius: 15px;
}
.myblock p, .myblock h2, .myblock h3 {
padding: 5px 5px 5px 20px;
margin-top: 0px !important;
}
For HTML output (gitbook) this yields
and for LaTeX output (pdf_book) it looks like this
with a corresponding entry at the section level in the TOC.
Maybe this solution?
CSS-file:
k1 {
font-family: 'Times New Roman', Times, serif;
font-size: 12pt;
text-align: justify;
}
#TOC {
color:black;
background-color: white;
position: fixed;
top: 0;
left: 0;
width: 250px;
padding: 10px;
overflow:auto;
margin-left: -5px;
}
body {
max-width: 800px;
margin-left:300px;
line-height: 20px;
}
div#TOC li {
list-style:none;
}
h2#toc-title {
font-size: 24px;
color: Red;
}
Rmd-file:
---
title: "Arbitrary elements"
author: "Me"
date: "`r Sys.Date()`"
output:
bookdown::html_document2:
toc: true
css: "arb.css"
toc-title: "Contents"
---
# My question is it: "..."
# Introduction of our story ...
# It was a strange person ...
## The Flame was in his body ...
# <k1> Figures and tables with captions will be placed in `figure` and `table` environments, respectively. </k1> {-}
## Where is the love, friends?
We'll be using a Lua filter for this, as those are a good way to modify R Markdown behavior. The "Bookdown Cookbook" has an excellent overview and includes a description of how to use Lua filters.
The way we are doing this is to side-step the normal TOC generator and rewrite it in Lua. Then we add our new TOC as a meta value named table-of-contents (and toc, for compatibility), which is enough to be included in the output.
So first let's dump the code to create a normal TOC:
_ENV = pandoc
local not_empty = function (x) return #x > 0 end
local section_to_toc_item
local function to_toc_item (number, text, id, subcontents)
if number then
text = Span({Str(number),Space()} .. text, {class='toc-section-number'})
end
local header_link = id == '' and text or Link(text, '#' .. id)
local subitems = subcontents:map(section_to_toc_item):filter(not_empty)
return List{Plain{header_link}} ..
(#subitems == 0 and {} or {BulletList(subitems)})
end
section_to_toc_item = function (div)
-- bail if this is not a section wrapper
if div.t ~= 'Div' or not div.content[1] or div.content[1].t ~= 'Header' then
return {}
end
local heading = div.content:remove(1)
local number = heading.attributes.number
-- bail if this is not supposed to be included in the toc
if not number and heading.classes:includes 'unlisted' then
return {}
end
return to_toc_item(number, heading.content, div.identifier, div.content)
end
-- return filter
return {
{ Pandoc = function (doc)
local sections = utils.make_sections(true, nil, doc.blocks)
local toc_items = sections:map(section_to_toc_item):filter(not_empty)
doc.meta['table-of-contents'] = {BulletList(toc_items)}
doc.meta.toc = doc.meta['table-of-contents']
return doc
end
},
}
The code makes a few minor simplifications, but should produce an identical TOC for most documents. Now we can go on and modify the code to our liking. For example, to include divs with the class toc-line, the section_to_toc_item could be modified by adding this code at the start of the function:
section_to_toc_item = function (div)
if div.t == 'Div' and div.classes:includes('toc-line') then
return to_toc_item(nil, utils.blocks_to_inlines(div.content), div.identifier)
end
⋮
end
Modify the code as you see fit.
Also, if you want to exclude the extra TOC lines from the normal output, you'll have to filter them out. Let the script return a second filter to do that:
return {
{ Pandoc = function (doc) ... end },
{ Div = function (div) return div.classes:includes 'toc-line' and {} or nil end }
}

Numbered captions on customized and reactive figure in R markdown HTML file

In recent years, it has been possible to add numbering to the figure captions on R chunks in html_document2, as outlined in Yihui Xie's online text for bookdown. However, it has been more difficult to preserve this numbering while also having custom figures output from these chunks. For example, trying to create the custom figures using CSS flexbox from Carson Sievert's online text.
There are several other threads that discuss numbering HTML Rmd figures and using hooks or CSS counters to add custom numbering. However, I could not find a solution that allowed for a custom figure as well as html_document2 numbering to be preserved.
In the example below, I want a side-by-side plotly graphic to be reactive to screen size but also have the same figure caption and numbering.
---
output:
bookdown::html_document2:
self-contained: TRUE
---
```{css, echo=FALSE}
#dualpanel {
width: 50%
}
#media screen and (max-width: 500px) {
#dualpanel {
width: 100%
}}
```
```{r chunk1, echo=FALSE, htmlcap='FIRST FIGURE CAP'}
temp <- plotly::plot_ly(mtcars, x = ~cyl, y=~mpg)
shiny::div(class = 'figure',
style = "display: flex; flex-wrap: wrap; justify-content: center",
shiny::div(temp, id = 'dualpanel'),
shiny::div(temp, id = 'dualpanel'))
```
```{r chunk2, echo=FALSE, fig.cap='SECOND FIGURE CAP'}
plot(mtcars$cyl, mtcars$mpg)
```
This creates an output like this:
In order to address this issue, it is important to know that knitr uses #fig:label in pandoc in order to create the automated numbering in the output. You can see this when you examine the markdown temporary output from the knitr process:
<div class="figure">
<img src="web_tiles_v2_files/figure-html/otherchunk-1.png" alt="SECOND FIGURE CAP" />
<p class="caption">(\#fig:SPECIFICCHUNKOFINTEREST)SECOND FIGURE CAP</p>
</div>
As such, one should be able to maintain the customized figure output by adjusting the custom hook seen in other solutions. This would look like the following, just make sure you have the right chunk label included:
```{r}
knit_hooks$set(customcap= function(before, options, envir) {
if(!before) {
paste('<p class="caption"> (\\#fig:chunk1)',options$customcap,"</p>",sep="")
}
})
```
One could also use some of the internal knitr functions to automatically grab the fig.lp and label: paste('<p class="caption">', knitr:::create_label(options$fig.lp, options$label), options$customcap,"</p>", sep="")
The entire code would look like:
---
output:
bookdown::html_document2:
self-contained: TRUE
---
```{css, echo=FALSE}
#dualpanel {
width: 50%
}
#media screen and (max-width: 500px) {
#dualpanel {
width: 100%
}}
```
```{r}
knit_hooks$set(customcap= function(before, options, envir) {
if(!before) {
paste('<p class="caption"> (\\#fig:chunk1)',options$customcap,"</p>",sep="")
}
})
```
```{r chunk1, echo=FALSE, customcap='FIRST FIGURE CAP'}
temp <- plotly::plot_ly(mtcars, x = ~cyl, y=~mpg)
shiny::div(class = 'figure',
style = "display: flex; flex-wrap: wrap; justify-content: center",
shiny::div(temp, id = 'dualpanel'),
shiny::div(temp, id = 'dualpanel'))
```
```{r chunk2, echo=FALSE, fig.cap='SECOND FIGURE CAP'}
plot(mtcars$cyl, mtcars$mpg)
```
This produces an output that has the dynamic elements and maintains labeling.

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.

how to colour different Rmarkdown kable tables in different colour

Below is the code I am using. Only problem is that both my tables are of same colour which is my second colour code (#ffff99). How can I keep the background of both tables different.
<style>
table {
background-color:#eff8e5;
}
</style>
``` {r}
kable(df1)
```
<style>
table {
background-color:#ffff99;
}
</style>
``` {r}
kable(df2)
```
HTML/CSS is not rendered the way you implicitly assume. Your code would work as expected if the rendering followed a procedure like:
set: "tables are green"
output green table
set: "tables are yellow"
output yellow table
But this is not the case. What actually happens is:
set: "all tables are green"
output table 1
(table 1 is green)
set: "all tables are yellow"
output table 2
(table 1 and table 2 are yellow)
As a solution, you could use two different classes:
<style>
.lightgreen {
background-color:#eff8e5;
}
.yellow {
background-color:#ffff99;
}
</style>
(Optimally, class names should describe the reason why the class is used and not how the class currently looks like, but without further information "lightgreen" and "yellow" are the best names I came up with).
Now you need to tell kable that the tables should get these classes assigned.
Option 1:
kable(df1, format = "html", table.attr = "class=\"lightgreen\"")
kable(df2, format = "html", table.attr = "class=\"yellow\"")
However, this strips most of the (probably desired) default table layout.
Option 2: Add a container around the tables and style tables in that container.
<style>
.lightgreen table {
background-color:#eff8e5;
}
.yellow table {
background-color:#ffff99;
}
</style>
<div class = "lightgreen">
```{r}
library(knitr)
df1 <- data.frame(a=1:10, b=2:11)
kable(df1)
```
</div>
<div class = "yellow">
```{r}
df2 <- data.frame(a=1:10, b=2:11)
kable(df2)
```
</div>

Display a data frame as table in R Markdown

In knitr I want to add a (small) data frame as a table using the kable package:
---
output: html_document
---
```{r}
knitr::kable(mtcars[1:5,1:5], format="html")
```
This returns a compact table as above, while changing it to format="markdown"returns a nice table but spanning the whole page:
I have found the knitr manual but it does not cover the extra formatting options for each format. How can I change the size of a knitr table or even better, where can I get this information from?
The general approach would be to use your own custom CSS and include that in the YAML at the start of the document.
You can actually sort of do this from within your document, but I would suggest editing your CSS outside of the document and working from there.
Here's a minimal example:
---
title: "Test"
date: "24 October 2015"
output:
html_document:
css: mystyle.css
---
```{r, results='asis'}
writeLines("td, th { padding : 6px } th { background-color : brown ; color : white; border : 1px solid white; } td { color : brown ; border : 1px solid brown }", con = "mystyle.css")
dset1 <- head(ToothGrowth)
knitr::kable(dset1, format = "html")
```
This should:
Create a file named "mystyle.css" with your relevant CSS styling.
Produce something that looks something like the following.

Resources