3

I am trying to write a function that creates plots and ran into an error that I don't understand. Here is a simplified example.

Reproducible example:

library (ggplot2)
# Sample data
xdata = 0:20
ydata = 20:40
dat <- data.frame(xdata, ydata)

# This works
line_p <- ggplot(dat, aes(x = xdata, y = ydata, group = NULL, color = NULL)) + geom_line()
line_p

I expected the following to work, but get an aesthetics error, but in this case the x and y variables are the same length. The issues seems to be having a default value of NULL for group and color. I tried explicitly passing NULL as well with aes_group and aes_color as function variables but this also did not work.

# Using a function doesn't work:

# create function
line_function <- function(mydata     = dat,
                          xinput     = x,
                          yinput     = y,
                          aes_group  = NULL,
                          aes_color  = NULL,
                          ...) {

  lineplot <- ggplot(dat, aes(x = xinput, y = yinput, group = aes_group, color = aes_color)) + geom_line()
}


# test the function
line_test_p <- line_function(
  mydata = dat,
  xinput = xdata,
  yinput = ydata
)

line_test_p

Testing with explicit inputs

# test the function again with explicit NULL inputs

line_test2_p <- line_function(
  mydata    = dat,
  xinput    = xdata,
  yinput    = ydata,
  aes_group = NULL,
  aes_color = NULL
)

line_test2_p

Is it not possible to write a generic function where ggplot will interpret the NULL values as in the example that works without a function, or am I missing something else?

Thanks!

DaveM
  • 664
  • 6
  • 19

1 Answers1

3

In short, you should check out aes_string for creating aesthetic mappings programmatically. It allows you to create aesthetic mappings using the names of variables stored strings. That way, it's easy to pass column names as arguments to a function and create the corresponding plot.

The following version of your function works for me:

# create function
line_function <- function(mydata     = dat,
                          xinput     = "x", # note the defaults are
                          yinput     = "y", # strings here
                          aes_group  = NULL,
                          aes_color  = NULL,
                          ...) {

  ggplot(mydata, # this should be the argument, not the global variable dat
         # now we create the aes binding with aes_string
         aes_string(x = xinput,
                    y = yinput,
                    group = aes_group,
                    color = aes_color)) +
    geom_line()
}

And now you can use the function to create your examples:

# test the function
line_test_p <- line_function(
  mydata = dat,
  xinput = "xdata", # note the strings
  yinput = "ydata"
)

# test the function again with explicit NULL inputs
line_test2_p <- line_function(mydata    = dat,
                              xinput    = "xdata", # and strings here
                              yinput    = "ydata",
                              aes_group = NULL,
                              aes_color = NULL)

And things should work out for you. Again, do check out the documentation, because there are different ways you can accomplish this, and you may prefer different ways for different purposes or preferences.

Andrew Milligan
  • 571
  • 2
  • 9
  • Andrew, that's it, thanks. The simplest change after reading the documentation was to change the lineplot line to: **lineplot <- ggplot(mydata, aes_(x = xinput, y = yinput, group = aes_group, color = aes_color)) + geom_line()** I also should have used **mydata** as the variable in the function as you mentioned, not **dat** – DaveM Oct 08 '17 at 18:11