I am new to R
I want to create a layout using grid library in R as show below.
How can I do it?
My sample code:
library(grid)
library(gridBase)
grid.newpage()
ly = grid.layout(3, 3)
grid.show.layout(ly)
You can achieve this with grid.arrange() from the gridExtra-library.
They have a good vignette detailing the process here, but in essence you create a matrix detailing your layout, like this:
grid.arrange(
grobs = gl,
widths = c(2, 1, 1),
layout_matrix = rbind(c(1, 2, NA),
c(3, 3, 4))
)
This allows for great flexibility, but it can be a hassle to work out the exact matrix by hand.
Related
The results of the plot can be normally arranged in grids. I currently have an issue by plotting the results of the ctree function from the party package in a grid. This question is a duplicate of a question from 6 years and 8 months ago (Plot of BinaryTree (ctree, party) ignores plot option of par()). It was opted that gridExtra could provide a solution. However, till now no solution for this issue has been given. Consider the example below.
library(party)
library(gridExtra)
#Create random dataframe
dfA <- data.frame(x=c(rnorm(50, 5), rnorm(50, 2)),
y=c(rbinom(50, 1, .9), rbinom(50, 1, .1)))
#Duplicate dataframe
dfB <- dfA
#Plot in base R wit par (does not work)
par(mfrow = c(1, 2))
plot(party::ctree(y~x, data=dfA))
plot(party::ctree(y~x, data=dfB))
#Try to organize in a grid wit gridExtra (does not work)
treeA <- party::ctree(y~x, data=dfA)
treeB <- party::ctree(y~x, data=dfB)
grobA <- arrangeGrob(plot(treeA))
grobB <- arrangeGrob(plot(treeB))
grid.arrange(grobA, grobB, ncol=2)
Error in gList(list(wrapvp = list(x = 0.5, y = 0.5, width = 1, height = 1, :
only 'grobs' allowed in "gList"
The arrangeGrob(plot(treeA)) and arrangeGrob(plot(treeB)) also return an error stating Error in vapply(x$grobs, as.character, character(1)) : values must be length 1, but FUN(X[[1]]) result is length 0
Does someone known how plot the results of the ctree function in a grid?
Thank you in advance.
## grab the scene as a grid object
library(gridExtra)
library(gridGraphics)
library(grid)
list.to.pass <- list('plot(ctree(y~x, data=dfA))',
'plot(ctree(y~x, data=dfB))')
out<-list()
for (i in c(1,2)){
print(i)
formula(list.to.pass[[i]])
out[[i]] <- grid.grab()
print(out[[i]])
dev.off()
}
grid.arrange(out[[1]], out[[2]], nrow = 1,ncol=2)
You will get:
The plots in party and its successor package partykit are implemented in grid and hence the base graphics options from par() such as mfrow do not work. You can use grid.layout() to achieve similar results. Doing so in plain grid is a bit technical but the code should not be too hard to follow:
grid.newpage()
pushViewport(viewport(layout = grid.layout(1, 2)))
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 1))
plot(treeA, newpage = FALSE)
popViewport()
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2))
plot(treeB, newpage = FALSE)
popViewport()
The reason for the newpage = FALSE argument is that by default the plot is drawn on a new page, rather than adding to a potentially existing plot.
I am new to R and I am learning from the book Hands on Programming with R. I have a simple task: plot a histogram using qplot. The book and I have different graphs from the same command
library("ggplot2")
x <- c(1, 2, 2, 2, 3, 3)
qplot(x, binwidth = 1)
Unlike my histogram (image below), the one in the book has this type of interval [1, 2) and thus the histogram starts from 1 and not 0.5. Appreciate your help in telling me what's wrong here.
I don't think you're doing anything wrong. I'm getting the same plot as you are getting with the code from the book.
I added xlim and I'm getting a slightly better plot.
qplot(x, binwidth = 1, xlim = c(0, 4))
My best bet is either
The qplot function was updated at some point (unlikely that this has changed) so labels were changed.
The book tries to reduce confusion by only giving a segment of the code, while actually performing some relabeling behind-the-scene (and causing extra confusion). This could be done rather simply
qplot(c(1, 2, 2, 2, 3, 3), binwidth = 1, xlab = 'x') +
scale_x_continuous(breaks = c(1, 2, 3), labels = c('[1, 2)', '[2, 3)', '[3, Inf)'))
I'm trying to save a plot using 3 maps made by the tmap package, with the larger one at the top, and the other 2 at the bottom like the example above:
But using tmap_arrange() provided by the package for this kind of procedure, it gives me the followig:
data(World)
p1 <- tm_shape(World)+tm_polygons()
p2 <- tm_shape(World[World$continent=='South America',])+tm_polygons()
p3 <- tm_shape(World[World$name=='Brazil',])+tm_polygons()
tmap_arrange(p1,p2,p3,nrow=2)
I've tried to use many options, like export the maps as images and then import again to R to compose a full image using par() and/or split.screen(), but also doesn't work properly.
There is any way to work around this and get the wanted result?
Thanks in advance!
One hackish way would be to use the grid package functionality. Grab the output of each plot/map and store it as a gTree object and then try to arrange the new objects in a grid.
library(tmap)
library(cowplot) # for plot_grid() function - good to arrange multiple plots into a grid
library(grid)
library(gridGraphics)
data(World)
tm_shape(World) + tm_polygons()
g1 <- grid.grab()
tm_shape(World[World$continent == 'South America', ]) + tm_polygons()
g2 <- grid.grab()
tm_shape(World[World$name == 'Brazil', ]) + tm_polygons()
g3 <- grid.grab()
# Try to arrange the plots into a grid using cowplot::plot_grid().
# First bind the p2 and p3 as one plot;
# adjust distance between them by forcing a NULL plot in between.
p23 <- plot_grid(g2, NULL, g3, rel_widths = c(1, -0.7, 1), nrow = 1)
plot_grid(g1, p23, nrow = 2, scale = c(0.8, 1))
I could not figure it out how to make it respond to the align argument though :/ But maybe this puts you in some exploring direction or others can edit/improve this answer.
# Save the plot
ggsave(filename = "tmap-arrange-grid-1.png",
width = 10, height = 6, units = "cm", dpi = 150)
Note that, initially I thought that I could explore with adding a NULL object to tmap_arrange like tmap_arrange(p1, NULL, p2, p3, nrow = 2), but unfortunately, it does not accept it.
Another approach, inspired from this related question could be something along these lines:
library(grid)
grid.newpage()
pushViewport(viewport(layout = grid.layout(nrow = 2, ncol = 2)))
print(p1, vp = viewport(layout.pos.row = 1, layout.pos.col = 1:2))
print(p2, vp = viewport(layout.pos.row = 2, layout.pos.col = 1))
print(p3, vp = viewport(layout.pos.row = 2, layout.pos.col = 2))
Again, here, I didn't have the time to explore with aligning the plots perfectly, but others might improve this answer.
I have 3 figures of which I would like to plot in the same place in R. I would like to have 2 columns, which would make the 3rd figure plotted alone in the second row. Using par(mfrow=c(2,2)) functions in R, is there a way to have the bottom figure plotted in the centre of the plot, as opposed to underneath the top figure?
I don't think you can do this using par(mfrow = ...)
However, you can use layout().
Try this:
par(mai=rep(0.5, 4))
layout(matrix(c(1,2,3,3), ncol = 2, byrow = TRUE))
plot(1:10)
plot(1:20)
plot(1:30)
So you can see the idea is to create a matrix where each cell indicates which graph to plot. You can extend the logic as follows:
par(mai=rep(0.5, 4))
layout(matrix(c(1,1, 2,2, 0, 3,3, 0), ncol = 4, byrow = TRUE))
plot(1:10)
plot(1:20)
plot(1:30)
I am trying to put two Venn diagrams in one single graph, i.e. I am using par(mfrow=c(1,2)) at the very beginning. However, when I use the Venn() function in the Vennerable package:
VennCompare = Venn(SetNames = c("A", "B", "C"), Weight = c(0, 38, 1, 0, 1, 80, 0, 14))
pdf(file="Venn.pdf", width=12, height=6)
par(mfrow=c(1,2))
plot(VennCompare, doWeights=FALSE)
plot(VennCompare, doWeights=TRUE, show = list(SetLabels = TRUE, Faces = FALSE))
dev.off()
The resultant pdf file contains 2 pages, and each page has a single Venn diagram.
How can I put the two diagrams into a single page (i.e. side-by-side)?
As already discussed in comments, Vennerable uses grid graphics and fixes the grid parameters inside of the package functions. You should probably ask kindly from package maintainers if they could add this kind of functionality in their packages, but in a meantime I offer you a Sketchof a hack which allows you to do what you want:
The first command allows you to edit the function called makevp.eqsc which seems to contain the grid definitions:
trace("makevp.eqsc",edit=TRUE)
Original code looks like this:
function (xrange, yrange)
{
pushViewport(plotViewport(name = "Vennmar", c(1, 1, 1, 1)))
pushViewport(viewport(name = "Vennlay", layout = grid.layout(1,
1, widths = diff(xrange), heights = diff(yrange), respect = TRUE)))
pushViewport(viewport(name = "Vennvp", layout.pos.row = 1,
layout.pos.col = 1, xscale = xrange, yscale = yrange))
}
The most relevant parts are grid.layout, which tells you what kind of grid you want to draw. Also layout.pos.row and layout.pos.col are important, they tell in which position to draw. Change the code for example like this:
function (xrange, yrange)
{
pushViewport(plotViewport(name = "Vennmar", c(1, 1, 1, 1)))
pushViewport(viewport(name = "Vennlay", layout = grid.layout(2,
1, widths = diff(xrange), heights = diff(yrange), respect = TRUE)))
pushViewport(viewport(name = "Vennvp", layout.pos.row = number,
layout.pos.col = 1, xscale = xrange, yscale = yrange))
}
Now you will get two stacked graphs, like this:
number<-1 #change the argument inside of makevp.eqsc
plot(VennCompare, doWeights=FALSE)
number<-2
plot(VennCompare, doWeights=TRUE,
show = list(SetLabels = TRUE, Faces = FALSE),add=TRUE) #note add=TRUE
This doesn't look really nice, but by modifying makevp.eqsc you can probably archieve more nice results.
I couldn't install that package, but a trick that might help here is to use grid.grab to capture the drawing into a grob that can be placed elsewhere,
library(grid)
myplot <- function(){
pushViewport(viewport(x=0.5,width=1, just=0.5))
grid.rect(gp=gpar(fill=grey(runif(1, 0.2, 0.8))))
grid.points()
popViewport()
}
p1 <- grid.grabExpr(myplot())
p2 <- grid.grabExpr(myplot())
library(gridExtra)
grid.arrange(p1, p2, ncol=2)
Try this:
v <- Venn(n=2)
plot(v)
grid.text("Title", vp = viewport(x=0.5, y=.9, w=unit(1, "npc"), h=unit(1, "npc")))