For the past month, I have been working on a project using GridExtra to draw a daily KPI report. I was basically using R to do some normal activities that we can easily done in Excel. However, since I need to make sure the result is a png instead of html, I got the chance to explore this amazing package GridExtra and GridTable. And I found out that the package although it may seem very complicated at first glance, it can be very useful and flexible to use. So, I have made this tutorial to show you guys some functions I always use.
First, this is the data I use for example. This is the data of New York Airbnb listings number throughout 2000–2018 in different boroughs of NYC. You can easily get from AIRDNA website.
- Load packages
library(grid)
library(gtable)
library(grid extra)
2. Define themes
# default theme has background color and borders
tth <- ttheme_default()
# minimal theme doesn’t have background color and borders
tthminimal <- ttheme_minimal()
tab <- tableGrob(df,theme = tth)
png(“table.png”, height=200, width=1000)
grid.draw(tab)
dev.off()
You can also change parameters in the theme, including foreground parameters, background parameters and column head parameters.
thbody <- ttheme_minimal(
core = list(fg_params=list(fontface=’plain’,cex=1.2,hjust=1,x=0.95),bg_params=list(col=’grey’,lwd=2)),
colhead = list(fg_params=list(col=’black’,fontface=’bold’,cex=1.5),bg_params=list(col=’grey’,fill=’yellow’,lwd=2))
)
tab <- tableGrob(df,theme = thbody)
# core — boday of table; colhead — column head of table
# cex — font size
# hjust — 1 is align to right, 0 is align to left
# x — distance to the left border
# lwd — line width
3. Edit a cell
First, let’s learn about the structure behind the table we see here.
> tab$layout
t l b r z clip name
1 1 1 1 1 1 on rowhead-fg
2 2 1 2 1 2 on rowhead-fg
8 1 1 1 1 0 on rowhead-bg
9 2 1 2 1 0 on rowhead-bg
15 1 2 1 2 1 on colhead-fg
16 1 3 1 3 2 on colhead-fg
36 1 2 1 2 0 on colhead-bg
37 1 3 1 3 0 on colhead-bg
57 2 2 2 2 1 on core-fg
58 3 2 3 2 2 on core-fg
This is an example of the structure. We can see that we can locate a cell by the top, left, bottom or right border of the cell and the cell name. The name is segmented to row head background and foreground, column head background and foreground, core background and foreground.
# I want to highlight 2018 cell
red <- which(grepl(‘colhead-bg’,tab$layout$name) & tab$layout$r==21)
tab$grobs[[red]] <- editGrob(tab$grobs[[red]],gp=gpar(fill=’red’))
4. Edit a column or a row
# I want to bold the 2018 numbers and change the numbers to red
bold <-which(grepl(‘core-fg’,tab$layout$name) & tab$layout$r==21)
for (i in bold) tab$grobs[[i]] <- editGrob(tab$grobs[[i]],gp=gpar(fontface=’bold’,col=’red’))
# I can also change alignment of a column
align<- which(grepl(‘core-fg’,tab$layout$name) & tab$layout$l==2)
for (i in align){
tab$grobs[[i]]$x = unit(0.01,’npc’)
tab$grobs[[i]]$hjust = 0
}
5. Add header or footnote
You can also add header and footnote to your table.
# Add header
head <- data.frame(rowone=c(‘Airbnb Data’,’1/7/2020'),rowtwo=c(‘Airbnb Data’,’1/7/2020'))
thhead <-ttheme_minimal(
core = list(fg_params=list(fontface=’bold’,col=’red’,cex=1.2),bg_params=list(col=’grey’,lwd=2))
)
header <- tableGrob(head[1,1],theme = thhead)
# combine with table
tab <- gtable_combine(header,tab,along = 2)
# now we can check the layout
> tab$layout
t l b r z clip name
1 1 1 1 1 1 on core-fg
2 1 1 1 1 0 on core-bg
3 2 1 2 1 1 on rowhead-fg
4 3 1 3 1 2 on rowhead-fg
5 4 1 4 1 3 on rowhead-fg
After combine the header and table, we can see there are two new core_fg added to the layout. Then we can merge the header cell by changing its rigth border.
# merge the cells
tab$layout[1:2,’r’] = rep(max(tab$layout$r),2)
# I have removed the rownumbers by specifying rows=Null while creating the table grob
tab <- tableGrob(df,theme = thbody,rows = NULL)