Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge vertical cells in tableGrob output tables in R?

I have a question similar to the one here, where OP aimed to merge the headers of the column present in the table horizontal merging. Here I wish to merge groups of cells which are vertically lined. The following is my target table design made in Microsoft Excel software:-

enter image description here

My attempt at making the target table using the method prescribed for question with horizontal merging

library(gridExtra)
library(grid)
library(ggplot2)

alphabets <- c(rep("A", 3), rep("B", 3), rep("C",3))
numbers <- c(rep(c(1,2,3), 3))
sounds <- c('Ayes','Bees','Cees')

df1 <- data.frame(alphabets = alphabets,numbers=numbers)
df2 <- data.frame(sounds = sounds)

tab1 <- tableGrob(df1,theme = ttheme_default(),row=NULL)
tab2 <- tableGrob(df2,theme = ttheme_default(),row=NULL)

halign <- combine(tab2,tab1, along =1)

grid.draw(halign)

This will give me the following output:-

enter image description here

I have a temporary work around for now. But it will fail if I am merging even number of cells.

sounds <- c('','Ayes','','','Bees','','','Cees','')
df2 <- data.frame(sounds = sounds)
tab2 <- tableGrob(df2,theme = ttheme_default(),row=NULL)
halign <- combine(tab2,tab1, along =1)
grid.draw(halign)

The output for this is:-

enter image description here

My question is how can you merge two table grob objects and keep the length of the largest table for the final output.

Thanks you for your efforts, the answers will greatly aid in the presentation of the results of my analysis.

Cheers

Lune3141

like image 892
Lune3414 Avatar asked Oct 29 '22 19:10

Lune3414


1 Answers

Why not set the locations first, then send it to tableGrob?

# Set locations you want to put sounds at
df2$toBind <- c(2, 5, 8)

# Set locations to allow merge
df1$toBind <- 1:nrow(df1)

# Merge them together
toPrint <-
  right_join(df2, df1) %>%
  mutate(sounds = ifelse(is.na(sounds)
                         , ""
                         , as.character(sounds))) %>%
  select(-toBind)

grid.table(toPrint, row = NULL)

Produces the table you have above, though it requires you to manually set the locations you want them.

The larger question may be what you are trying to accomplish here, and why you don't want to repeat the sounds column. Depending on your output goal, you may want to look at something like booktabs in LaTeX.

Sorry for the confusion -- I was looking for a more reliable way to generate the table you had at the end of your question. This appears to be what you need to do to generate the "merged" cell look:

halign$layout[halign$layout$t != 1 &
                halign$layout$l == 1, c("t")] <-
  c(2,5,8,2,5,8)

halign$layout[halign$layout$b != 1  &
                halign$layout$l == 1, c("b")] <-
  c(4,7,10,4,7,10)

grid.draw(halign)

This is finding everything in the first column (l == 1) that is not the first row (t != 1 and b != 1 respectively) and setting the top and bottoms to new locations. You will either need to manually adjust the locations or do it programatically for your actual data (e.g., how many rows it should match, and do the arithmetic for it).

enter image description here

As an additional aside, to make the merged rows stand out more, you may want to consider setting different background colors when generating the tab2 grob. e.g.,:

tab2 <- tableGrob(df2
                  , theme = ttheme_default(core=list(bg_params = list(fill = c("white","darkgrey"), col=NA)) )
                  , rows = NULL)

enter image description here

Example with even number of rows:

halign_alt <- combine(tab2,tab3, along =1)

halign_alt$layout[halign_alt$layout$t != 1 &
                    halign_alt$layout$l == 1, c("t")] <-
  c(2,5,7,2,5,7)

halign_alt$layout[halign_alt$layout$b != 1  &
                    halign_alt$layout$l == 1, c("b")] <-
  c(4,6,9,4,6,9)

grid.draw(halign_alt)

enter image description here

like image 118
Mark Peterson Avatar answered Nov 14 '22 12:11

Mark Peterson