Create pdf-format table that can wrap the text well in rmarkdown - pdf

I used the rmarkdown to create a pdf file, where some tables are included in the output. The tables are created by using pander function.
As you see, the output does not wrap the text well, so the output is quite dirty.
Suppose the code is as follows:
title: "Untitled"
output: pdf_document
---
```{r kable}
library(xtable)
a <- rep(1,5)
b <- rep("33333333333333333333333333333333333333333333333333333333333333333", 5)
c <- rep("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", 5)
data <- as.data.frame( cbind(a, b, c) )
```
```{r b}
library(pander)
pander(data, split.cells = 5, split.table = Inf)
```
```{r c}
pander(data, split.cells = 5)
```
I do not know if there is any method to create pdf-format table that can wrap the text well.
I have tried the method in this link. wrap long text in kable table column
But it fails.

Related

Iterating to create tabs with gt in quarto

Something that is very handy is to iterate through a variable and then dynamically create tabs based on values of that variable (here homeworld). This works well with the results: asis chunk option. I can make that work but there is some strange interaction with the {gt} package whereby I can only make gt work with purrr::walk if I use gt::as_raw_html. However if I just produce a single table outside of purrr::walk I don't need gt::as_raw_html. Here is the error message I get {gt} does not work:
Error running filter
/Applications/quarto/share/filters/quarto-pre/quarto-pre.lua:
...lications/quarto/share/filters/quarto-pre/quarto-pre.lua:2410:
attempt to concatenate a nil value (local 'v') stack traceback:
...lications/quarto/share/filters/quarto-pre/quarto-pre.lua:2417: in
function
<...lications/quarto/share/filters/quarto-pre/quarto-pre.lua:2415>
Here is the quarto (quarto version 1.1.175) code to reproduce:
---
title: "Untitled"
format: html
execute:
warning: false
---
```{r r-pkgs}
library(dplyr)
library(glue)
library(gt)
library(purrr)
## just to simplify
starwars <- starwars %>%
filter(!is.na(sex))
```
# Does work
::: {.panel-tabset}
```{r}
#| results: asis
walk(
unique(starwars$sex), \(hw) {
cat(glue("## {hw} \n\n"))
starwars %>%
filter(sex == hw) %>%
count(homeworld) %>%
head() %>%
gt() %>%
as_raw_html() %>%
print()
cat("\n\n")
}
)
```
:::
# Does not work
::: {.panel-tabset}
```{r}
#| results: asis
#| eval: false
walk(
unique(starwars$sex), \(hw) {
cat(glue("## {hw} \n\n"))
starwars %>%
filter(sex == hw) %>%
count(homeworld) %>%
head() %>%
gt() %>%
print()
cat("\n\n")
}
)
```
:::
## single does work
```{r}
#| results: asis
starwars %>%
count(homeworld) %>%
head() %>%
gt()
```
Posting back answer from the duplicate issue in quarto-dev/quarto-cli#2370
About the issue
The behavior you see has to do with the print method used, and the iteration with walk()
When you use print() after gt() or after gt() %>% as_raw_html() it will not have the same effect, as the print method used will not be the same. In the context of knitr, this matters.
Using as_raw_html() makes sense to include table as raw HTML in such document, and it probably will have the same result as when gt object are printing in knitting to HTML table (though the use of htmltools). When you use gt() %>% print(), it will not use the correct printing method that is used when just gt() is in a chunk (the knit_print() method more on that here for advanced understanding.
More on how to create content dynamically with knitr
Let me add some context about knitr and dynamically created content.
Iterating to dynamically create content in knitr require to use the correct print method (usually knit_print()), and it is better to iterate on child content with knitr::knit_child() function that will correctly handle the printed output specific to sewing result in the document. We have some resource about that in R Markdown Cookbook that would apply to Quarto as well.
About knit_child() : https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html
About knit_expand() also : https://bookdown.org/yihui/rmarkdown-cookbook/knit-expand.html
As an example, this is how we recommend to dynamically create content when using knitr content so that R code result is correctly mixed with other content, specifically when the content to dynamically create is a mix of raw markdown, and R code results.
---
title: "Untitled"
format: html
execute:
warning: false
keep-md: true
---
```{r r-pkgs}
library(dplyr)
library(glue)
library(gt)
library(purrr)
## just to simplify
starwars <- starwars %>%
filter(!is.na(sex))
```
# Tables
::: {.panel-tabset}
```{r}
#| output: asis
res <- purrr::map_chr(unique(starwars$sex), \(hw) {
knitr::knit_child(text = c(
"## `r hw`",
"",
"```{r}",
"#| echo: false",
"starwars %>%",
" filter(sex == hw) %>%",
" count(homeworld) %>%",
" head() %>%",
" gt()",
"```",
"",
""
), envir = environment(), quiet = TRUE)
})
cat(res, sep = '\n')
```
:::
You could also put the child content in a separate file for easier writing as in the Cookbook, by writing what you would need as document for one value you are iterating
## `r hw`
```{r}
#| echo: false
starwars %>%
filter(sex == hw) %>%
count(homeworld) %>%
head() %>%
gt()
```
This is the safest way to mix markdown content (like ##) with R code output ( like Tables or Htmlwidgets) which are content you can't easily just cat() into the file.
See more in the issue

! Package pdftex.def Error - when knitting to PDF

I am able to knit to PDF for the example below:
---
title: "R Notebook"
output:
pdf_document: default
html_notebook: default
html_document:
df_print: paged
---
Table 1 example:
```{r, warning=FALSE, message=FALSE, echo=FALSE, include=FALSE, fig.pos="H"}
library(magrittr)
library(tidyverse)
library(kableExtra)
library(readxl)
library(modelsummary)
library(scales)
tmp <- mtcars
# create a list with individual variables
# remove missing and rescale
tmp_list <- lapply(tmp, na.omit)
tmp_list <- lapply(tmp_list, scale)
# create a table with `datasummary`
# add a histogram with column_spec and spec_hist
# add a boxplot with colun_spec and spec_box
emptycol = function(x) " "
final_4_table <- datasummary(mpg + cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb ~ N + Mean + SD + Heading("Boxplot") * emptycol + Heading("Histogram") * emptycol, data = tmp) %>%
column_spec(column = 5, image = spec_boxplot(tmp_list)) %>%
column_spec(column = 6, image = spec_hist(tmp_list))
```
```{r finaltable, echo=FALSE}
final_4_table
```
However, I cannot knit to PDF my own code which involves more variables. My R Markdown starts by reading my excel file and then it is pretty much the same as example above:
---
title: "table1"
output:
pdf_document: default
html_document:
df_print: paged
---
Table 1
```{r prep-tableone, message=FALSE, warning=FALSE, echo=FALSE, include=FALSE, fig.pos="H"}
library(magrittr)
library(tidyverse)
library(kableExtra)
library(readxl)
library(modelsummary)
library(scales)
### set directory
setwd("/etcetc1")
## read dataset
my_dataset <- read_excel("my_dataset.xlsx")
my_dataset <- as.data.frame(my_dataset)
...
I can run this code in R script; it works just fine. I can also knit this code to HTML just fine. When trying to knit to PDF I get the following error:
output file: table1test.knit.md
! Package pdftex.def Error: File `table1test_files/figure-latex//boxplot_65c214bae9bb.pdf' not found: using draft setting.
Error: LaTeX failed to compile table1test.tex. See https://yihui.org/tinytex/r/#debugging for debugging tips. See table1test.log for more info.
In addition: Warning messages:
1: package 'ggplot2' was built under R version 4.1.1
2: package 'tibble' was built under R version 4.1.1
3: package 'tidyr' was built under R version 4.1.1
4: In in_dir(input_dir(), evaluate(code, envir = env, new_device = FALSE, :
You changed the working directory to /etcetc1 (probably via setwd()). It will be restored to /etcetc2. See the Note section in ?knitr::knit
Execution halted
Am I missing any packages? Do you know what might be happening?
I use TeXShop for LaTeX.

kable unable to output unicode character in pdf_book (bookdown)

I am trying to use the checkmark unicode character (\u2713) in a table rendered by kable in a bookdown project. A MWE consists in the following 2 files (index.Rmd, preamble.tex) part of the generated minimal bookdown project.
index.Rmd
---
title: "A Minimal Book Example"
subtitle: "subtitle"
lang: fr
author: "Yihui Xie"
date: "`r Sys.Date()`"
site: bookdown::bookdown_site
documentclass: book
mainfont: Arial
mathfont: Arial
bibliography: [book.bib, packages.bib]
biblio-style: apalike
link-citations: yes
subparagraph: yes
description: "This is a minimal example of using the bookdown package to write a book. The output format for this example is bookdown::gitbook."
---
```{r setup, include=FALSE}
# Set locale to french for month and day names (calendar plots)
Sys.setlocale(locale = 'French')
# Load all needed libraries
if(!require('pacman'))install.packages('pacman')
pacman::p_load(kableExtra)
```
(ref:O3) O~3~
# Prerequisites
✓
```{r stations-polluants, echo=FALSE}
stations_polluants_table <- data.frame(
stations = c("41B001", "41B004", "41B011", "41MEU1", "41N043", "41R001", "41R002", "41R012", "41WOL1", "Total / polluant"),
O3 = c("", rep("✓", 5), "", rep("\u2713", 2), "7")
)
kable(stations_polluants_table, col.names = c("Station", "(ref:O3)"), booktabs = T, align = "c", caption = "Caption text") %>%
row_spec(0, bold = T) %>%
row_spec(10, bold = T) %>%
collapse_rows(columns = 1, latex_hline = "major", valign = "top")
```
```{r include=FALSE}
# automatically create a bib database for R packages
knitr::write_bib(c(
.packages(), 'bookdown', 'knitr', 'rmarkdown'
), 'packages.bib')
```
preamble.tex
\usepackage{booktabs}
\newfontfamily{\unicodefont}{Arial Unicode MS}
\usepackage{newunicodechar}
\newunicodechar{✓}{{\unicodefont{✓}}}
By compiling in PDF with rmarkdown::render_site(output_format = 'bookdown::pdf_book', encoding = 'UTF-8') one can notice that ✓ is correctly rendered in the text, while it is replaced by <U+2713> in the generated table. I also tried to use \u2713 in the table without more success.
What am I doing wrong ? Please note that, even if the prefered output is PDF, I would also like to compile as gitbook (so Rmd files need to stay independent from the output format).
Many thanks.
After having a moment of clarity, the solution simply lies in using text references in bookdown, i.e. (ref:check) ✓ and use the reference within the table.
index.Rmd
```{r setup, include=FALSE}
# Set locale to french for month and day names (calendar plots)
Sys.setlocale(locale = 'French')
# Load all needed libraries
if(!require('pacman'))install.packages('pacman')
pacman::p_load(kableExtra)
```
(ref:O3) O~3~
# Prerequisites
✓
(ref:check) ✓
```{r stations-polluants, echo=FALSE}
stations_polluants_table <- data.frame(
stations = c("41B001", "41B004", "41B011", "41MEU1", "41N043", "41R001", "41R002", "41R012", "41WOL1", "Total / polluant"),
O3 = c("", rep("(ref:check)", 5), "", rep("(ref:check)", 2), "7")
)
kable(stations_polluants_table, col.names = c("Station", "(ref:O3)"), booktabs = T, align = "c", caption = "Caption text") %>%
row_spec(0, bold = T) %>%
row_spec(10, bold = T) %>%
collapse_rows(columns = 1, latex_hline = "major", valign = "top")
```
```{r include=FALSE}
# automatically create a bib database for R packages
knitr::write_bib(c(
.packages(), 'bookdown', 'knitr', 'rmarkdown'
), 'packages.bib')
```

Flexdashboard not able to render ggplotly and ggplot object on same markdown

I have a basic reproducible example here that I think might just be a package limitation. I was wondering if I am just doing something wrong? They both plot fine separately but when combined in the same markdown make the dashboard unable to correctly render.
---
title: "Untitled"
output:
flexdashboard::flex_dashboard:
orientation: rows
source_code: embed
runtime: shiny
---
```{r setup, include=FALSE}
library(tidyverse)
library(plotly)
library(albersusa)
state_sf <- usa_sf("aeqd")
state_dat <- data.frame(state = c("Washington", "Wyoming","Texas","California"), pct = c(0.3,0.5,0.8,0.1))
state_map <- state_sf %>%
left_join(state_dat, by = c("name" = "state"))
```
Test
=====================================
Sidebar {.sidebar data-width=200}
-------------------------------------
Testing
Row
-----------------------------------------------------------------------
###Plotly
```{r graph 1, fig.height=4, fig.width=6}
#Symptoms by state last week===================================================
ggplotly(
ggplot(data = state_map) +
geom_sf(aes(fill=pct))
)
```
###Bar
```{r graph 2, fig.height=4, fig.width=3}
ggplot(data=state_dat) +
geom_col(aes(state,pct,fill=pct))
```
If you are using runtime: shiny you need to use the proper type of Shiny's renderX() functions for each type of plot object to display properly. I don't know why only one plot chunk (w/o renderX()) works, but two breaks it.
### Plotly
```{r graph_1, fig.height=4, fig.width=3}
#Symptoms by state last week
renderPlotly({
ggplotly(
ggplot(data = state_map) +
geom_sf(aes(fill=pct))
)
})
```
### Bar
```{r graph_2, fig.height=4, fig.width=3}
renderPlot({
ggplot(data=state_dat) +
geom_col(aes(state,pct,fill=pct))
})
```

Display kable table in line with text -- Sweave Rnw file

I have an Rnw file with a table using the kable command. I want the table to be displayed in line with the text that it follows. How can I stop the table from being displayed at the top of the page? This is the Rnw code:
\documentclass{article}
\begin{document}
Here is my data, which is supposed to be below this sentence.
\\
\begin{abstract}
<<>>=
a <- 1; b <-2; c <-3; d <- 4
df.mse <- data.frame(row.names = c("Normal model", "Laplace model"))
df.mse["Normal model", "Normal MLE"] <- a
df.mse["Normal model", "Laplace MLE"] <- b
df.mse["Laplace model", "Normal MLE"] <- c
df.mse["Laplace model", "Laplace MLE"] <-d
library(knitr)
kable(df.mse, caption="approximate MSE for each model/estimator combination")
#
\end{abstract}
\end{document}
I'd prefer for the solution to not involve changing the actual Tex file, as I'd like to carry on working on the Sweave file without worrying about overriding the solution. I know you can use the float package in LaTeX but I'm not sure how to do that in the context of a Sweave file.
Don't include a caption in the call to kable. Then it will just output a tabular environment without wrapping it in a table float. If the caption is not required, that simply means leaving out the caption argument in your call to kable.
If you do want a caption, but want the table placed inline, you need to start your table with \begin{table}[h]. You can put that in the Rnw file like this:
<<>>=
a <- 1; b <-2; c <-3; d <- 4
df.mse <- data.frame(row.names = c("Normal model", "Laplace model"))
df.mse["Normal model", "Normal MLE"] <- a
df.mse["Normal model", "Laplace MLE"] <- b
df.mse["Laplace model", "Normal MLE"] <- c
df.mse["Laplace model", "Laplace MLE"] <-d
library(knitr)
#
\begin{table}[h]
\caption{This is the caption.}
<<echo=FALSE>>=
kable(df.mse)
#
\end{table}