I use kbl() function, in a rnw file that I compile in a pdf with knitr, to make a table starting from a dataframe. I use kableExtra option scale_down to adapt the table size to page size. It works fine but the table overlay with the page number of my pdf output. I'd like to know what's the best way to handle this type of problem. Thanks in advance for the help.
You could add some Latex code that puts the tabular environment into a box and resizes the content. Below is an example using \resizebox
Here's tab, a LaTex table with Gaussian random numbers generated by kable:
```{r, message = F, warning=F}
library(knitr)
library(tidyverse)
library(kableExtra)
ncol <- 10
nrow <- 30
df <- map_dfc(1:ncol, ~ data.frame(round(rnorm(nrow), 2))) %>%
set_names(letters[1:ncol])
tab <- kbl(df, format = "latex")
```
And here's how to resize it by text height/width using resizebox (see this post on tex.stackexchange for details on how the scaling works)
```{r, results='asis'}
cat(
"\\begin{table}
\\centering
\\resizebox*{\\textwidth}{\\dimexpr\\textheight-2\\baselineskip\\relax}{%",
tab,
"\n}
\\end{table}"
)
```
Result for the 30x10 table
Let's double rows and columns (ncol <- 20; nrow <- 60)
Result for 60x20 table.
I have three suggestions. The first one is maybe set your table to the next page using \newpage in your Rmarkdown code which is latex code. The second option is maybe set latex_options="HOLD_position" in your Kable_styling function. This will set the table at a certain place which maybe could help your problem. The third option is using 'longtable = TRUE` which means that the table continues on the next page. Here is the code for option one and two with:
```{r}
library(knitr)
library(tidyverse)
library(kableExtra)
df <- data.frame(x = 1:10, y = 11:20)
kable(df) %>%
kable_styling(latex_options = "HOLD_position")
```
\newpage
```{r}
kable(df) %>%
kable_styling(latex_options = "HOLD_position")
```
Which looks like this:
Here is the code for option three:
```{r}
library(tidyverse)
library(knitr)
library(kableExtra)
df <- data.frame(x = 1:50, y = 11:60)
kable(df, "latex", longtable = T, booktabs = T) %>%
kable_styling(latex_options = c("repeat_header"), font_size = 7)
```
Looks like this:
Related
How to insert escape characters into dataframe?
It will be useful for the formatting of text data into table packages.
We could be use one universal solution for every table package (my hope).
But now we should employ a lot of approaches for the every case (depends on libraries and output formates: pdf, html).
It is really uncomfortable!
For example, we have next data
df <- data.frame("names" = c("a long long long long long ... pretty long name of the our story","Here is also long, but a little shorter"))
We see a normal output
names
1 a long long long long long ... pretty long name of the our story
2 Here is also long, but a little shorter
But how we can achieve this output ("\n")?
names
1 a long long long long long
... pretty long name of the our story
2 Here is also long, but a little shorter
I promised to add a simple example:
knit to HTML, in PDF doesn't work
```{r warning = FALSE, echo = FALSE, message=FALSE, include=FALSE,}
library(flextable)
library(gt)
#data
df <- data.frame("names" = c("a long long long \n long long ... <br> pretty long name of the our story","Here is also long, but a little shorter"))
#table one
table3 <- flextable(df)
table3 <- set_table_properties(table3, layout = "autofit", width = .5)
table3
#table two
table4 <- gt(df) %>% fmt_markdown(columns = everything())
table4
```
<center>
<caption>Table in flextable </caption>
</center>
`r table3`
<center>
<caption>Table in gt </caption>
</center>
`r table4`
In the first case - works \n, in the second - /br/ and there are only two packages!
Don't add any line breaks to your text!! This is absolutely unnecessary. All you need is the skillful use of the kableExtra package. Note the code below is the content from the RMarkdown.
The document created with it can be found here.
Add everything from ## RMarkdown Start to ## RMarkdown End to RMarkdown
Of course, don't forget to remove the comment characters before the code blocks (#```)!!
## RMarkdown Start
---
title: "LongText"
author: "Marek Fiołka"
date: "30 11 2021"
output:
html_document: default
pdf_document: default
---
#```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#```
Prepare data frame with long text
#```{r echo=TRUE, message=FALSE, warning=FALSE}
library(stringi)
library(tidyverse)
library(kableExtra)
n=50
df = tibble(
id = 1:n,
txt = stri_rand_lipsum(n)
)
#```
See the data frame in a typical display
#```{r}
print(df)
#```
View data frame formatted with Kable Extra for HTML
#```{r}
df %>% kbl() %>%
kable_styling()
#```
View data frame formatted with Kable Extra for PDF
#```{r}
df %>% kbl() %>%
kable_paper(full_width = F) %>%
column_spec(1, bold = T, border_right = T) %>%
column_spec(2, width = "30em")
## RMarkdown End
This way you can create not only html documents but also corresponding pdf documents. Below is a fragment of a document created in this format. Note that in this case you have to use kable_paper with column_spec instead of kable_styling.
Hope this is what you were looking for.
Update
## RMarkdown Start
---
title: "LongText"
author: "Marek Fiołka"
date: "30 11 2021"
output:
pdf_document: default
html_document: default
---
#```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
#```
Prepare data frame with long text
#```{r echo=TRUE, message=FALSE, warning=FALSE}
library(stringi)
library(tidyverse)
library(kableExtra)
n=10
df = tibble(
id = 1:n,
txt = stri_rand_lipsum(n)
)
#```
See the data frame in a typical display
#```{r echo=TRUE}
print(df)
#```
View data frame formatted with [kableExtra](http://haozhu233.github.io/kableExtra/) for HTML
#```{r}
df %>% kbl() %>%
kable_styling()
#```
View data frame formatted with [kableExtra](http://haozhu233.github.io/kableExtra/) for PDF
#```{r}
df %>% kbl() %>%
kable_paper(full_width = F) %>%
column_spec(1, bold = T, border_right = T) %>%
column_spec(2, width = "30em")
#```
View data frame formatted with [gt](https://gt.rstudio.com/index.html) (only for HTML)
#```{r}
library(gt)
df %>% gt %>%
fmt_markdown(columns = everything()) %>%
tab_options(table.width = px(400))
#```
View data frame formatted with [flextable](https://davidgohel.github.io/flextable/articles/overview.html) HTML & PDF
#```{r message=FALSE, warning=FALSE}
library(flextable)
df %>% flextable %>% width(2, width = 6, unit = "in")
#```
View data frame formatted with [huxtable](https://hughjonesd.github.io/huxtable/) HTML & PDF
#```{r message=FALSE, warning=FALSE}
library(huxtable)
df %>% as_hux %>%
set_width(1) %>%
set_right_border(everywhere, 1, brdr(3, "double", "grey"))
#```
## RMarkdown End
I'm trying to knit a table in a large Rmarkdown document. The table represent disease levels on a farm and thus some are expressed as percentages percentages. When the disease levels are above target I would like to highlight by changing the color of the font to red. This works fine when text does not have a % label, but when I escape the % label the % label in the PDF document is always proceeded by an unwanted "". I'm a vet not a data scientist I have spent many hours on this but can't find an answer.
The original document is extremely complex pulling data from many sources to generate the current disease levels and targets using shiny input to determine various options so not possible to use code from the original document. But I have produced a very minimal reproducible example below
require(kableExtra)
require(scales)
library(knitr)
require(tidyverse)
knitr::opts_chunk$set(echo = TRUE)
MDF = data.frame(a = label_percent()(.07),b = label_percent()(.05))
MDF$a = as.character(MDF$a)
MDF$b = as.character(MDF$b)
MDF[1,] = apply(MDF[1,],2,function(f) gsub("%", "\\\\%", f))
MDF = MDF %>% mutate(a = cell_spec(a, color = ifelse(a > 6,"red","black")))
kable(MDF, "latex", escape = F, booktabs = T)
As far as I get it the issue is that the percent sign in the conditionally formatted cell gets escaped twice, once via the gsub and once via kable itself so that you end up with an additional \textbackslash() inserted in you latex code. Hence, one option to solve your issue would be to manually escape only the percent signs in the column to which you don't apply the conditional formatting:
---
title: "Untitled"
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r}
require(kableExtra)
require(scales)
library(knitr)
require(tidyverse)
MDF = data.frame(a = .07, b = .05) %>%
mutate(across(c(a, b), percent)) %>%
# Escape percent sign in column b only
mutate(across(c(b), ~ gsub("%", "\\\\%", .x))) %>%
mutate(a = cell_spec(a, color = ifelse(a > 6,"red","black")))
kable(MDF, "latex", escape = F, booktabs = T)
```
I'm doing a markdown report for my work. I need the outputs in word. Although with KABLE I can place titles on my tables, they are not numbered.
What should I add to kable () or in YAML to get automatic numbering of my tables?
crude example of what I do:
table(cars$speed) %>%
as.data.frame() %>%
kable(caption = "title",digits = 0, format.args = list( decimal.mark = ",",big.mark = "."),booktabs = T) %>%
kable_styling(latex_options = c("hold_position"))
To do this you will need to use the bookdown extensions to markdown. The following is an example rmarkdown (.Rmd) file which does want you want:
---
output:
bookdown::word_document2
---
See Table \#ref(tab:myfirsttable).
```{r myfirsttable, echo = FALSE}
knitr::kable(head(cars, 3), caption = "First three rows of cars dataset")
```
See Table \#ref(tab:mysecondtable).
```{r mysecondtable, echo = FALSE}
knitr::kable(head(iris, 3), caption = "First three rows of iris dataset")
```
Once generated the word document looks like:
For more information see:
https://bookdown.org/yihui/bookdown/a-single-document.html
https://bookdown.org/yihui/bookdown/tables.html
Compiling a report with bookdown I encounter difficulties in referencing tables generated with the huxtable package. For my work, LaTex/PDF, as well as an HTML version of the report, need to be created.
When rendering the document knitr::is_XXX_output() selects the optimal way to display the tables, see MWE:
```{r chunk-label, results='asis', fig.cap='chunk-caption'}
set.seed(1234)
dat <- data.frame(cond = factor(rep(c("A","B"), each=2)),
rating = c(rnorm(2),rnorm(2, mean=.8)))
hux <- as_hux(dat) %>%
set_caption('hux caption') %>%
set_label("tab:hux-label")
if (knitr::is_html_output()) {
print_html(hux) # output table html friendly (requires in chunk options "results='asis'")
}
if (knitr::is_latex_output()) {
hux
}
```
I am not sure whether it is recommended to use the caption and label commands provided by huxtable
set_caption('pipe caption') and set_label("tab:hux-label")
or knitr
chunk-label and fig.cap='chunk caption'
For figures, the latter works very well, but unfortunately not for tables.
The hook for "tab.cap" as discussed in following did not work well with bookdown and if PDF & HTML are needed.
Using table caption on R markdown file using knitr to use in pandoc to convert to pdf
Help and recommendations are very much appreciated!
If you upgrade to huxtable 4.3.0 (now on CRAN), it automatically takes care of bookdown table captions for you. Here's a short example:
---
title: "Bookdown test"
output:
bookdown::pdf_book: default
link-citations: yes
---
```{r setup, include=FALSE}
library(dplyr)
library(huxtable)
knitr::opts_chunk$set(echo = FALSE)
```
My table is \#ref(tab:foo1). The other table is \#ref(tab:foo2). The third is \#ref(tab:foo3).
```{r}
hux(a = 1:5, b = 1:5) %>%
set_caption("My labelled table") %>%
set_label("tab:foo1")
hux(a = 1:5, b = 1:5) %>%
set_caption("My unlabelled table")
hux(a = 1:5, b = 1:5) %>%
set_caption("My labelled table, prefix should be autoadded!") %>%
set_label("foo2")
hux(a = "A table with no caption, but a label") %>%
set_label("tab:foo3")
hux(a = "A table with no caption or label")
```
Not everything is perfect. If you set echo = TRUE you will need to manually insert \usepackage[table]{xcolor} before \usepackage{fancyvry} in the TeX header.
When I knit the following code chunk in Rmarkdown it will print out the results as well. I just want to run and show the code. In other code chunks in the same .Rmd file this knitr syntax works...
```{r import, results = "hide"}
gs_ls()
df <- gs_title("worlds-view-of-America")
confInPres <- df %>% gs_read(ws = "Sheet1", range = cell_rows(1:38))
colnames(confInPres) <- paste("year", colnames(confInPres), sep = "_")
colnames(confInPres)[1] <- "Country"
confInTrump <- select(confInPres, Country, year_2017)
favUS <- df %>% gs_read(ws = "Sheet2", range = cell_rows(1:38))
```
Take a look here.
If you want to show the code, use echo=TRUE.