I'm trying to make a table where the entire header column is at an angle -- not just the text, but the cell itself. I've found the code for angling the text, but nothing that would angle the cell itself. Below is the code I'm starting with:
---
output: pdf_document
---
library(knitr)
library(kableExtra)
library(dplyr)
df <- data.frame(
Long_Column_Name = 1:5,
Different_Column_Name= 5:9,
Third_Column_Name = 10:14
)
df %>%
kable(align='c',linesep='') %>%
row_spec(0,angle=45) %>%
column_spec(1,background='#CCCCFF',include_thead=TRUE)
Attached images shows what's produced from this code compared with an approximation of the output I want; the text in the headers is angled, but the cells are still rectangular and matching the rows below. Ideally the cells in the row would themselves be angled at 45 degrees to match the text. Is there a way to accomplish this?
Related
Here is my current table code:
reftable <- matrix(c("181198", "234321", "306789", "16000234"), ncol = 1, byrow = TRUE)
colnames(reftable) <- c("Score")
rownames(reftable) <- c("How I Met Your Mother", "There Are No Ifs, Ands, Or Buts in the Land of Fantasies and Dreams", "Leo and Carrie Simply Cannot Get Along", "Parry Needs A Dentist")
reftable <- as.table(reftable)
reftable
However, when I knit this code to a pdf, all the numbers turn into hashtags and it's hard to read because there are no border lines. How do I convert this into a ggplot table so that there are border lines on the tables and the inputted numbers are preserved?
library gridExtra may help you
library(gridExtra)
pdf("reftable.pdf", height = 11, width = 8.5)
grid.table(reftable)
dev.off()
There was a simple way using ggtexttable
ggtexttable(reftable)
I usually use flextable to output tables/dataframes to pdf output from rmarkdown:
library(flextable)
library(dplyr)
reftable <- data.frame(
Show = c("How I Met Your Mother", "There Are No Ifs, Ands, Or Buts in the Land of Fantasies and Dreams", "Leo and Carrie Simply Cannot Get Along", "Parry Needs A Dentist"),
Score = c("181198", "234321", "306789", "16000234")
)
reftable %>%
flextable() %>%
border_inner()
border_inner() gives all inside border lines. You can control borders with different options: https://davidgohel.github.io/flextable/reference/border_inner_h.html and control size
I have a really wide table (300+ columns) and would like to display it by wrapping the columns. In the example I will just use 100 columns.
What I have in mind is repetitively using kable to display the subset of the table:
library(kableExtra)
set.seed(1)
data = data.frame(matrix(rnorm(300, 10, 1), ncol = 100))
kable(data[, 1:5], 'latex', booktabs = T)
kable(data[, 6:10], 'latex', booktabs = T)
kable(data[, 11:15], 'latex', booktabs = T)
But this is apparently tedious... I know there are scaling down options but since I have so many columns, it won't be possible.
Is there any parameter I can twist in kable to make it happen?
Updated:
#jay.sf 's answer seems working well, but it didn't yield the same result here. Instead I got some plain code - could you please have a second look and let me know where can I improve? Thanks!
my sessionInfo() is: R version 3.5.1 (2018-07-02) with rmarkdown::pandoc_version() of 1.19.2.1.
This question is actually trickier than I thought at first glance. I used some tidyverse functions, specifically dplyr::select to get columns and purrr::map to move along groups of column indices.
My thinking with this was to make a list of vectors of column indices to choose, such that the first list item is 1:20, the second is 21:40, and so on, in order to break the data into 20 tables of 5 columns each (the number you use can be a different factor of ncol(data)). I underestimated the work to do that, but got ideas from an old SO post to rep the numbers 1 to 20 along the number of columns, sort it, and use that as the grouping then to split the columns.
Then each of those vectors becomes the column indices in select. The resulting list of data frames each gets passed to knitr::kable and kableExtra::kable_styling. Leaving things off there would get map's default of printing names as well, which isn't ideal, so I added a call to purrr::walk to print them neatly.
Note also that making the kable'd tables this way meant putting results="asis" in the chunk options.
---
title: "knitr chunked"
output: pdf_document
---
```{r include=FALSE}
library(knitr)
library(kableExtra)
library(dplyr)
library(purrr)
set.seed(1)
data = data.frame(matrix(rnorm(300, 10, 1), ncol = 100))
```
```{r results='asis'}
split(1:ncol(data), sort(rep_len(1:20, ncol(data)))) %>%
map(~select(data, .)) %>%
map(kable, booktabs = T) %>%
map(kable_styling) %>%
walk(print)
```
Top of the PDF output:
You could use a matrix containing your columns numbers and give it into a for loop with the cat function inside.
---
output: pdf_document
---
```{r, results="asis", echo=FALSE}
library(kableExtra)
set.seed(1)
dat <- data.frame(matrix(rnorm(300, 10, 1), ncol=100))
m <- matrix(1:ncol(dat), 5)
for (i in 1:ncol(m)) {
cat(kable(dat[, m[, i]], 'latex', booktabs=TRUE), "\\newline")
}
```
Result
My data frame has ugly column names, but when displaying the table in my report, I want to their "real" names including special characters '(', new lines, greek letters, repeated names, etc.
Is there an easy way of replacing the names in knitr to allow such formatting?
Proposed solution
What I have tried to do is suppress the printing of the data frame names and use add_header_above for better names and names that span several columns. Some advice I've seen says to use:
x <- kable(df)
gsub("<thead>.*</thead>", "", x)
to remove the column names. That's fine, but the issue is that when I subsequently add_header_above, the original column names come back. If I use col.names=rep('',times=ncol(d.df)) in kable(...) the names are gone but the row remains, leaving a gap between my new column names and the table body. Here's a code chunk to illustrate:
```{r functions,echo=T}
drawTable <- function(d.df,caption='Given',hdr.above){
require(knitr)
require(kableExtra)
require(dplyr)
hdr.2 <- rep(c('Value','Rank'),times=ncol(d.df)/2)
x <- knitr::kable(d.df,format='latex',align='c',
col.names=rep('',times=ncol(d.df))) %>%
kable_styling(bootstrap_options=c('striped','hover',
'condensed','responsive'),position='center',
font_size = 9,full_width=F)
x %>% add_header_above(hdr.2) %>%
add_header_above(hdr.above)
}
```
```{r}
df <- data.frame(A=c(1,2),B=c(4,2),C=c(3,4),D=c(8,7))
hdr.above <- c('A2','B2','C2','D2')
drawTable(df,hdr.above = hdr.above)
```
I am not sure where you got the advice to replace rownames, but it seems excessively complex. It is much easier just to use the built-in col.names argument within kable. This solution works for both HTML and LaTeX outputs:
---
output:
pdf_document: default
html_document: default
---
```{r functions,echo=T}
require(knitr)
df <- data.frame(A=c(1,2),B=c(4,2),C=c(3,4),D=c(8,7))
knitr::kable(df,
col.names = c("Space in name",
"(Special Characters)",
"$\\delta{m}_1$",
"Space in name"))
```
PDF output:
HTML output:
If you're targeting HTML, then Δ is an option too.
I couldn't get the accepted answer to work on HTML, so used the above.
I'm using Rmarkdown to produce a PDF of frequency tables. Producing a complex frequency table after running freq from questionr and adding row groupings with group_rows leads to an alignment problem on the last line of the first group. Reproducible example here:
---
output:
pdf_document:
latex_engine: xelatex
fig_caption: true
---
```{r}
library(haven)
library(questionr)
library(dplyr)
library(magrittr)
library(knitr)
library(kableExtra)
# Build some data
x <- rep(c(1,0),times=50)
y <- c(rep(1,times=25),rep(0,times=75))
z <- c(rep(1,times=75),rep(0,times=25))
# Function to run frequencies on several variables at a time
MassFreq <- function(...){
step1 <- list(...) # Wrap items into a list
step2 <- lapply(step1,freq,total=TRUE) # run frequencies on all items
step3 <- bind_rows(step2) # collapse list results into single df
Response <- unlist(lapply(step2,row.names),recursive=FALSE) # Get row names from frequencies
step4 <- cbind(Response,step3) #Stick row names at front of the dataframe
}
# Run function - returns a data frame object
test <- MassFreq(x,y,z)
# Build table
test %>%
kable(format="latex", booktabs = TRUE, row.names=FALSE) %>%
group_rows("Group 1",1,3) %>%
group_rows("Group 2",4,6) %>%
group_rows("Group 3",7,9)
```
Gives me this upon knitting:
The first "Total" text is right-aligned, but everything else is fine. Adding align=('lrrr') in the kable line does nothing, and align=('crrr') is kind of a mess. Using the index method for group_rows produces the same results. When leaving out the group_rows commands, everything in the first column is left-aligned and looks fine. My hunch is that kableExtra isn't playing well with questionr because the "Total" rows are created when running questionr::freq.
This is a bug in current CRAN version of kableExtra, 0.5.2. It has been fixed in the dev version. I will make a CRAN release next week.
In R, if you create a data frame with a single column, then try to print it into an R Markdown document, it gets turned into a heading and plain text instead of an actual table.
For example, if your R Markdown document contains this code:
# A Heading
```{r, results='asis'}
library("knitr")
test_df <- data.frame("test")
kable(test_df)
test_df_2 <-data.frame(first = "one", second = "two")
kable(test_df_2)
```
It gets converted into this Markdown:
# A Heading
```r
test_df <- data.frame("test")
kable(test_df)
```
X.test.
--------
test
```r
test_df_2 <-data.frame(first = "one", second = "two")
kable(test_df_2)
```
first second
------ -------
one two
Which renders this output:
This makes sense, because the documentation on Markdown considers ------------- to be an H2 second level heading. However, this is not the case for ------ -------, which gets correctly rendered into a table.
Is this a bug? Is the only solution to include at least two columns?