1

I have two custom functions that produce a bar or jitter graph. If an object exists, I would like it to produce the bar graph. If an object doesn't exist, I would like the jitter graph to be produced. I think the problem is making the code inside the if loop within a function dynamic so it can be altered to any dataset.

This is what I have so far, I think this will be an easy fix and I may just be missing formatting/syntax etc... (be kind I am new to writing functions in r).

data <- iris

#graph 1 function:
make_bar_graph <- function(data, x, y, xlab = NULL, ylab = NULL, 
                             linewidth = 0.5, colour = NULL, fill = NULL, 
                             stat.colour = "black", 
                             bar.position = "dodge", bar.width = 0.8, bar.colour = "black", 
                             point.position = position_jitterdodge(0.7), point.size = 2,
                             errorbar.position = position_dodge(0.8), errorbar.width = 0.3, errorbar.colour = "black",
                             ...) {
  ggplot(data = data, aes(x = {{x}}, y = {{y}}, fill = {{fill}}, colour = {{colour}})) +
    geom_bar(stat="summary", fun = "mean", position = bar.position, width = bar.width, colour = bar.colour, show.legend = FALSE, inherit.aes=TRUE, ...) +
    geom_hline(yintercept=0) +
    labs(x=xlab, y=ylab) +
    geom_point(position = point.position, size = point.size, show.legend = FALSE, ...) +
    scale_fill_manual(values = c("gray95", "gray85", "gray75", "gray65", "gray55", "gray45")) +
    scale_colour_manual(values=c("#FF5695", "#8E8DFF", "#8CB5FF", "#79DBFF", "#42EFD7", "#79EBAC")) +
    theme(axis.title.x = element_blank())
   
}


#graph 1 example:
make_bar_graph(data, Species, Petal.Width, fill = Species, colour = Species)


#graph2 function
make_jitter_graph <- function(data, x, y, xlab = NULL, ylab = NULL, linewidth = 0.5, size.jitter = 2, colour = NULL, fill = NULL, stat.colour = "black", ...) {
  ggplot(data = data, aes(x = {{x}}, y = {{y}}, fill = {{fill}}, colour = {{colour}})) +
    stat_summary(fun = median, show.legend = FALSE, geom="crossbar", linewidth = linewidth, colour = stat.colour, ...) +
    geom_jitter(show.legend = FALSE, width = 0.25, size = size.jitter, ...) +
    labs(x=xlab, y=ylab)
}

#graph 2 example:
make_jitter_graph(data = data, x = Species, y = Petal.Width, colour = Species, fill = Species)



#How can I make either of these two graphs produced in a loop:
make_graphs <- function(data, x, y, xlab = NULL, ylab = NULL, 
                             linewidth = 0.5, colour = NULL, fill = NULL, 
                             stat.colour = "black", 
                             bar.position = "dodge", bar.width = 0.8, bar.colour = "black", 
                             point.position = position_jitterdodge(0.7), point.size = 2, 
                             errorbar.position = position_dodge(0.8), errorbar.width = 0.3, errorbar.colour = "black", size.jitter = 2,
                             ...){
  if(exists("OBJECT")){
    require(ggpubr)
    make_bar_graph(data = data, x=x, y=y, linewidth = linewidth, colour = colour, fill = fill,
                       stat.colour = stat.colour, bar.position=bar.position,  bar.width=bar.width, bar.colour=bar.colour,
                       point.position=point.position, point.size=point.size, errorbar.position = errorbar.position, errorbar.width = errorbar.width, errorbar.colour = errorbar.colour, ...)
  }else{
    make_jitter_graph(data = data, x=x, y=y, linewidth = linewidth, colour = colour, fill = fill, stat.colour = stat.colour, size.jitter=size.jitter, ...)
  }
}

# Run when OBJECT doesn't exist:
make_graphs(data = data, x = Species, y = Petal.Width, colour = Species, fill = Species)

#Get error: Error in stat_summary(fun = median, show.legend = FALSE, geom = "crossbar", : ℹ Error occurred in the 1st layer. Caused by error in `FUN()`: ! object 'Species' not found

# Run when OBJECT exists
OBJECT <- 4
make_graphs(data = data, x = Species, y = Petal.Width, colour = Species, fill = Species)

#Get the error: Error in geom_bar(stat = "summary", fun = "mean", position = bar.position, : ℹ Error occurred in the 1st layer. Caused by error in `FUN()`: ! object 'Species' not found

Thank you!

1 Answer 1

1

EDIT - two ways to do this:

1) Putting calls to ggplot2 inside make_graphs()

I think there's probably a way to make the whole process more concise, but could you just eliminate the first two functions entirely and put the ggplot calls inside your make_graphs function? Like this

