ymediceacuerdate
ymediceacuerdate

Reputation: 97

Altering padding when combining tableGrob and ggplot objects in R

I am trying to combine multiple tableGrob objects with a ggplot object into a single .png file; I am having trouble understanding how to edit the tableGrob theme parameters in a way that lets me adjust the padding and dimensions of the table objects. Ideally, I want them to be in a 4*1 grid, with minimal padding between each. The text of the table objects should also be left-justified.

I am working with dummy data, and each row of my input dataset will be used to create its own .png file (two rows are included in the code snippet below to generate a reproducible example).

I tried to use this post as an example, and set the grid.arrange spacing based on the "heights" attributes of each table object, but this hasn't quite done the trick. As a side note, right now, the plot gets overwritten each time; I'll fix this later, am just concerned with getting the output dimensions/arrangement correct. Code is below; edited to include library calls, and fixed a typo:

require("ggplot2")
require("gridExtra")
require("grid")

    # Generate dummy data frame
    sampleVector <- c("1", "Amazing", "Awesome", "0.99", "0.75", "0.5", "$5,000.00", "0.55", "0.75", "0.31", "0.89", "0.25", "Strong community support", "Strong leadership", "Partners had experience", "", "CBO not supportive", "Limited experience", "Limited monitoring", "")
    sampleVectorB <- c("3", "Amazing", "Awesome", "0.99", "0.75", "0.5", "$5,000.00", "0.55", "0.75", "0.31", "0.89", "0.25",  "Strong community support", "Strong leadership", "Partners had experience", "", "CBO not supportive", "Limited experience", "Limited monitoring", "")

    sampleDF <- data.frame(rbind(sampleVector, sampleVectorB))
    colnames(sampleDF) <- c("CBO", "PMQ", "HMQ", "ER", "PR", "HR", "NS", "CTI", "Home and Hosp", "Home", "Phone", "Other", "S1", "S2", "S3", "S4", "C1", "C2", "C3", "C4")

    indata <- sampleDF

    #Finds the longest string from a vector of strings (i.e. #chars, incld. whitespace); returns index into this vector that corresponds to this string
    findMax <- function(tempVector){
         tempMaxIndex <- 1

         for(i in 1:length(tempVector)){
              print(nchar(tempVector[i]))
              if(nchar(tempVector[i]) > nchar(tempVector[tempMaxIndex])){
                   tempMaxIndex <- i
              }
         }
         return(tempMaxIndex)
    }

    # Same as above but w/o the colon:
    addWhitespacePlain <- function(stringVec, maxNum){
         for(i in 1:length(stringVec))
         {
              string <- stringVec[i]

              while(nchar(string) < maxNum+1){
                   string <- paste(string, " ")
              }

              stringVec[i] <- string
         }

         return(stringVec)
    }


    staticText <- c("Participant Match Quality", "Hospital-Level Match Quality", "Enrollment Rate", "Participant Readmissions", "Hospital Readmissions", "Net Savings", 
                    "Strengths", "Challenges")
    m <- findMax(staticText)
    staticText <- addWhitespacePlain(staticText, nchar(staticText[m]))

    # Loop through our input data and keep only one CBO each pass
    for(i in 1:length(indata$CBO)){

         # Select only the row that has this CBO's data
         temp <- indata[i,]

         ###############################################################################################

         # MAKE TOP TEXT TABLE (as a DF)

         # Get values from our input data set to fill in the values for the top text portion of the graphic
         topVals <- t(data.frame(temp[2], temp[3], temp[4], temp[5], temp[6], temp[7]))
         topDF <- data.frame(staticText[1:6], topVals, row.names=NULL)
         colnames(topDF) <- c(paste("CBO", temp[1]), " ")

         # Find which of the strings from the top text portion is the longest (i.e. max # of chars; including whitespace)
         m2 <- findMax(rownames(topDF)) # returns an index into the vector; this index corresponds to string w/max num of chars

         # Add whitespace to non-max strings so all have the same length and also include colons
         rownames(topDF) <-  addWhitespacePlain(rownames(topDF), nchar(rownames(topDF)[m2]))

         # for testing
       #  print(topDF, right=FALSE)

         ###############################################################################################

         # MAKE BAR CHART

         #Subset the data to select the vars we need for the horizontal bar plot
         graphdata <- t(data.frame(temp[,8:12]))
         vars <- c("CTI", "Home & Hosp.", "Home", "Phone", "Other")
         graphDF <- data.frame(vars, graphdata, row.names = NULL)
         colnames(graphDF) <- c("vars", "values")

         # Make the plot (ggplot object)
         barGraph <- ggplot(graphDF, aes(x=vars, y=values,fill=factor(vars))) +
         geom_bar(stat = "identity") +
         theme(axis.title.y=element_blank())+
         theme(legend.position="none")+
         coord_flip()

        # print(barGraph)

         ###############################################################################################

         # MAKE BOTTOM TEXT TABLE

         strengths <- t(data.frame(temp[13], temp[14], temp[15], temp[16]))
         challenges <- t(data.frame(temp[17], temp[18], temp[19], temp[20]))

         #Drop nulls
         strengths <- data.frame(strengths[which(!is.na(strengths)),], row.names=NULL)
         challenges <- data.frame(challenges[which(!is.na(challenges)),], row.names=NULL)

         colnames(strengths) <- c(staticText[7])
         colnames(challenges) <- c(staticText[8])

         ###############################################################################################

         # OUTPUT (padding not resolved yet)

         # Set the path for the combined image
         png("test1", height=1500, width=1000)

       #customTheme <- ttheme_minimal(core=list(fg_params=list(hjust=0, x=0.1)),
       #                           rowhead=list(fg_params=list(hjust=0, x=0)))

       # top<-tableGrob(topDF, theme=customTheme)
       # bottom_strength <- tableGrob(strengths, theme=customTheme)
       # bottom_challenges <- tableGrob(challenges, theme=customTheme)

       top<-tableGrob(topDF)
       bottom_strength <- tableGrob(strengths)
       bottom_challenges <- tableGrob(challenges)

        x <- sum(top$heights)
        y <- sum(bottom_strength$heights)
        z <- sum(bottom_challenges$heights)

         grid.arrange(top, barGraph, bottom_strength, bottom_challenges,
                     as.table=TRUE,
                    heights=c(2, 1, 2, 2),
                    nrow = 4)
                   # heights= unit.c(x, unit(1), y, z))
         dev.off()
    }

Upvotes: 2

Views: 1334

Answers (1)

baptiste
baptiste

Reputation: 77096

Your example is too complicated, I'm not sure what exactly is the issue. The following 4x1 layout has zero padding, is that what you're after?

ta <- tableGrob(iris[1:4,1:2])
tb <- tableGrob(mtcars[1:3,1:3])
tc <- tableGrob(midwest[1:5,1:2])
p <- qplot(1,1) + theme(plot.background=element_rect(colour = "black"))
h <- unit.c(sum(ta$heights), unit(1,"null"), sum(tb$heights), sum(tc$heights))
grid.newpage()
grid.arrange(ta,p,tb,tc, heights=h)

enter image description here

Upvotes: 9

Related Questions