Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding sub-tables on each panel of a facet ggplot in r

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...

  1. using annotate() but this argument does not pass dataframes...

  2. 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 ()

  3. 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!! :-)

like image 735
Aurelie Calabrese Avatar asked Aug 28 '14 17:08

Aurelie Calabrese


People also ask

How do you facet in ggplot2?

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).

How to draw data with the ggplot2 package?

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:

How to add more white space between the margins in ggplot2?

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.

How to draw multi-panel plots of a data set using ggpubr?

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:


1 Answers

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) 

enter image description here

like image 125
Stéphane Laurent Avatar answered Sep 23 '22 01:09

Stéphane Laurent