make_graphs <- function(data, x, y, xlab = NULL, ylab = NULL, 
                        linewidth = 0.5, colour = NULL, fill = NULL, 
                        stat.colour = "black", 
                        bar.position = "dodge", bar.width = 0.8, bar.colour = "black", 
                        point.position = position_jitterdodge(0.7), point.size = 2, 
                        errorbar.position = position_dodge(0.8), errorbar.width = 0.3, errorbar.colour = "black", size.jitter = 2,
                        ...){
  if(exists("OBJECT")){
    require(ggpubr)
    ggplot(data = data, aes(x = {{x}}, y = {{y}}, fill = {{fill}}, 
                            colour = {{colour}})) +
      geom_bar(stat="summary", fun = "mean", position = bar.position, 
               width = bar.width, colour = bar.colour, show.legend = FALSE, 
               inherit.aes=TRUE, ...) +
      geom_hline(yintercept=0) +
      labs(x=xlab, y=ylab) +
      geom_point(position = point.position, size = point.size, 
                 show.legend = FALSE, ...) +
      scale_fill_manual(values = c("gray95", "gray85", "gray75", "gray65", 
                                   "gray55", "gray45")) +
      scale_colour_manual(values=c("#FF5695", "#8E8DFF", "#8CB5FF", "#79DBFF", 
                                   "#42EFD7", "#79EBAC")) +
      theme(axis.title.x = element_blank())  }else{
    ggplot(data = data, aes(x = {{x}}, y = {{y}}, fill = {{fill}}, 
                            colour = {{colour}})) +
      stat_summary(fun = median, show.legend = FALSE, geom="crossbar", 
                   linewidth = linewidth, colour = stat.colour, ...) +
      geom_jitter(show.legend = FALSE, width = 0.25, size = size.jitter, ...) +
      labs(x=xlab, y=ylab)  }
}

Then when the object doesn't exist you get this:

rm(OBJECT)
make_graphs(data = data, x = Species, y = Petal.Width, 
            colour = Species, fill = Species)

enter image description here

And when it does exist you get this:

OBJECT <- 4
make_graphs(data = data, x = Species, y = Petal.Width, 
            colour = Species, fill = Species)

enter image description here

2) Using aes_string()

Here, you'd change the way you set up the ggplot functions, so they get their aes() passed as aes_string() instead, then put actual strings in the make_graphs() call. The graph functions get defined like this now:

make_bar_graph <- function(data, x, y, xlab = NULL, ylab = NULL, 
                           linewidth = 0.5, colour = NULL, fill = NULL, 
                           stat.colour = "black", 
                           bar.position = "dodge", bar.width = 0.8, bar.colour = "black", 
                           point.position = position_jitterdodge(0.7), point.size = 2,
                           errorbar.position = position_dodge(0.8), errorbar.width = 0.3, errorbar.colour = "black",
                           ...) {
  ggplot(data = data, aes_string(x = x, y = y, fill = fill, colour = colour)) +
    geom_bar(stat="summary", fun = "mean", position = bar.position, width = bar.width, colour = bar.colour, show.legend = FALSE, inherit.aes=TRUE, ...) +
    geom_hline(yintercept=0) +
    labs(x=xlab, y=ylab) +
    geom_point(position = point.position, size = point.size, show.legend = FALSE, ...) +
    scale_fill_manual(values = c("gray95", "gray85", "gray75", "gray65", "gray55", "gray45")) +
    scale_colour_manual(values=c("#FF5695", "#8E8DFF", "#8CB5FF", "#79DBFF", "#42EFD7", "#79EBAC")) +
    theme(axis.title.x = element_blank())
  
}

make_jitter_graph <- function(data, x, y, xlab = NULL, ylab = NULL, linewidth = 0.5, 
                              size.jitter = 2, colour = NULL, fill = NULL, 
                              stat.colour = "black", ...) {
  ggplot(data = data, aes_string(x = x, y = y, fill = fill, colour = colour)) +
    stat_summary(fun = median, show.legend = FALSE, geom="crossbar", linewidth = linewidth, colour = stat.colour, ...) +
    geom_jitter(show.legend = FALSE, width = 0.25, size = size.jitter, ...) +
    labs(x=xlab, y=ylab)
}

The make_graphs() stay like you had it, then you can just call it like this:

make_graphs(data = data, x = "Species", y = "Petal.Width", 
            colour = "Species", fill = "Species")
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks so much, always helpful to get another perspective. Works great :)
If anyone else has a way to make the nested function dynamic, like in the original question, I would love to see that too out of curiosity
Your other way to go would be with aes_string(). I'll edit the answer

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.