print to pdf file using grid.table in r - too many rows to fit on one page

流过昼夜 提交于 2019-11-28 12:07:18

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()

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)

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()

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()

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

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()
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!