I am trying to create a complete set of plots using facet_wrap
from the ggplot2 package in R.
As a simplified example I used a subset of the dataset mpg included in ggplot2
library(plyr)
library(ggplot2)
library(gtable)
library(gridExtra)
myData = subset(mpg, manufacturer == "audi" | manufacturer == "chevrolet")
myData = droplevels(myData)
Here is my code to plot the data:
p = ggplot(myData, aes(x=hwy, y=cty, colour=model) )
p = p + facet_wrap( ~ manufacturer)#, scales="free") # sets panel division
p = p + geom_point(size = 3) # sets points aspect
p = p + geom_smooth(stat="identity")
print(p)
Now here comes the tricky part... I have another dataframe 'indivParam' with extra information that I would like to display as a table on the plot. Let's say this silly one:
indivParam = ddply(myData, .(manufacturer , model), summarize,
var1 = unique(class),
var2 = round(mean(displ)),
var3 = round(mean(cyl)))
What I am trying to do is to add a sub-table on each panel, with info extracted from indivParam. For example add the following table on the first panel of the plot:
tg = tableGrob(subset(indivParam, manufacturer == "audi"),
show.rownames=FALSE, gp=gpar(fontsize=8, lwd=2),
xmin=15, xmax=30, ymin=10, ymax=20)
grid.newpage()
grid.draw(tg)
I tried several options...
using annotate()
but this argument does not pass dataframes...
using annotation_custom()
as suggested in this thread : Adding table within the plotting region of a ggplot in r
p1 = p + annotation_custom(tableGrob(indivParam,
show.rownames=FALSE,
gp=gpar(fontsize=8, lwd=2)),
xmin=15, xmax=30, ymin=10, ymax=20)
print(p1)
This does not work either because it displays the entire table on each panel, instead of a sub-table with data related to each panel ()
Finally, after reading the examples on the 'tableGrob' doc page, I tried to create one grid with all the sub-table grobs and simply superimpose it on the plot:
lg <- lapply(as.character(unique(indivParam$manufacturer)),
function(x) tableGrob( as.data.frame(dlply(indivParam, .(manufacturer))[x]),
name="test",show.rownames=FALSE,
gp=gpar(fontsize=8, lwd=2)))
grid.newpage()
print(p)
grid.draw(do.call(arrangeGrob, lg))
But then, the organization does not match the one used by facet.., and I suspect that even if I could put the two tables next to each other, they would be centered and would hide the plots...
Is there any way I could improve this last attempt by choosing the position of the sub-tables? Or is there an even better way to solve this issue? An obvious one would be to use a geom_table()
but I don't think this geom exist (yet)...
Any help/hint will be much appreciated!! :-)
To facet continuous variables, you must first discretise them. ggplot2 provides three helper functions to do so: Divide the data into bins of width width: cut_width (x, width) . Divide the data into n bins each containing (approximately) the same number of points: cut_number (x, n = 10).
In order to draw our data with the ggplot2 package, we also need to install and load ggplot2: Now, we can plot our data in a facet plot with default spacing as shown below:
The following code illustrates how to add more white space between the margins of each panel of our ggplot2 facet plot. For this, we can use the theme function and the panel.spacing argument as shown below. Note that we can use different units and values within the unit function.
The function facet () [in ggpubr] allows to draw multi-panel plots of a data set grouped by one or two variables. Additionally, we’ll show how to easily modify panel labels. Required R packages: ggpubr to easily create ggplot2-based publication ready plots. Or, install the latest developmental version from GitHub as follow:
Here is a solution with the amazing package ggpmisc
:
library(ggpmisc)
library(dplyr)
library(tibble)
myData <- filter(mpg, manufacturer == "audi" | manufacturer == "chevrolet")
gg <- ggplot(myData, aes(x=hwy, y=cty, colour=model)) +
facet_wrap(~ manufacturer) +
geom_point(size = 3) +
geom_smooth(stat="identity")
tb <- myData %>%
group_by(manufacturer, model) %>%
summarize(var1 = round(mean(displ)), var2 = round(mean(cyl))) %>%
ungroup()
tbs <- lapply(split(tb, tb$manufacturer), "[", -1)
df <- tibble(x = rep(-Inf, length(tbs)),
y = rep(Inf, length(tbs)),
manufacturer = levels(as.factor(tb$manufacturer)),
tbl = tbs)
gg + geom_table(data = df, aes(x = x, y = y, label = tbl),
hjust = 0, vjust = 1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With