Separate columns for text and code/output in Markdown - r

I am writing a small exercise book with Markdown. I would like to have the final output with the plots on a column and the document text on the other. Similar problems are addressed here and here. Unfortunately, they mainly desire one output per column. I would like to produce the output on a column and the text on the other. Really interesting is Docco, but it apprently shows the code output with the text.
A possible solution would be the RPres markdown horizontal rule: using ***, it creates two easy to use columns. But I do find documentation on its implementation in Markdown documents.
Here an image showing my results so far and an example of my code:
```{r setoption, cache=TRUE, warning=FALSE, message=FALSE, fig.width=12}
knitr::opts_chunk$set(cache=TRUE, warning=FALSE, message=FALSE, fig.width=4, echo = FALSE)
```
```{r, loadlibraries}
library(knitr)
library(lattice)
```
### Exercise 1 - 22/4/'16
Is the data set shown in the following figure symmetric or skewed? How many modes does this data set have?
```{r 1.1}
e1 <- rep(seq(1, 6, 1), c(6, 4, 2, 2, 4, 6))
barchart(table(e1), horizontal = FALSE, xlab = "", ylab = "Frequency")
```
**Solution:**
The data set is symmetric. Furthermore, it has two modes.
### Exercise 2 - 22/4/'16
Describe the shape of the dataset shown in the following figure.
```{r 2.1}
e2 <- rep(seq(1, 9, 1), c(6, 5, 4, 3, 2, 1, 1, 1, 1))
barchart(table(e2), ylab = "Frequency", horizontal = FALSE)
```
**Solution:**
The dataset is right skewed, also said right skewed, with one mode.

