I've been trying to edit some plots created by ggplot2 using the functions provided by the packages grid and gridExtra. I realize that ggplot2 alone can make some really nice multifaceted plots. However, in some instances I like to create individual plots and then combine then together later on. While trying to do just that, I came across some unexpected behavior using cbind() with grid.draw() or grid.arrange() when using a ggplot2 graph that had been edited. Below is the code for an MWE:
#Load libraries
library(ggplot2); library(gridExtra)
#Load data
data(mtcars)
#Ggplot
p = qplot(wt,mpg,data=mtcars,color=cyl)
grob = ggplotGrob(p)
#Bold xlabel
grobEdited = editGrob(grid.force(grob),gPath("xlab","GRID.text"),grep=TRUE,gp=gpar(fontface="bold"))
#Visualize
grid.newpage()
grid.draw(grobEdited)
It worked as expected. Now to illustrate the issue, lets cbind() two of the same edited ggplot2 graphs:
#Cbind example with edited graphs
grid.newpage()
grid.draw(cbind(grobEdited,grobEdited))
It didn't work as expected! Now test cbind() on the unedited graphs:
#Cbind example with grob
grid.newpage()
grid.draw(cbind(grob,grob))
Works as expected. I'm new to gridded figures, so is there something I'm doing wrong?
I'm posting an answer following the comment from #user20650. The easiest workaround is to cbind() the ggplot2 graphs before editing them using the editing functions provided by grid or gridExtra:
#Edit after cbind()
grobEdited = editGrob(grid.force(cbind(grob,grob)),gPath("xlab","GRID.text"),global=TRUE,grep=TRUE,gp=gpar(fontface="bold"))
#Visualize
grid.newpage()
grid.draw(grobEdited)
Related
I am ploting a multiple histogram for 5 variables, and I have the same title repeated along all of them. I didn´t find a way to personalize it for each histogram. Is there a way to do it? I am using the psych R package.
Maybe another package to recommend?
The code line:
multi.hist(AutosCompleteNorm[,11:15],main="bah")
And "bah" is repeated 5 times. I tried c("a","b",..."e") as an argument but it didn´t work.
Package documentation:
https://www.rdocumentation.org/packages/psych/versions/1.8.3.3/topics/multi.hist
Thanks!
The current psych package doesn't seem to support this, which is strange because it would have been a natural feature for such a plot.
For customizability, I recommend you to take a look at ggplot and then layout in the format you wish using gridExtra.
Here's the code to create the few histogram in ggplot:
library(ggplot2)
p1 <- ggplot(vids, aes(x=log(likes)))+geom_histogram()+labs(title="title1")
p2 <- ggplot(vids, aes(x=log(dislikes)))+geom_histogram()+labs(title="title2")
p3 <- ggplot(vids,
aes(x=log(comment_count)))+geom_histogram()+labs(title="title3")
And then laying them up in a 2 row layout (nrow=2):
library(gridExtra)
grid.arrange(p1, p2, p3, nrow = 2)
Changing the layout to nrow=1:
Following these comments, I just updated psych so that multi.hist is more useful.
You can now specify the margins for the plots, and it will, by default label each plot with the variable name.
I have not pushed the development version of psych (1.8.9) to CRAN yet, but it is available on my repository at
install.packages("psych",repos="https://personality-project.org/r",type="source")
I am trying to plot a table with the values from a dataframe. I am not sure of what approach to take using ggplot2.
I am also trying one approach using gridextra::grid.table() and tableGrob() functions and both are working similarly.
For example: I plot iris as a table using following code
library(gridExtra)
library(grid)
d <- head(iris, 3)
g <- tableGrob(d)
grid.draw(g)
When I plot this data using grid.draw, why I am getting row numbers 1 to 3 along with the table and how can I work on removing these numbers and change font type and background colors. Please guide!
Also guide me to the approach using ggplot2
Your help will be appreciated!
I have two ggplot2 plots and I want to draw a series (10-100) slightly different curves between them. That is, I will have a two-panel layout and want to draw connecting lines from the left plot to the right plot. So far I have tried doing this by converting things to grob's and using the gtable package to add curves.
To illustrate, I have something like:
library(ggplot2)
library(gtable)
library(grid)
library(gridExtra)
p1 = ggplot(data.frame(x=1:10,y=1:10),aes(x=x,y=y))+geom_point()
p2 = ggplot(data.frame(x=1:10,y=1:10),aes(x=x,y=y))+geom_point()
g1 = ggplotGrob(p1)
g2 = ggplotGrob(p2)
gt = gtable:::cbind.gtable(g1,g2,size='first')
gt$heights = unit.pmax(g1$heights,g2$heights)
for(i in 1:10) {
gt = gtable_add_grob(gt,curveGrob(0,0.5,1,0.5,ncp=5,square=FALSE,curvature=i/10),l=5,r=8,b=3,t=3)
}
grid.newpage()
grid.draw(gt)
producing a plot like this:
which is almost right, except only the last of the curveGrob objects is shown. I've tried playing around with the z-index for the added grobs and the last one plotted always overwrites the others. I want my plot to look the same, except it should show all 10 curves between the two plot areas, instead of just the one that is showing with my existing code.
So how can I either modify my existing code to show all 10 curves or achieve the same effect by using a different method? I am stuck using ggplot2 for the main plots, as they are considerably more complex than the toy example shown.
gtable wants unique names for grobs that are in the same position
gt = gtable_add_grob(gt,curveGrob(0,0.5,1,0.5,ncp=5,square=FALSE,curvature=i/10),
l=5,r=8,b=3,t=3, name=paste(i))
I'm trying to inset a plot using ggplot2 and annotation_custom (the plot is actually a map that I'm using to replace the legend). However, I'm also using facet_wrap to generate multiple panels, but when used with annotation_custom, this reproduces the plot in each facet. Is there an easy way to insert the plot only once, preferably outside the plotting area?
Here is a brief example:
#Generate fake data
set.seed(9)
df=data.frame(x=rnorm(100),y=rnorm(100),facets=rep(letters[1:2]),
colors=rep(c("red","blue"),each=50))
#Create base plot
p=ggplot(df,aes(x,y,col=colors))+geom_point()+facet_wrap(~facets)
#Create plot to replace legend
legend.plot=ggplotGrob(
ggplot(data=data.frame(colors=c("red","blue"),x=c(1,1),y=c(1,2)),
aes(x,y,shape=colors,col=colors))+geom_point(size=16)+
theme(legend.position="none") )
#Insert plot using annotation_custom
p+annotation_custom(legend.plot)+theme(legend.position="none")
#this puts plot on each facet!
This produces the following plot:
When I would like something more along the lines of:
Any help is appreciated. Thanks!
In the help of annotation_custom() it is said that annotations "are the same in every panel", so it is expected result to have your legend.plot in each facet (panel).
One solution is to add theme(legend.position="none") to your base plot and then use grid.arrange() (library gridExtra) to plot both plots.
library(gridExtra)
p=ggplot(df,aes(x,y,col=colors))+geom_point()+facet_wrap(~facets)+
theme(legend.position="none")
grid.arrange(p,legend.plot,ncol=2,widths=c(3/4,1/4))
How do plot multiple lattice plots onto a single lattice plot where the plots are generated using an lapply function?
The following is a demonstration of what I have tried so far using the built in mtcars dataset.
require(lattice)
response <- c("cyl","disp","hp","drat")
par(mfrow=c(2,2))
lapply(response, function(variable) {
print(xyplot(mtcars$mpg ~ mtcars[variable]))
})
This produces the plots desired. However it seems to be ignoring the par(mfrow=c(2,2)) instruction and plotting each plot separately.
If you really don't want to use the built-in facetting or viewport options of lattice, you can replicate the behavior of par(mfrow) with the following,
require(lattice)
response <- c("cyl","disp","hp","drat")
# save all plots in a list
pl <- lapply(response, function(variable) {
xyplot(mtcars$mpg ~ mtcars[variable])
})
library(gridExtra)
# arrange them in a 2x2 grid
do.call(grid.arrange, c(pl, nrow=2))
Your example is not how lattice is intended to be used (grid would be more appropriate).
Here is a lattice solution:
xyplot(mpg ~ cyl+disp+hp+drat,
data=mtcars,
groups=cyl+disp+hp+drat,
scales=list(relation="free"),
col="blue"
)
The multiplot function on this page is something I have used many times to get multiple plot objects on one page.