0

I am trying to build multiple graphs with ggplot in batch. The graphs all come from the same dataframe, the only thing I need to change is the metric (y axis) that I observe.

What I am doing now is far from efficient as I am copy-pasting the ggplot setup for each graph and just changing the metric where it needs to be modified.

I know there is a way, to dynamically create these graphs by just listing all the metrics that need to change dynamically so that I only need to use ggplot once in a loop.

I think in the past I managed to do it using eval() , get() and maybe assign() but I can't remember how I had done it.

Ideally, in the end I would have the different graphs created with each a unique name based on the metric: Forecast_Monthly_Visits_FR_Graph, Forecast_Monthly_Sales_FR_Graph etc. Below a reproducible example. Thanks a lot.

library(ggplot2)

Date <- as.Date(c('2022-01-01','2022-01-02','2022-01-03','2022-01-01','2022-01-02','2022-01-03'))
Type <- c("Actual", "Actual", "Actual", "Forecast", "Forecast", "Forecast")
Visits <- c(67398,63398,61398,53422,72726,92822)
Sales <- c(17398,23398,41398,12422,33726,53822)
Actual_Forecast_Monthly_France <- data.frame(Date , Type , Visits, Sales)

Forecast_Monthly_Visits_FR_Graph <-
  ggplot(data=Actual_Forecast_Monthly_France, aes(x=Date, y=Visits, group=Type,  linetype = factor(Type) , show.legend = FALSE)) +
  geom_line(aes(color=Type)) +
  geom_point(size = 0.5) +
  geom_text(aes(label=round(Visits)), size = 3) +
  theme(axis.text.x = element_text(angle = 90)) +
  labs(title = "Visits") +
  theme(plot.title = element_text(hjust = 0.5)) +
  scale_color_manual(values= c("#03a623", "#030063", "#ffaad7", "#b6b6b6"))

Forecast_Monthly_Visits_FR_Graph

 Forecast_Monthly_Sales_FR_Graph <-
  ggplot(data=Actual_Forecast_Monthly_France, aes(x=Date, y=Sales, group=Type,  linetype = factor(Type) , show.legend = FALSE)) +
  geom_line(aes(color=Type)) +
  geom_point(size = 0.5) +
  geom_text(aes(label=round(Sales)), size = 3) +
  theme(axis.text.x = element_text(angle = 90)) +
  labs(title = "Sales") +
  theme(plot.title = element_text(hjust = 0.5)) +
  scale_color_manual(values= c("#03a623", "#030063", "#ffaad7", "#b6b6b6"))

Forecast_Monthly_Sales_FR_Graph 

2 Answers 2

5

Similar to the approach by @Peter with the exception that I pass the column names as strings which IMHO makes it a bit easier to loop over the columns using e.g. lapply. Note, as I pass the column names as strings I use the .data pronoun:

library(ggplot2)

plot_fun <- function(x) {
  ggplot(data = Actual_Forecast_Monthly_France, aes(x = Date, y = .data[[x]], group = Type, linetype = factor(Type), show.legend = FALSE)) +
    geom_line(aes(color = Type)) +
    geom_point(size = 0.5) +
    geom_text(aes(label = round(Visits)), size = 3) +
    theme(axis.text.x = element_text(angle = 90)) +
    labs(title = x) +
    theme(plot.title = element_text(hjust = 0.5)) +
    scale_color_manual(values = c("#03a623", "#030063", "#ffaad7", "#b6b6b6"))
}

cols <- names(Actual_Forecast_Monthly_France)[!names(Actual_Forecast_Monthly_France) %in% c("Date", "Type")]
names(cols) <- cols

lapply(cols, plot_fun)
#> $Visits

#> 
#> $Sales

Sign up to request clarification or add additional context in comments.

Comments

2

You can create a function which includes the y variable you want to plot. Then it becomes relatively simple to create a for loop to cycle through multiple y variable options or you could use a function from purrr. Now included the loop, and I've had to go down the route of quoted variables names as @stefan explained.

library(ggplot2)
library(purrr)

gg_fun <- function(y_var){
  Forecast_Monthly_Visits_FR_Graph <-
    ggplot(data=Actual_Forecast_Monthly_France, aes(x=Date, y=!!sym(y_var), group=Type,  linetype = factor(Type) , show.legend = FALSE)) +
    geom_line(aes(color=Type)) +
    geom_point(size = 0.5) +
    geom_text(aes(label=round(Visits)), size = 3) +
    theme(axis.text.x = element_text(angle = 90)) +
    labs(title = y_var) +
    theme(plot.title = element_text(hjust = 0.5)) +
    scale_color_manual(values= c("#03a623", "#030063", "#ffaad7", "#b6b6b6"))
  
  return(Forecast_Monthly_Visits_FR_Graph)
  
}

gg <- map(c("Visits", "Sales"), gg_fun)


gg[[1]]

gg[[2]]

Created on 2022-09-13 with reprex v2.0.2

data

Date <- as.Date(c('2022-01-01','2022-01-02','2022-01-03','2022-01-01','2022-01-02','2022-01-03'))
Type <- c("Actual", "Actual", "Actual", "Forecast", "Forecast", "Forecast")
Visits <- c(67398,63398,61398,53422,72726,92822)
Sales <- c(17398,23398,41398,12422,33726,53822)
Actual_Forecast_Monthly_France <- data.frame(Date , Type , Visits, Sales)

Created on 2022-09-13 with reprex v2.0.2

2 Comments

You have to fix the title. One reason why I prefer to pass the column names as strings. (;
Of course! will modify this - updated now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.