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

烈酒焚心 提交于 2019-11-27 05:56:22

问题


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:


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




回答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)




回答3:


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



回答4:


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



回答5:


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



回答6:


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


来源:https://stackoverflow.com/questions/15937131/print-to-pdf-file-using-grid-table-in-r-too-many-rows-to-fit-on-one-page

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