Combining Grid.Table and Base Package Plots in R Figure

Combining grid.table and base package plots in R figure

You forgot to pop the viewport, so your second grid.table was still in first viewport. So just use popViewport() after each grid.table commands and it should work.

library(gridBase)
library(gridExtra)

pdf("test-grid.pdf")
par(mfrow=c(2,2))

data(mtcars)
sample_table1 <- matrix(1,3,5)
sample_table2 <- matrix(2,2,2)

plot.new()
vps <- baseViewports()
pushViewport(vps$figure)
vp1 <-plotViewport()
grid.table(sample_table1)
popViewport()

plot.new()
vps <- baseViewports()
pushViewport(vps$figure)
vp1 <-plotViewport()
grid.table(sample_table2)
popViewport()

plot(mtcars$mpg, mtcars$cyl)
plot(mtcars$disp, mtcars$hp)

dev.off()

Arrange base plots and grid.tables on the same page

To combine base plots and grid objects the package gridBase is useful.

A rough worked example base on your layout above

library(grid)
library(gridBase)
library(gridExtra)

layout(matrix(c(1,3, 2,3, 4,3), nrow = 3, ncol = 2, byrow = TRUE))

# First base plot
plot(1:10)

# second base plot
frame()
# Grid regions of current base plot (ie from frame)
vps <- baseViewports()
pushViewport(vps$inner, vps$figure, vps$plot)
# Table grob
grob <- tableGrob(iris[1:2,1:2])
grid.draw(grob)

popViewport(3)

# third base plot
plot(1:10)

# fourth
frame()
vps <- baseViewports()
pushViewport(vps$inner, vps$figure, vps$plot)
grid.draw(grob)
popViewport(3)

Which gives

Sample Image

combine barplot and grid.table

If you want to make the barplot in ggplot2, you need to reshape your data into long format. Based on your example data, the following code:

library(ggplot2)
library(gridExtra)
library(reshape2)

bp <- ggplot(melt(df, id.vars = 1),
aes(x = variable, y = value, fill = sample_id)) +
geom_bar(stat = 'identity', position = 'dodge') +
scale_fill_manual(values = rainbow(10)) +
labs(x = NULL, y = NULL) +
coord_flip() +
theme_minimal(base_size = 14)
gt <- tableGrob(df, rows = NULL, theme = ttheme_minimal())

grid.arrange(bp, gt, ncol = 2, widths = c(2.5,2))

which gives the following result:

Sample Image

Adding a small table to a base graphics multiple plot chart

With plotrix you can modify your code as follows:

library(plotrix)
Table1<- data.frame( a=1:6,b=2:7,c=3:8)
layout(matrix(c(1:4), 2, 2, byrow = FALSE), widths=c(1,1), heights=c(1,1))
plot(1:6)
plot(2:7)
plot(3:8)
plot.new()
addtable2plot(0,0,Table1,
xpad=6, ypad=2,
bty='o',
display.rownames = TRUE,
hlines = TRUE,
vlines = TRUE,
title = "The table")

Sample Image

positioning plots and table

Here's an example of how to combine two base plots and a grid.table in the same figure.

library(gridExtra)

layout(matrix(c(1,0,2,0), 2))
hist(iris$Sepal.Length, col="lightblue")
hist(iris$Sepal.Width, col="lightblue")

pushViewport(viewport(y=.25,height=.5))
grid.table(head(iris), h.even.alpha=1, h.odd.alpha=1,
v.even.alpha=0.5, v.odd.alpha=1)

The coordinates sent to viewport are the center of the panel. Too see exactly where its boundaries are you can call grid.rect().

Sample Image

Combine base and ggplot graphics in sub figures of graphic device

One solution (that does not involve compromising on the plots you want to make) is to use the layout argument in viewpoint() to set up a grid for the sub plots, that overlays the par(mfrow)/par(mfcol) grid.

