1

I have a data set where I created ggplots for each ind where I end up with four different graphs. I had put these graphs into a list, and then used plot_grid from cowplot to get a single output that displays all four graphs at once. I'm not quite sure how to create a generic example here.The four graphs have different scales, but I would like my end product to have the same scales for each graph from the plot_grid output. How would I do this?

Here is a sample data set:

library(ggplot2)
data(iris)
rsq <- lapply(1:length(unique(iris$Species)), function(i) {
  cor(iris[iris$Species == unique(iris$Species)[i], "Sepal.Length"], iris[iris$Species == unique(iris$Species)[i], "Petal.Length"])^2
})

p.list <- lapply(1:length(unique(iris$Species)), function(i) {
  ggplot(iris[iris$Species == unique(iris$Species)[i], ], aes(x = Sepal.Length, y = Petal.Length)) +
    geom_point() + theme_bw()+
    geom_text(aes(x=min(Sepal.Length),y=max(Petal.Length),label=paste0("R= ",round(rsq[[i]],2))))
})

cowplot::plot_grid(plotlist = p.list[1:3], nrow = 1, ncol = 3, 
                   labels = "AUTO")

John Huang
  • 845
  • 4
  • 15
  • 2
    To help us to help you could you make your question reproducible by sharing the code you tried and the desired output? Also, why not simply facet by `ind` which will automatically give you the same scale. – stefan Jun 20 '21 at 20:17
  • 1
    I have edited the post using the `iris` data set as an example. I don't use facet on the data because the graphs are constructed from multiple different data sets, and I essentially paste them all together using `plot_grid` which doesn't plot them with the same x and y scales. – John Huang Jun 21 '21 at 18:02

1 Answers1

1

There are at least two options to achieve your desired result.

  1. If you want to stick with plot.grid you could achieve your desired result by setting the same limits for the x and the y scale in each of your plots. To this end compute the overall minimum and maximum in your data:
library(ggplot2)

rsq <- lapply(1:length(unique(iris$Species)), function(i) {
  cor(iris[iris$Species == unique(iris$Species)[i], "Sepal.Length"], iris[iris$Species == unique(iris$Species)[i], "Petal.Length"])^2
})

d_list <- split(iris, iris$Species)

xmin <- min(unlist(lapply(d_list, function(x) min(x["Sepal.Length"]))))
xmax <- max(unlist(lapply(d_list, function(x) max(x["Sepal.Length"]))))
ymin <- min(unlist(lapply(d_list, function(x) min(x["Petal.Length"]))))
ymax <- max(unlist(lapply(d_list, function(x) max(x["Petal.Length"]))))

p.list <- lapply(1:length(unique(iris$Species)), function(i) {
  ggplot(iris[iris$Species == unique(iris$Species)[i], ], aes(x = Sepal.Length, y = Petal.Length)) +
    geom_point() +
    scale_x_continuous(limits = c(xmin, xmax)) +
    scale_y_continuous(limits = c(ymin, ymax)) +
    theme_bw() +
    geom_text(aes(x = min(Sepal.Length), y = max(Petal.Length), label = paste0("R= ", round(rsq[[i]], 2))))
})

cowplot::plot_grid(
  plotlist = p.list[1:3], nrow = 1, ncol = 3,
  labels = "AUTO"
) 

enter image description here

  1. As a second approach you could make use of faceting as I mentioned in my comment. To this end bind your datasets into one and add an id variable. Additionally put the r-square values in a data frame too. Doing so allows you to make your plot using facetting:
library(ggplot2)
library(dplyr)

d_list <- split(iris, iris$Species)

rsq_list <- lapply(d_list, function(x) {
  data.frame(
    rsq = cor(x["Sepal.Length"], x["Petal.Length"])[1, 1]^2,
    Sepal.Length = min(x["Sepal.Length"]),
    Petal.Length = max(x["Petal.Length"])
  )
})

d_bind <- dplyr::bind_rows(d_list)
rsq_bind <- dplyr::bind_rows(rsq_list, .id = "Species")

ggplot(d_bind, aes(x = Sepal.Length, y = Petal.Length)) +
  geom_point() +
  theme_bw() +
  geom_text(data = rsq_bind, aes(label = paste0("R= ", round(rsq, 2)))) +
  facet_wrap(~Species)

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51
  • Is there a way to select a few levels at a time in `facet_wrap`? In my data set, I have 3000+ levels for the `ID`. This would no doubt break the code if I ran it on my computer. – John Huang Jun 22 '21 at 15:36
  • 1
    Hi John. Okay. I See. You data is actually more demanding as the datasets I have to deal with. Maybe `ggforce::facet_wrap_paginate` is helpful, as it allows to split a facetted plot over multiple pages. – stefan Jun 23 '21 at 06:48