I'm trying to print two table side-by-side through Rmarkdown, output as PDF.
I can print the tables out fine, but they end up stuck really close together and I cannot find a way to create more space between them. The solutions I find in other posts returns strange output or errors, e.g. the second one from here just gives an 'error 43': Align multiple tables side by side
My code is this:
```{r, echo=FALSE}
library(knitr)
kable(list(head(bymonth),head(bydecade)),align='c')
```
Anyone know how to add some spacing between those two tables?
Incorporating the answer given here you could do it manually like this:
```{r, echo = FALSE, results = 'asis', warning = F}
library(knitr, quietly = T)
t1 <- kable(head(mtcars[,1:2]), format = 'latex')
t2 <- kable(head(mtcars[,3:4]), format = 'latex')
cat(c("\\begin{table}[h] \\centering ",
t1,
"\\hspace{1cm} \\centering ",
t2,
"\\caption{My tables} \\end{table}"))
```
The basic idea is to create the tables individually and align them with plain latex. The spacing is added by \\hspace{1cm}.
Related
I am trying to produce a "longitudinal" layout for long tables in RMarkdown with kable. For example, I would like a table to be split over two columns, like in the example below:
dd <- data.frame(state=state.abb, freq=1:50)
kable(list(state=dd[1:25,], state=dd[26:50,]))
However, this hack produces an output that looks a way worse than the normal kable output (for example the header is not in bold). Is there a "proper" way to do this using kable?
kable is a great tool, but has limits. For the type of table you're describing I would use one of two different tools depending on output wanted.
Hmisc::latex for .Rnw -> .tex -> .pdf
htmlTable::htmlTable for .Rmd -> .md -> .html
Here is an example of the latter:
dd <- data.frame(state=state.name, freq=1:50)
dd2 <- cbind(dd[1:25, ], dd[26:50, ])
library(htmlTable)
htmlTable(dd2,
cgroup = c("Set 1:25", "Set 26:50"),
n.cgroup = c(2, 2),
rnames = FALSE)
You can still use Kable with a slight modification to your code.
dd <- data.frame(state=state.abb, freq=1:50)
knitr::kable(
list(dd[1:25,], dd[26:50,]),
caption = 'Two tables placed side by side.',
booktabs = TRUE
)
This code is a modification of this. You can also find more information about tables on that page
I'm using R Markdown and am trying to generate a table and centre it in a word document. Below is the code i have taken from github as a test
Table \#ref(tab:table-single) is a simple example.
```{r table-single, tidy=FALSE}
knitr::kable(
head(mtcars, 10), booktabs = TRUE,
caption = 'A table of the first 10 rows of the mtcars data.'
)
```
When i run this piece of code the table name never resolves so i get \#ref(tab:table-single) instead of Table 2.1 as can be seen from the final document
Can someone see where in my code i have made a mistake in relation to referencing my table
I am knitting to MS Word
Thanks
If you use the bookdown package to render your markdown, you will get proper cross-referencing:
---
output: bookdown::word_document2
---
Table \#ref(tab:table-single) is a simple example.
```{r table-single, tidy=FALSE}
knitr::kable(
head(mtcars, 10), booktabs = TRUE,
caption = 'A table of the first 10 rows of the mtcars data.'
)
```
I'm trying to generate a flexdashboard, creating each page from within a loop and with each of the generated pages containing a dygraph (although any HTML widget ought to behave the same).
I have looked extensively and it seems that rmarkdown comments can be generated using cat("title") (as per the solution here: generate markdown comments within for loop).
The HTML widgets on the other hand only behave nicely if you use htmltools::tagList() (as per the solution here:For loop over dygraph does not work in R).
I dont have working code to share, but this broadly gives the picture of what I am hoping to achieve:
for (i in 1:ncol(downloadedData)){
fund_NAVS <- downloadedData[,i] #this is an xts object
fund_NAVS <- fund_NAVS[!is.na(fund_NAVS)]
cat("pageTitle")
cat("===================================== \n")
cat("Row\n")
cat("------------------------------------- \n")
cat("### Page title")
dygraph(fund_NAVS)
}
I've been able to get this to partially work using pander::pandoc.header. However, getting content (plots and HTML objects) to actually show up in the final HTML file is a different story.
---
output:
flexdashboard::flex_dashboard:
orientation: columns
source: embed
vertical_layout: fill
---
```{r results='asis'}
library(pander)
pages <- 5
cols <- 2
sections <- 3
for (p in 1:pages) {
pandoc.header(paste("Page", p), level = 1)
for (c in 1:cols) {
pandoc.header(paste("Column", c), level = 2)
for (s in 1:sections) {
pandoc.header(paste("Section", s), level = 3)
cat("hi")
pandoc.p("")
}
}
}
```
I was able to autogenerate content by building r chunks explicitly then kniting them inline with r paste(knitr::knit(text = out)). This amazing line of code was found in an SO post.
In my case, I wanted to produce a series of graphs, each with a separate tab, with different content. Each graph was similar but there were numerous (about 15) and I didn't want to copy/paste all of the separate chunks.
Here is a gist you can download of a more simple example. (The code is also below but note that I add \ before each chunk so that it rendered as a single block of code so remove the \ before running.) I built a much more complicated function to build graphs, but the idea of the R chunks can be carried forward to any list object containing htmlwidgets as elements.
---
title: "Loop to Auto Build Tabs Containing htmlwidgets"
output: flexdashboard::flex_dashboard
---
\```{r setup, echo =FALSE, eval = TRUE}
library(tidyverse)
library(flexdashboard)
library(highcharter)
labels <- mtcars %>% names # these will serve as labels for each tab
# create a bunch of random, nonsensical line graphs
hcs <- purrr::map(.x = mtcars, ~highcharter::hchart(mtcars, y = .x, type = 'line')) %>%
setNames(labels) # assign names to each element to use later as tab titles
\```
Page
====================
Column {.tabset .tabset-fade}
-----------------------------
<!-- loop to build each tabs (in flexdashboard syntax) -->
<!-- each element of the list object `out` is a single tab written in rmarkdown -->
<!-- you can see this running the next chunk and typing `cat(out[[1]])` -->
\```{r, echo = FALSE, eval = TRUE}
out <- lapply(seq_along(hcs), function(i) {
a1 <- knitr::knit_expand(text = sprintf("### %s\n", names(hcs)[i])) # tab header, auto extracts names of `hcs`
a2 <- knitr::knit_expand(text = "\n```{r}") # start r chunk
a3 <- knitr::knit_expand(text = sprintf("\nhcs[[%d]]", i)) # extract graphs by "writing" out `hcs[[1]]`, `hcs[[2]]` etc. to be rendered later
a4 <- knitr::knit_expand(text = "\n```\n") # end r chunk
paste(a1, a2, a3, a4, collapse = '\n') # collapse together all lines with newline separator
})
\```
<!-- As I mentioned in the SO post, I don't quite understand why it has to be -->
<!-- 'r paste(knitr::knit(...)' vs just 'r knitr::knit(...)' but hey, it works -->
`r paste(knitr::knit(text = paste(out, collapse = '\n')))`
I am trying to combine two tables in R Markdown into a single table, one below the other & retaining the header. The figure below shows the desired output. After putting my markdown code I will show the actual output. I realize that the way I have structured the pander statements will not allow me to get the output I want but searching SO I was unsuccessful in finding the right way to do so.
I can do some post processing in Word to get the output exactly as I want but I am trying to avoid that overhead.
The testdat.RData file is here: https://drive.google.com/file/d/0B0hTmthiX5dpWDd5UTdlbWhocVE/view?usp=sharing
The R Markdown RMD file is here: https://drive.google.com/file/d/0B0hTmthiX5dpSEFIcGRNQ1MzM1E/view?usp=sharing
Desired Output
```{r,echo=FALSE,message = FALSE, tidy=TRUE}
library(pander)
load("testdat.RData")
pander::pander(t1,big.mark=',', justify=c('left','right','right','right'))
pander::pander(t2,big.mark=',', justify=c('left','right','right','right'))
```
Actual Output
Thanks,
Krishnan
Here's my attempt using the xtable package:
```{r,echo=FALSE, message = FALSE, results="asis"}
library(xtable)
# Add thousands separator
t1[-1] = sapply(t1[-1], formatC, big.mark=",")
t2[-1] = sapply(t2[-1], formatC, big.mark=",")
t1$Mode = as.character(t1$Mode)
# Bind together t1, extra row of column names, and t2
t1t2 = rbind(t1, names(t1), t2)
# Render the table using xtable
print(xtable(t1t2, align="rrrrr"), # Right-align all columns (includes extra value for row names)
include.rownames=FALSE, # Don't print rownames
hline.after=NULL,
# Add midrules before/after each set column names
add.to.row = list(pos = list(-1,0,4,5),
command = rep("\\midrule \n",4)))
```
And here's the output:
Allow me to make a formal answer since my comment seemed to work for you.
pander(rbind(t1,names(t2),t2))
I'm new to knitr (and also quite new to R), so this might be a dumb question...
I have two data.frames, which both have two columns, but different numbers of rows. I want to show them in my knitr report, but having one narrow table below another narrow table when they could so easily sit next to each other doesn't look good.
Is there any way they could be displayed next to each other?
Update
Ok, based on the suggestion below, here's what I did (I'm putting three tables together now):
```{r fig.height=13.5, fig.width=10, echo=FALSE, comment=""}
grid.arrange(textGrob("Visual Clusters", gp=gpar(fontsize=14, fontface="bold")),
textGrob("We have biofilm data for...", gp=gpar(fontsize=14, fontface="bold")),
textGrob("Left Over Isolates", gp=gpar(fontsize=14, fontface="bold")),
tableGrob(clusters, show.rownames=FALSE, gp=gpar(fontsize=10)),
tableGrob(clust_ab, show.rownames=FALSE, gp=gpar(fontsize=10)),
tableGrob(n_clust, show.rownames=FALSE, gp=gpar(fontsize=10)),
ncol=3, nrow=2, heights=c(1,30))
```
This looks already really good, with titles for the three tables and without the numbered rows.
The only issue I couldn't resolve so far is that the tables are all centred horizontally, so the shorter ones start below the longest one, if you know what I mean.
The development version of knitr (on Github; follow installation instructions there) has a kable() function, which can return the tables as character vectors. You can collect two tables and arrange them in the two cells of a parent table. Here is a simple example:
```{r two-tables, results='asis'}
library(knitr)
t1 = kable(mtcars, format='html', output = FALSE)
t2 = kable(iris, format='html', output = FALSE)
cat(c('<table><tr valign="top"><td>', t1, '</td><td>', t2, '</td><tr></table>'),
sep = '')
```
You can also use CSS tricks like style="float: [left|right]" to float the tables to the left/right.
If you want to set cell padding and spacing, you can use the table attributes cellpadding / cellspacing as usual, e.g.
```{r two-tables, results='asis'}
library(knitr)
t1 = kable(mtcars, format='html', table.attr='cellpadding="3"', output = FALSE)
t2 = kable(iris, format='html', table.attr='cellpadding="3"', output = FALSE)
cat(c('<table><tr valign="top"><td>', t1, '</td>', '<td>', t2, '</td></tr></table>'),
sep = '')
```
See the RPubs post for the above code in action.
Would you settle for "an image" of data.frames? Clearly my solution is crude, feel free to fiddle with the details (spacing between data.frames, for example).
Two data.frames, side by side
========================================================
```{r}
library(gridExtra)
x <- data.frame(a = runif(5), b = runif(5))
y <- data.frame(a = runif(7), b = runif(7))
grid.arrange(tableGrob(x), tableGrob(y), ncol = 2)
```