As you're asking for columns, my answer will be: table.
Using pipe_tables, figure and text can be alinged next to each other. However, this comes at a price:
The cells of pipe tables cannot contain block elements like paragraphs and lists, and cannot span multiple lines.
If this limitation is acceptable, pipe_tables provide a quite straightforward solution:
```{r img, fig.show = "hide", echo = FALSE}
library(knitr)
hist(rnorm(1000))
```
Figure|Explanation
-------------------------------|-------------------------
`r include_graphics(paste0(opts_chunk$get("fig.path"), "img-1.png"))`|Histogram of 1000 draws from a standard normal density.
Although the column headers cannot be omitted, you can leave them blank if desired.
Note that I initially suppress the plot (fig.show = "hide") and use include_graphics to include it afterwards. Otherwise, there would be a newline after the plot which disrupts the table.
(In knitr 1.12.3, include_graphics doesn't seem to work properly with inline code chunks. However, the current development version 1.12.25 works well.)
Extension
I hacked together an extension that allows to use a single chunk to generate and show the plots and some more features:
```{r setup, echo = FALSE}
library(knitr)
FigureNextToText <- function(number, # number of plot in chunk
text,
alt = "", # alternative text for image
label = opts_current$get("label"), # set explicitly when using inline!
ext = ".png",
headerL = " ", headerR = " ", # empty string confuses pandoc if only right header is set
widthL = 30, widthR = 30,
...) {
path <- fig_chunk(label = label, ext = ext, number = number, ...)
template <- "%s|%s
%s|%s
![%s](%s)|%s\r\n\r\n"
output <- sprintf(
template,
headerL, headerR,
paste0(rep("-", widthL), collapse = ""), paste0(rep("-", widthR), collapse = ""),
alt, path, text
)
return(asis_output(output))
}
```
```{r img, fig.show = "hide", echo = FALSE, results = "asis"}
library(knitr)
hist(rnorm(1000))
hist(runif(n = 1000, min = 0, max = 10))
FigureNextToText(1, text = "Histogram of draws from standard normal density.", widthL = 50, widthR = 10)
FigureNextToText(2, text = "Histogram of draws from uniform distribution.", headerR = "Explanation", alt = "Histogram 2.")
```
Some text.
`r FigureNextToText(2, text = "The same plot, this time inline.", label = "img", headerR = "Explanation", alt = "Histogram 2.")`
Some more text.
I know that the setup looks a little bit scary, but once FigureNextToText is defined, it can be called quite simply, e.g.:
FigureNextToText(2, text = "Histogram of draws from uniform distribution.", headerR = "Explanation", alt = "Histogram 2.")
Finding the correct values for widthL and widthR is somewhat cumbersome. This is because their effect depends on the number of characters in the cell, i.e. the filename of the image in the MD file and the alt text, too.

Related

R Markdown html: main and axis labels of plots as text suitable for search-function

I want to generate a R markdown html document with plots and it should be possible to jump to a certain plot by search-function (in my example there are 3 plots and I want to jump in the html-doc to the plot, where the main is "rivers").
I think, the problem is, that main and axis labels of a plot are grafical elements, like the plot itself, and not text. So the search-function doesn't work.
Of course it would be possible to add manually text before each plot, but as all my plots are generated with a for-loop, I don_t know how to do it.
is there a possibilty to include text-output in this kind of for-loop or are there other ideas, how the main or axis labels of a plot can be suitable for search-function?
thanks in advance!
---
title: "search function test"
author: "Michel Grün"
date: "last edited `r format(Sys.Date(),'%d.%m.%Y')`"
output:
html_document:
df_print: paged
---
knitr::opts_chunk$set(echo = TRUE,warning = FALSE)
df<-data.frame(x=seq(1,20),
trees=rnorm(20,4,3),
mountains=rnorm(20,6,3),
rivers=rnorm(20,4,4))
for(i in 2:length(colnames(df))){
plot(df$x,df[,i],
main=colnames(df)[i],
xlab=colnames(df)[1],
ylab=colnames(df)[i])
}
solved in another issue: https://stackoverflow.com/a/57034752/16578253
in this issue, the question is slightly different, but a solution shown there was also the solution for my problem. The idea is to create headings + outputs within a loop. As result, in the output dokument every header is followed by a plot and the header is of course suitable for search-function. It's important to use the argument results='asis' in the chunk konfiguration to allow that cat() is interpreted as Markdown syntax. Furthermore the
cat()ing tshould be surrounded by some newlines to make sure it's interpreted properly.
You can combine a svg device with a knitr hook:
---
title: "search function test"
author: "Michel Grün"
date: "last edited `r format(Sys.Date(),'%d.%m.%Y')`"
output:
html_document:
df_print: paged
---
```{r setup}
library(ggplot2)
library(knitr)
# see https://github.com/yihui/knitr/issues/754
local({
hook_plot <- knit_hooks$get("plot")
knit_hooks$set(plot = function(x, options) {
x <- paste(x, collapse = ".")
if (!grepl("\\.svg", x)) {
return(hook_plot(x, options))
}
# read the content of the svg image and write it out without <?xml ... ?>
paste(readLines(x)[-1], collapse = "\n")
})
})
opts_chunk$set(echo = TRUE, warning = FALSE, dev = "svglite")
df <- data.frame(
x = seq(1, 20),
trees = rnorm(20, 4, 3),
mountains = rnorm(20, 6, 3),
rivers = rnorm(20, 4, 4)
)
```
```{r}
for (i in 2:length(colnames(df))) {
plot(df$x, df[, i],
main =paste0(colnames(df)[i], " äöα😋"),
xlab = colnames(df)[1],
ylab = colnames(df)[i]
)
}
```

papaja and text references knitting to word

I am trying to create text references for tables and figures. However, I do get it to work following the examples in the documentation. There is neither a text reference nor a table caption using either approach. Here is some example script.
# Results
See Table \#ref(tab:ResultsANOVAI) or Table \#ref(tab:ResultsANOVAII) for ANOVA results. They show that ...
(ref:ResultsANOVAI) Results ANOVA I
```{r ANOVAI, warning=FALSE, tab.cap='(ref:ResultsANOVAI)'}
library(afex)
daten <- data.frame(vp = rep(1:30, each = 6),
cond1 = rep(1:3, each = 2),
cond2 = rep(1:2),
rt = rnorm(180, 600, 100))
aov.res <- aov_ez("vp", "rt", daten, within = c("cond1", "cond2"))
apa_anova <- apa_print.afex_aov(aov.res)
apa_table(apa_anova$table)
```
A little bit of text after the table.
(ref:ResultsANOVAI) Results ANOVA II
```{r ANOVAII, warning=FALSE}
apa_anova <- apa_print.afex_aov(aov.res)
apa_table(apa_anova$table,
caption = "(ref:ResultsANOVAII)")
```
Hints are heartly welcome.
Jens
the following code should work:
# Results
See Table \#ref(tab:ANOVAI) or Table \#ref(tab:ANOVAII) for ANOVA results. They show that ...
(ref:ResultsANOVAI) Results ANOVA I
```{r ANOVAI, warning=FALSE}
library(afex)
daten <- data.frame(vp = rep(1:30, each = 6),
cond1 = rep(1:3, each = 2),
cond2 = rep(1:2),
rt = rnorm(180, 600, 100))
aov.res <- aov_ez("vp", "rt", daten, within = c("cond1", "cond2"))
apa_anova <- apa_print.afex_aov(aov.res)
apa_table(apa_anova$table, caption = "(ref:ResultsANOVAI)")
```
A little bit of text after the table.
(ref:ResultsANOVAII) Results ANOVA II
```{r ANOVAII, warning=FALSE}
apa_anova <- apa_print.afex_aov(aov.res)
apa_table(apa_anova$table,
caption = "(ref:ResultsANOVAII)")
```
So why did your code not work?
When you want to add a caption to a table via text references, add something like caption = "(ref:caption-name)" to your call to apa_table() (the chunk option tab.cap does not work)
When you are using cross references (i.e., "see Table 1 and 2"), use \#ref(tab:chunk-name) -- your chunk names are ANOVAI and ANOVAII in your example, so it has to be \#ref(tab:ANOVAI) and \#ref(tab:ANOVAII)
Hope this helps!
For further reading, the relevant parts of the papaja manual are here:
Table captions
Cross references

table with long text, bullet points and specific table width

I want a table to have bullet points in one column and to have a specific table width (in order to be placed on one page when rendered to PDF).
How can I achieve this in rmarkdown using one of the many packages out there?
What I have tried and have so far:
---
output: pdf_document
---
```{r, include = FALSE}
df <- data.frame(col1 = "Some really long text here. I mean some reeeeeaaly loooong text. So long, it should be wrapped. Really.",
col2 = "* bullet point 1\n * bullet point 2", col3 = "Yes, there is still another column.")
```
# Attempt 1: kableExtra
```{r, echo = FALSE, warning = FALSE}
library(kableExtra)
df1 <- df
df1$col2 <- linebreak(df1$col2)
knitr::kable(df1, escape = FALSE) %>% column_spec(1, width = "15em")
```
# Attempt 2: pander
```{r, echo = FALSE}
pander::pander(df, keep.line.breaks = TRUE, style = 'grid', justify = 'left')
```
This renders to:
As you can see both options have caveats. The kableExtra version does have a specific table width that fits on one page but does not show bullet points nicely. Whereas the pander solution renders the bullet points nicely but spans multiple pages, because I don't know how to specifiy the table width in pander.
Is there a solution that can do both?
Related questions are for example here and there.
An alternative solution based on kableExtra (optional: with footnotes)
This approach allows to add a caption, to manually add footnotes within the table, and to fix column widths.
To create the bullet point list:
"thicker" \cdots from LaTex are employed as bullets (alternatives see here)
linebreaks are forced with \n (indentation is therefore not as nice as with the pander approach from #daroczig).
MWE
library(stringi); library(kableExtra); library(dplyr)
string_short <- "Descriptor"
string_long <- substr(stri_rand_lipsum(1), 1, 50)
# add footnotes manually within table
string_bulletlist <- "$\\boldsymbol{\\cdot}$ bullet point 1: foo$^{a}$ \n $\\boldsymbol{\\cdot}$ bullet point 2: bar$^{b}$"
df <- data.frame(col1 = c(string_short, string_short),
col2 = c(string_bulletlist, string_bulletlist),
col3 = c(string_long, string_long)
)
col_names <- c("Descriptor", "Description with list", "Some comment")
# header: bold column names
colnames(df) <- paste0("\\textbf{", col_names,"}")
# add footnote with kableExtra commands
names(df)[1] <- paste0(names(df)[1], footnote_marker_symbol(1))
df %>%
mutate_all(linebreak) %>% # required for linebreaks to work
kable(
"latex",
escape = F,
booktabs=TRUE,
align = "l",
caption = 'kableTable with bullet list and footnote') %>%
# kable_styling(full_width = F) %>% # makes no difference here
footnote(general = "General comment of the table.",
alphabet = c("Footnote A;", "Footnote B;"),
symbol = c("Footnote Symbol 1")) %>%
column_spec(1, width = "5em") %>% # fix width column 1
column_spec(2, width = "10em") %>% # fix width column 2
column_spec(3, width = "15em") # fix width column 3
To [improve line spacing[(https://stackoverflow.com/questions/53794142/increase-line-row-spacing-with-kableextra), one can add the following before & after code chunk in the Rmd:
\renewcommand{\arraystretch}{1.5} <!-- increase line spacing for the table -->
RMD CHUNK HERE
\renewcommand{\arraystretch}{1} <!-- reset row hight/line spacing -->
Comment:
I also tried the pander approach from #daroczig and made the following experiences:
Pro: nice line spacing plus a "real bullet list" (compared to the $\boldsymbol{\cdot}$-workaround in the kableExtra approach).
Con: a large blank space is included after the bullet list
In addition, when using the pander approach in an Rmd file using the huskydown thesis template the footnotes greatly messed up the table alignment.
Use the split.table parameter of pandoc.table (that is being called by pander in the background) or disable the table splitting in general via panderOptions's table.split.table, eg
pander::pander(df, keep.line.breaks = TRUE, style = 'grid', justify = 'left', split.table = Inf)
or
library(pander)
panderOptions('table.style', 'grid')
panderOptions('table.alignment.default', 'left')
panderOptions('table.split.table', Inf)
panderOptions('keep.line.breaks', TRUE)
pander(df)

Space after every five rows in kable output (with booktabs option) in R Markdown document

I am using knitr::kable() to render tables as part of an R Markdown document (that itself is part of a bookdown project). In particular, the booktabs option (through setting the booktabs argument to equal TRUE) renders the table in a nice-looking way. However, I'd like for there not to be a space after every five rows.
Here, for example, is the code and how the table in the bookdown demo appears when rendered as a PDF:
knitr::kable(
head(iris, 20), caption = 'Here is a nice table!',
booktabs = TRUE
)
I'd like for the space that aappears after every five rows to not be included, but I cannot seem to find a setting in knitr::kable() that does this.
The reason why the row height is not always equal is that by default, kable inserts a \addlinespace every 5 rows when booktabs is specified as TRUE, as is shown here:
linesep = if (booktabs) c('', '', '', '', '\\addlinespace') else '\\hline'
To alter this, add linesep = "" as an argument to kable().
knitr::kable(
head(iris, 20), caption = 'Here is a nice table!',
booktabs = TRUE,
linesep = ""
)
See Get rid of \addlinespace in kable for more details.
It is also worth saying that you can play around with this option if you want to change the style. For example linesep = c("", "", "", "\\hline") would add a horizontal line every four spaces.
Based on the example above I was interested in controlling the separation. That works nicely with the following helper function. This makes it possible to control the locations of the line separation.
linesep<-function(x,y=character()){
if(!length(x))
return(y)
linesep(x[-length(x)], c(rep('',x[length(x)]-1),'\\addlinespace',y))
}
knitr::kable(
head(iris, 20), caption = 'Here is a nice table!',
booktabs = TRUE,
linesep = linesep(c(3,2,1,1,3,5,4,1))
)
Bart's answer failed to work for me on my remote server when using prettyNum() on the table and passing the output to kableExtra::kable_styling(), where it just added an column full of NAs and no linespaces. It seems to work fine on my local machine, so I can't reproduce the error.
Anyway, this alternative solution works for me (but only when passing the table to kableExtra for some reason):
linesep <- function(table, groups) {
sep_indx <- rep("", nrow(table))
sep_indx[cumsum(groups)] <- '\\addlinespace'
return(sep_indx)
}
knitr::kable(
head(iris, 20),
caption = 'Here is a nice table!',
booktabs = TRUE,
linesep = linesep(head(iris, 20), c(3, 2, 1, 1, 3, 5, 4, 1))
) %>% kableExtra::kable_styling(latex_options = c("scale_down", "HOLD_position"))
example

R Markdown Footnote in xtable

I'm having issues with a footnote not appearing under a table in my R Markdown report. Below is the code I'm using to process which does successfully but with no footnote appearing under the table.
```{r ccxtable7, results="asis", echo=FALSE}
comment <- list(pos = list(0), command = NULL)
comment$pos[[1]] <- c(nrow(indPctChgCC))
comment$command <- c(paste("\\hline\n",
"{\\footnotesize Note: * signifies number of
properties used was 35 or less.}\n", sep = ""))
print(xtable(valPctCon(indPctChgCC, indfreqCC, 35), align = "crrrrr",
label = "tab:indCC", add.to.row = comment, hline.after = c(-1,0),
caption = "Industrial Certified-Certified Percentage Change per Value Segment"))
```
indPctChCC is a 3x5 matrix of strings. Could someone help me understand why the footnote is not appearing under the table with this current code?
add.to.row (and also hline.after) are arguments of the print function, not xtable().
This should get you where you want:
print(xtable(tab, align = "crrr",
label = "tab:indCC",
caption = "Industrial Certified-Certified Percentage Change per Value Segment"),
add.to.row = comment,
hline.after = c(-1,0))

Resources