Sara
Sara

Reputation: 59

Automating multiple plots/graphs with two Ys from one data set

I am trying to graph 34 individual plots against time with two Y variables. My dataset is structured: X Y1A Y2A Y1B Y2B . . . Y1n Y2n

I can get plot individually by simply asking ggplot to plot the columns I want. However, I have 34 plots to do in each of 5 datasets, so automating this would be useful. I am really stuck as to how to structure the language to do what I want it to do. (New user). I am not good at for loops or even know if this is exactly the right structure of code I want to use. I have looked at apply functions and those don't seem to do what I want, since I am not trying to manipulate my data, but just graph all of it at once.

I have not tried melt but I am again stuck at how to create two lines at a time. Should I name my columns something different/easier to automate.

I have searched for hours and haven't found anything that quite answered my question.


df <- matrix( c( 1,   0.011,    0.002,     0.007,      0.002,
              2,   0.011,      NA,   0.007, NA,
              3,   0.010,    0.002,     0.007,      0.002,
              4,   0.010,      NA,       0.007, NA, 
              5,   0.010,       NA,      0.006, NA, 
              6,   0.010,    0.002,    0.006,       0.002
              ), nrow = 6, ncol= 5, byrow= TRUE) 
colnames(df)<- c("time", "prefish1",  "obsfish1",  "prefish2",  "obsfish2")
biomass<-as.data.frame(df)
for (i in biomass[2]) {   
}
for (k in biomass[3]) {

}
}  ##this will call just columns 2 and 3 as a pair.##
ggplot(biomass, aes(x= time)) +
  geom_line(aes(y=i)) +
  geom_point(aes(y=k)) +
  ggtitle(i) + ylab("biomass t/km2") + 
  ##I would also like to title them using the header one of the column pairs## 
  theme_classic()

EDIT I just tried this:

pre<- biomass[+c(2,4)] 
obs<- biomass[+c(3,5)] 
for(i in 1:NCOL(pre)){
}
  for(k in 1:NCOL(obs)){
    plot(biomass$time, pre[,i], type= "l", xlab= "time", ylab ="biomass t/km2")
    par(new= TRUE)
    plot(biomass$time, obs[,k], type = "p", main = paste("Fit", names(obs)[k]), xlab= "time", ylab ="biomass t/km2")

  }

But something is breaking here, and I want both points and lines on same plot for each pair.

Expected results should be 34 individual plots. - or in this example, two individual plots.

Upvotes: 1

Views: 268

Answers (2)

Tung
Tung

Reputation: 28391

Another option: build a function for plotting. Then create two name vectors, loop them simultaneously, pass to the newly created function and save result in a list. After that use plot_grid to combine all plots together

library(tidyverse)

## plot function
my_bio_plot <- function(biomass, .var1, .var2) {

  p <- ggplot(biomass, aes(x = time)) +
    geom_line(aes(y = .data[[.var1]])) +
    geom_point(aes(y = .data[[.var2]])) +
    ggtitle(paste0(.var1, " (line) vs ", .var2, " (dot)")) + 
    ylab(expression("biomas"~(t/km^2))) +
    theme_classic()
  return(p)
}

## create two separate name vectors
var1_names <- colnames(biomass)[grepl("^pre", colnames(biomass))]
var2_names <- colnames(biomass)[grepl("^obs", colnames(biomass))]

## loop through two vectors simultaneously and save result in a list 
# ..1 = var1_names, ..2 = var2_names
my_plot <- pmap(list(var1_names, var2_names), ~ my_bio_plot(biomass, ..1, ..2))

## merge plots together
# https://cran.r-project.org/web/packages/cowplot/
# install.packages("cowplot", dependencies = TRUE)
library(cowplot)

plot_grid(plotlist = my_plot,
          ncol = 2,
          labels = "AUTO")

Created on 2019-05-21 by the reprex package (v0.3.0)

Upvotes: 1

Jon Spring
Jon Spring

Reputation: 66765

Could a faceting approach work, or do you want separate output files?

The most common way to do this in ggplot would be to put the separate runs into facets. To do this, we need to reshape the data before feeding it into ggplot: instead of having separate pairs of columns in the data for every graph, we can have one pair of columns, with another column (num below) specifying which graph each row relates to. Then we can use that num variable to map to facet. (We could use the same prep to accomplish the 2nd task, too...)

library(tidyr)   # Useful for reshaping the data
library(ggplot2)

biomass %>%
  # Gather data into long format
  gather(column, value, -time) %>%
  # Separate the number of graph from the type of column
  separate(column, c("var", "num"), sep = -1) %>%
  # Put the two types of column back into separate columns
  spread(var, value) %>%


  ggplot(aes(x= time, group = num)) +
  geom_line(aes(y = prefish)) +
  geom_point(aes(y= obsfish)) +
  facet_wrap(~num) +
  ylab("biomass t/km2") + 
  ##I would also like to title them using the header one of the column pairs## 
  theme_classic()

enter image description here

Upvotes: 1

Related Questions