Related
I'm new to grobbing and I am trying to create a simple grid.arrange object but cannot figure out how to might a compact/tight layout.
Below is a simple example of what I'm trying to run and the grob that I get.
library(grid)
library(gridExtra)
name = textGrob("My Name", gp=gpar(fontsize = 20, fontface = "bold"))
name2 = textGrob("Second Name", gp=gpar(fontsize = 16))
tbl = tableGrob(head(iris))
grid.arrange(name, name2, tbl)
UPDATE:
Using the answer found here I was able to get the text compact but I am still struggling to get the table to be right under the text.
library(grid)
library(gridExtra)
name = textGrob("My Name", gp=gpar(fontsize = 20, fontface = "bold"))
name2 = textGrob("Second Name", gp=gpar(fontsize = 16))
tbl = tableGrob(head(iris))
margin = unit(0.5, "line")
grid.newpage()
grid.arrange(name, name2, tbl,
heights = unit.c(grobHeight(name) + 1.2*margin,
grobHeight(name2) + margin,
unit(1,"null")))
Typically you'd use the top= argument for a single grob. With two grobs like this, it might be easiest to combine them in a table; the major hurdle is that gtable doesn't consider justification so you have to adjust the positions yourself,
library(gtable)
justify <- function(x, hjust="center", vjust="top", draw=FALSE){
w <- sum(x$widths)
h <- sum(x$heights)
xj <- switch(hjust,
center = 0.5,
left = 0.5*w,
right=unit(1,"npc") - 0.5*w)
yj <- switch(vjust,
center = 0.5,
bottom = 0.5*h,
top=unit(1,"npc") - 0.5*h)
x$vp <- viewport(x=xj, y=yj)
if(draw) grid.draw(x)
return(x)
}
title <- gtable_col('title', grobs = list(name,name2),
heights = unit.c(grobHeight(name) + 1.2*margin,
grobHeight(name2) + margin))
grid.newpage()
grid.arrange(justify(title, vjust='bottom'), justify(tbl))
I have a fairly wide table (4/3 of page width) that I'm trying to print using grid.table or grid.arrange (via tableGrob) into a pdf file. The table goes beyond page boundaries and gets clipped. Is there a way to force grid.table/grid.arrange to scale the table to the print area?
There is a way, but it's unclear what should happen when the text is too wide to fit in some cells.
One option is to set the widths manually,
library(grid)
library(gridExtra)
g1 <- g2 <- tableGrob(head(iris, 10), rows=NULL)
g2$widths <- unit(rep(1/ncol(g2), ncol(g2)), "npc")
grid.newpage()
gt = arrangeGrob(textGrob("page 1"), textGrob("page 2"),
rectGrob(gp=gpar(fill="grey98")),
rectGrob(gp=gpar(fill="grey98")),
nullGrob(),
layout_matrix=rbind(c(1,5,2), c(3,5,4)),
widths = unit(c(1,5,1),c("null", "cm", "null")),
heights = unit(c(1, 1),c("line", "null")),
vp = viewport(width=0.9, height=0.9))
tc = list(g1, g2)
gt <- gtable::gtable_add_grob(gt, tc, l=c(1,3), t=2,
name="newgrobs")
grid.draw(gt)
but of course with a fixed font size it means that some text might be cut.
Probably a better option is to introduce line breaks, and/or (slightly) reduce the font size.
g3 <- tableGrob(head(iris, 10), theme = ttheme_default(7),
rows=NULL, cols=gsub("\\.", "\\\n",names(iris)))
g3$widths <- unit(rep(1/ncol(g2), ncol(g2)), "npc")
grid.newpage()
gt = arrangeGrob(textGrob("page 1"), textGrob("page 2"),
rectGrob(gp=gpar(fill="grey98")),
rectGrob(gp=gpar(fill="grey98")),
nullGrob(),
layout_matrix=rbind(c(1,5,2), c(3,5,4)),
widths = unit(c(1,1,1),c("null", "line", "null")),
heights = unit(c(1, 1),c("line", "null")),
vp = viewport(width=0.9, height=0.9))
tc = list(g2, g3)
gt <- gtable::gtable_add_grob(gt, tc, l=c(1,3), t=2,
name="newgrobs")
grid.draw(gt)
I got this done using font sizes. Not the best solution (requires manual intervention) but maybe someone can contribute something more elegant.
termTable = tableGrob(terms, h.even.alpha=1, h.odd.alpha=1, v.even.alpha=0.5, v.odd.alpha=1, core.just='left', rows=c(),
gpar.coretext =gpar(fontsize=8),
gpar.coltext=gpar(fontsize=10, fontface='bold'),
gpar.rowtext=gpar(fontsize=10, fontface='bold')
)
With the most recent version of gridExtra, the correct formatting to update rimorob's answer is:
termTable = tableGrob(terms, theme =ttheme_default(gpar.coretext =gpar(fontsize=8), gpar.coltext=gpar(fontsize=10, fontface='bold'), gpar.rowtext=gpar(fontsize=10, fontface='bold') ))
I have a fairly wide table (4/3 of page width) that I'm trying to print using grid.table or grid.arrange (via tableGrob) into a pdf file. The table goes beyond page boundaries and gets clipped. Is there a way to force grid.table/grid.arrange to scale the table to the print area?
There is a way, but it's unclear what should happen when the text is too wide to fit in some cells.
One option is to set the widths manually,
library(grid)
library(gridExtra)
g1 <- g2 <- tableGrob(head(iris, 10), rows=NULL)
g2$widths <- unit(rep(1/ncol(g2), ncol(g2)), "npc")
grid.newpage()
gt = arrangeGrob(textGrob("page 1"), textGrob("page 2"),
rectGrob(gp=gpar(fill="grey98")),
rectGrob(gp=gpar(fill="grey98")),
nullGrob(),
layout_matrix=rbind(c(1,5,2), c(3,5,4)),
widths = unit(c(1,5,1),c("null", "cm", "null")),
heights = unit(c(1, 1),c("line", "null")),
vp = viewport(width=0.9, height=0.9))
tc = list(g1, g2)
gt <- gtable::gtable_add_grob(gt, tc, l=c(1,3), t=2,
name="newgrobs")
grid.draw(gt)
but of course with a fixed font size it means that some text might be cut.
Probably a better option is to introduce line breaks, and/or (slightly) reduce the font size.
g3 <- tableGrob(head(iris, 10), theme = ttheme_default(7),
rows=NULL, cols=gsub("\\.", "\\\n",names(iris)))
g3$widths <- unit(rep(1/ncol(g2), ncol(g2)), "npc")
grid.newpage()
gt = arrangeGrob(textGrob("page 1"), textGrob("page 2"),
rectGrob(gp=gpar(fill="grey98")),
rectGrob(gp=gpar(fill="grey98")),
nullGrob(),
layout_matrix=rbind(c(1,5,2), c(3,5,4)),
widths = unit(c(1,1,1),c("null", "line", "null")),
heights = unit(c(1, 1),c("line", "null")),
vp = viewport(width=0.9, height=0.9))
tc = list(g2, g3)
gt <- gtable::gtable_add_grob(gt, tc, l=c(1,3), t=2,
name="newgrobs")
grid.draw(gt)
I got this done using font sizes. Not the best solution (requires manual intervention) but maybe someone can contribute something more elegant.
termTable = tableGrob(terms, h.even.alpha=1, h.odd.alpha=1, v.even.alpha=0.5, v.odd.alpha=1, core.just='left', rows=c(),
gpar.coretext =gpar(fontsize=8),
gpar.coltext=gpar(fontsize=10, fontface='bold'),
gpar.rowtext=gpar(fontsize=10, fontface='bold')
)
With the most recent version of gridExtra, the correct formatting to update rimorob's answer is:
termTable = tableGrob(terms, theme =ttheme_default(gpar.coretext =gpar(fontsize=8), gpar.coltext=gpar(fontsize=10, fontface='bold'), gpar.rowtext=gpar(fontsize=10, fontface='bold') ))
The grid-package has a special tool for generating axis. It writes the axis outside the current viewport and the height using grobHeight is therefore considered to be 0mm. Unfortunately I need to make space for the axis and I want to know the exact height of the object. Below is an example that illustrates the problem:
library(grid)
plotColorBar <- function () {
grid.newpage()
xg <- xaxisGrob(at=c(0,.25,.5,.75, 1),
label= sprintf("%d %%", c(0,.25,.5,.75, 1)*100),
main=FALSE)
bar_layout <- grid.layout(nrow=3, ncol=3,
heights = unit.c(unit(.80, "npc"),
grobHeight(xg),
unit(.2, "npc") - grobHeight(xg)),
widths = unit.c(unit(.25, "npc"),
unit(1, "npc") -
unit(.5, "npc"),
unit(.25, "npc")))
pushViewport(viewport(layout=bar_layout, name="Bar_layout"))
pushViewport(viewport(layout.pos.row=3,
layout.pos.col=2,
name="Color_bar"))
grid.draw(xg)
bar_clrs <- colorRampPalette(c("red", "blue"), space="Lab")(101)
grid.raster(t(as.raster(bar_clrs)), width=1, height=1, interpolate=FALSE)
popViewport()
pushViewport(viewport(layout.pos.row=1,
layout.pos.col=1:3,
name="Main_exc_bar"))
grid.rect(gp=gpar(col="black", fill="#00000022"))
grid.text("Coool")
popViewport()
}
png(filename="axisWihtoutHeight.png", width=250, height=250, res=96)
plotColorBar()
dev.off()
Gives the following image:
Notice that the grey area covers the axis text. When I try convertY(grobHeight(xg), "mm") it returns 0mm.
Now applying the #baptiste recommended fix improves the image slightly:
heightDetails.xaxis = function(x) do.call(sum, lapply(x$children, grobHeight))
png(filename="axisWihtHeight.png", width=250, height=250, res=96)
plotColorBar()
dev.off()
As you can see the text for some reason is twice the height. Adjusting this manually through the following option although this does feel a little clumsy:
heightDetails.xaxis = function(x) {
grobHeight(x$children$ticks) +
grobHeight(x$children$labels) +
grobHeight(x$children$labels)
}
png(filename="axisWihtDoubleHeight.png", width=250, height=250, res=96)
plotColorBar()
dev.off()
Final solution
As suggested it seems that unit(1.5*cex, "line") does the job nicely:
heightDetails.xaxis = function(x) {
cex <- 1
if (!is.null(x$children$labels$gp$cex))
cex <- x$children$labels$gp$cex
grobHeight(x$children$ticks) +
unit(1.5*cex, "line")
}
you'll want to define a heightDetails method for the gTree, something along those lines
heightDetails.xaxis = function(x) do.call(sum, lapply(x$children, grobHeight))
I have recently started using the grid.table function from the gridExtra package to turn tabular data into png image files for use on the web. I've been delighted with it so far as it produces very good-looking output by default, sort of like a ggplot2 for tables. Like the person who asked this question I would love to see the ability to specify the justification for individual columns but that would be icing on what is an already more-ish cake.
My question is whether it is possible to add text around a grid.table so that I can give plotted tables a title and a footnote. It seems to me this should be feasible, but I don't know enough about grid graphics to be able to work out how to add grobs to the table grob. For example, this code:
require(gridExtra)
mydf <- data.frame(Item = c('Item 1','Item 2','Item 3'),
Value = c(10,15,20), check.names = FALSE)
grid.table(mydf,
gpar.coretext=gpar(fontsize = 16),
gpar.coltext = gpar(fontsize = 16),
gpar.rowtext = gpar(fontsize = 16),
gpar.corefill = gpar(fill = "blue", alpha = 0.5, col = NA),
h.even.alpha = 0.5,
equal.width = FALSE,
show.rownames = FALSE,
show.vlines = TRUE,
padding.h = unit(15, "mm"),
padding.v = unit(8, "mm")
)
generates this plot:
when I would really like to be able to do something like the following in code rather than by editing the image with another application:
To place text close to the table you'll want to evaluate the table size first,
library(gridExtra)
d <- head(iris)
table <- tableGrob(d)
grid.newpage()
h <- grobHeight(table)
w <- grobWidth(table)
title <- textGrob("Title", y=unit(0.5,"npc") + 0.5*h,
vjust=0, gp=gpar(fontsize=20))
footnote <- textGrob("footnote",
x=unit(0.5,"npc") - 0.5*w,
y=unit(0.5,"npc") - 0.5*h,
vjust=1, hjust=0,gp=gpar( fontface="italic"))
gt <- gTree(children=gList(table, title, footnote))
grid.draw(gt)
Edit (17/07/2015) With gridExtra >=2.0.0, this approach is no longer suitable. tableGrob now returns a gtable, which can be more easily customised.
library(gridExtra)
d <- head(iris)
table <- tableGrob(d)
library(grid)
library(gtable)
title <- textGrob("Title",gp=gpar(fontsize=50))
footnote <- textGrob("footnote", x=0, hjust=0,
gp=gpar( fontface="italic"))
padding <- unit(0.5,"line")
table <- gtable_add_rows(table,
heights = grobHeight(title) + padding,
pos = 0)
table <- gtable_add_rows(table,
heights = grobHeight(footnote)+ padding)
table <- gtable_add_grob(table, list(title, footnote),
t=c(1, nrow(table)), l=c(1,2),
r=ncol(table))
grid.newpage()
grid.draw(table)
If you want just the title (no footnote), here is a simplified version of #baptiste's example:
title <- textGrob("Title", gp = gpar(fontsize = 50))
padding <- unit(0.5,"line")
table <- gtable_add_rows(
table, heights = grobHeight(title) + padding, pos = 0
)
table <- gtable_add_grob(
table, list(title),
t = 1, l = 1, r = ncol(table)
)
grid.newpage()
grid.draw(table)