Setting up the viewpoint grid as a multiple of the par(mfrow) dimensions allows you to nicely place your subplots in the desired grid position. The scale of the viewpoint grid will dictate the size of the subplot - so a bigger grid will lead to smaller subplots.

# base R plots
par(mfrow = c(2, 3))
plot(x = mtcars$mpg, y = mtcars$cyl)
plot(x = mtcars$mpg, y = mtcars$disp)
plot(x = mtcars$mpg, y = mtcars$hp)
plot(x = mtcars$mpg, y = mtcars$drat)
plot(x = mtcars$mpg, y = mtcars$wt)
plot(x = mtcars$mpg, y = mtcars$qsec)

# set up viewpoint grid
library(grid)
pushViewport(viewport(layout=grid.layout(20, 30)))

# add ggplot subplots (code for these objects in question) at `layout.pos.row`, `layout.pos.col`
print(g1, vp = viewport(height = unit(0.2, "npc"), width = unit(0.05, "npc"),
layout.pos.row = 2, layout.pos.col = 9))
print(g2, vp = viewport(height = unit(0.2, "npc"), width = unit(0.05, "npc"),
layout.pos.row = 2, layout.pos.col = 19))
print(g3, vp = viewport(height = unit(0.2, "npc"), width = unit(0.05, "npc"),
layout.pos.row = 2, layout.pos.col = 29))
print(g4, vp = viewport(height = unit(0.2, "npc"), width = unit(0.05, "npc"),
layout.pos.row = 12, layout.pos.col = 9))
print(g5, vp = viewport(height = unit(0.2, "npc"), width = unit(0.05, "npc"),
layout.pos.row = 12, layout.pos.col = 19))
print(g6, vp = viewport(height = unit(0.2, "npc"), width = unit(0.05, "npc"),
layout.pos.row = 12, layout.pos.col = 29))

Sample Image

If you have simple base R plots then another route is to use the ggplotify to convert the base plot to ggplot and then use cowplot or patchwork for the placement. I could not get this working for my desired plots, which uses a more complex set of plotting functions (in base R) than those in the dummy example above.

grid arrange to place table and graph on one image

This is not an answer.

Your code is not reproducible. Wrapping your data in a read.table() function (and accepting default variable names), guessing that you are using base graphics, fixing typos in your code, and loading the gridExtra package (necessary for the grid.arrange function), I still cannot get your code to work. Using the ggplot2 package to draw the graph, I can get your code to work. The code is now reproducibe. See here for how to make a great reproducible example. And using my code, the result in my opinion looks pretty good. But it might not be what you intended. That's why the community asks you to generate a reproducible example. All the better then to see what you mean by "a lot of space between p2 and p1".

But taking your workaround from your comment above - there are unnecessary elements in the code. You do not need both grid.arrange and arrangeGrob. Also, because you have the elements arranged side-by-side, I don't think you need both widths and heights; widths alone is sufficient.

library(ggplot2)
library(gridExtra)

x = read.table(text = "
1/1/2010 10
1/2/2010 20
1/3/2010 15
1/4/2010 56
1/5/2010 46
1/6/2010 15
1/8/2010 15
1/9/2010 15
1/10/2010 20
1/11/2010 15
1/12/2010 15
1/13/2010 40
1/14/2010 15
1/15/2010 15
1/16/2010 70", sep = "", header = FALSE)

p1<-ggplot(x, aes(V2, V1)) + geom_point()
p2<-tableGrob(x)
grid.arrange(p2, p1, main="Total Data and Image", ncol = 2)

Your fix:

grid.arrange(p2, p1, main="Total Data and Image", ncol = 2, widths=c(1,2))

Edit
Baptiste's solution - see comments below:

  grid.arrange(p2, p1, main=textGrob("Total Data and Image", gp=gpar(cex=3)), ncol = 2,
widths=unit.c(grobWidth(p2), unit(1,"npc") - grobWidth(p2)))


Related Topics



Leave a reply



Submit