15

I'm trying to output a dataframe of about 40 rows and 5 columns to a .pdf file using grid.table in gridExtra package of R.

However, 40 rows is too long for a page so the .pdf file only shows part of the dataframe. I want to know if I can print two columns on one page so all of the rows show up on one page. Alternatively, I need to know how to print the dataframe over multiple pages. Thanks, John

1
  • 2
    Why not just adjust the size of the pdf device? Commented Apr 10, 2013 at 22:30

6 Answers 6

7

I'd suggest the following strategy: create the tableGrob, query its heights, split the rows to fit each page,

library(gridExtra)
library(grid)
d <- iris[sample(nrow(iris), 187, TRUE),]
tg <- tableGrob(d, rows = seq_len(nrow(d))) 

fullheight <- convertHeight(sum(tg$heights), "cm", valueOnly = TRUE)
margin <- unit(0.51,"in")
margin_cm <- convertHeight(margin, "cm", valueOnly = TRUE)
a4height <- 29.7 - margin_cm
nrows <- nrow(tg)
npages <- ceiling(fullheight / a4height)

heights <- convertHeight(tg$heights, "cm", valueOnly = TRUE) 
rows <- cut(cumsum(heights), include.lowest = FALSE,
            breaks = c(0, cumsum(rep(a4height, npages))))

groups <- split(seq_len(nrows), rows)

gl <- lapply(groups, function(id) tg[id,])

pdf("multipage.pdf", paper = "a4", width = 0, height = 0)
for(page in seq_len(npages)){
  grid.newpage()
  grid.rect(width=unit(21,"cm") - margin,
            height=unit(29.7,"cm")- margin)
  grid.draw(gl[[page]])
}
## alternative to explicit loop:
## print(marrangeGrob(grobs=gl, ncol=1, nrow=1, top=NULL))
dev.off()

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

5

Try this for drawing table on a pdf file that span multiple pages using gridExtra package:

  1. Adjust pdf device aspect ratio

    pdf(file = myfile.pdf, height = 12, width = 26)
    
  2. Split the large data frame into chunks and call grid.newpage before drawing a table.

    require(gridExtra)
    pdf(file = myfile.pdf, height = 12, width = 26)
    grid.newpage()
    grid.table(sga_hits[1:38, ], show.rownames = FALSE)
    grid.newpage()
    grid.table(sga_hits[39:75, ], show.rownames = FALSE)
    dev.off()
    

Automate the above as follows:

    require(gridExtra)
    pdf(file = myfile.pdf, height = 12, width = 26)
    total_rows_per_page = 38 
    start_row = 1 

    if(total_rows_per_page > nrow(sga_hits)){
         end_row = nrow(sga_hits)
    }else {
         end_row = total_rows_per_page 
    }    

    for(i in 1:ceiling(nrow(sga_hits)/total_rows_per_page)){

       grid.newpage()   

       grid.table(sga_hits[start_row:end_row, ], show.rownames = FALSE)

       start_row = end_row + 1

       if((total_rows_per_page + end_row) < nrow(sga_hits)){

            end_row = total_rows_per_page + end_row

       }else {

            end_row = nrow(sga_hits)
       }    
    }

    dev.off()

2 Comments

may i ask from where the "sga_hits" is from? It seems you forgot to specify it
@Haakonkas you may take it as the data frame you are working on. It can be any data frame. If you want a different name, please change it at your own discretion
3

Implementing viewports from the grid is one potential solution.

A viewport defines a region in the graphics device. It is sometimes useful to define a viewport, then push it and draw inside it. A different viewport may then be pushed and drawn inside of; this method amounts to a simple way to arrange objects on a page.

First, define page and margin sizes.

# Assume total page size is 8.5in x 11in
vp.page <- viewport(x = 0.5, y = 0.5,
                   width = unit(x = 8.5, units = "inches"),
                   height = unit(x = 11, units = "inches"))

# Assume 0.5in margins (i.e., 0.5 left, right, bottom, top)
# This totals 1in for each dimension
vp.marg <- viewport(x = 0.5, y = 0.5,
                    width = (7.5 / 8.5), height = (10 / 11))

Next, Define viewports for each column.

To arrange columns horizontally within a viewport, their x positions will be equally spaced in the interval (0,1).

In the 2 column case, x1 = 0.25 and x2 = 0.75:

# Define the viewport for column 1
vp.col1 <- viewport(x = 0.25, y = 0.5, width = 0.5, height = 1)

# Define the viewport for column 2
vp.col2 <- viewport(x = 0.75, y = 0.5, width = 0.5, height = 1)

Now, actual data is defined. This data will also need to be "grob'd" to be drawn into viewports.

# Assume data is stored as `dat` and has 40 rows
# Grob the data for column 1
col1 <- tableGrob(dat[1:20,], rows = NULL)

# Grob the data for column 2
col2 <- tableGrob(dat[21:40,], rows = NULL)

Now, draw the pdf:

# Initiate the pdf
pdf("results.pdf", height = 11, width = 8.5)
# Push the viewports for page and margin
pushViewport(vp.page); pushViewport(vp.marg)

# Push column 1
pushViewport(vp.col1)
# Draw column 1
grid.draw(col1)

# Return to the previous viewport
upViewport()

# Push the viewport for column 2
pushViewport(vp.col2)
# Draw column 2
grid.draw(col2)

# End the pdf and save it
dev.off()

Comments

2

pdf() has a width and a height argument.

Your best bet is to enlarge the dimensions and then if you're printing to paper, whichever program you're using would most likely be better suited.

Alternatively, if you want to print two columns on one page, just iterate over the columns:

# assuming `myDF` is your data.frame

pdf("filename.pdf")
for (cl in seq(from=1, to=ncol(myDF)-1, by=2)) {
      plot.new()
      grid.table(myDF[, cl+(0:1)])
    }
dev.off()

Comments

2

One way is to shrink the font the font size and the horizontal/vertical padding.

grid.table(mtcars, gpar.coretext = gpar(fontsize=6), gpar.coltext = gpar(fontsize=6), padding.h=unit(2, "mm"), padding.v=unit(2, "mm"), show.rownames = TRUE)

Comments

1

I just used a hack. I printed the table to html using R2HTML and then I converted the html to pdf using wkhtmltopdf.

in R:

library(R2HTML)
HTML(table, file="table.html")

in the shell

wkhtmltopdf table.html table.pdf

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.