6

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

zx8754
  • 52,746
  • 12
  • 114
  • 209
Lune3414
  • 144
  • 1
  • 9
  • Not exactly what you were asking for, but a quick and easy fix would be to have the name of the "merged" cells in the top row for that block instead of the middle row for it's block. The complex but more accurate answer would be to make more use of the arrange.grid() function, as shown on https://cran.r-project.org/web/packages/gridExtra/vignettes/arrangeGrob.html . – Xizam Sep 27 '16 at 14:08
  • @Xizam That will still be a work around the real problem of not being able to merge vertical cells (like we can in excel soft wares). I considered the idea of using the top row for labeling a block. It does not work very well aesthetically when the block sizes are a bit longish. – Lune3414 Sep 27 '16 at 14:15

1 Answers1

2

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

baptiste
  • 75,767
  • 19
  • 198
  • 294
Mark Peterson
  • 9,370
  • 2
  • 25
  • 48
  • thanks @Mark Peterson. Your solution is an improvement over my solution. Unfortunately it is not achieving what [this] (http://stackoverflow.com/questions/33214671/merging-table-header-cells-using-tablegrob/33218463#33218463) solution did for merging horizontal columns. – Lune3414 Sep 27 '16 at 16:11
  • I had misunderstood and was trying to match what you posted, rather than with the merging as I now understand it. See the edit for a version that works. – Mark Peterson Sep 27 '16 at 16:36
  • That is a really cool way of getting the table. Sorry I am a bit new to the $layout. One question. So by changing the halign$layout$t, you are moving the top and bottom cells which are not of the target color to a new location. Is that correct. Also we will still have the problem when we have to merge even number of cells (say 2 cells). For now I will accept your answer as it does get me almost there. Cheers – Lune3414 Sep 27 '16 at 17:01
  • It is moving the location of the top and bottom of each cell (except the header), not just moving the cell and leaving blank cells. The number of cells is not an issue, it should correctly center, as long as you set where top and bottom go. – Mark Peterson Sep 27 '16 at 17:12
  • Thanks a lot for your efforts. This solution is perfect. I will try to post a solution later in the week which does the $layout arithmetic automatically. Cheers – Lune3414 Sep 27 '16 at 19:02