writing R function with ggplot

I have to plot multiple datasets in the same format, and after copy-pasting the code several times, I decided to write a function. I understand simple function in R, and managed to write the following:

testplot <- function(data, mapping){
output <- ggplot(data) +
  geom_bar(mapping,
           stat="identity", 
             position='stack')
}
p <- testplot(df, aes(x=xvar, y=yvar, fill=type))

this works fine, however, my plot is more complicated and requires the "data" argument to go separately into each component:

output <- ggplot() +
  geom_bar(df1, mapping,
           stat="identity", 
             position='stack')+
geom_errorbar(df1, ...)+
geom+bar(df2, mapping,
...+
geom_errorbar(df2, ...)

but when I write the function and try to run it as

output <- ggplot() +
  geom_bar(data, mapping,
           stat="identity", 
             position='stack')
}
p <- testplot(df, aes(x=xvar, y=yvar, fill=type))

it gives me an error:

Error: `data` must be a data frame, or other object coercible by `fortify()`, not an S3 object with class uneval Did you accidentally pass `aes()` to the `data` argument?

Is there a way around it?

EDIT: when I try to include 2 dataframes like this:

testplot <- function(data, data2, mapping){
output <- ggplot() +
 geom_bar(data=data, mapping=mapping,
           stat="identity", 
             position='stack',
           width = barwidth)+
geom_bar(data2=data2, mapping=mapping,
           stat="identity", 
             position='stack',
           width = barwidth)
}



p <- testplot(data=df, data2=df2, mapping=aes(x=norms_number, y=coeff.BLDRT, fill=type))

it says "Ignoring unknown parameters: data2"

Most of the first arguments to the ggplot2 layer functions are reserved for the mapping argument, which is from aes. So in your function definition you have a dataframe "data" being implicitly assigned to the mapping variable. To get around this, explicitly assign data = data in your function definitions.

for example

output <- ggplot() +
 geom_bar(data = data, mapping = mapping,
          stat="identity", 
            position='stack')
}

EDIT:

There are many ways to do this and it really depends on how complex you want your function to be. If you are gonna stick to a global aesthetic mapping, then you can leave the mapping in the main ggplot call and assign data = NULL, then specify which data frame will be associated with which layer. Consider the following reproducible example

library(ggplot2)
data1 <- data.frame(v1=rnorm(10, 50, 20), v2=rnorm(10,30,5))
data2 <- data.frame(v1=rnorm(10, 100, 20), v2=rnorm(10,50,10))
plot_custom_ggplot <- function(df1, df2, mapping) {
    ggplot(data = NULL, mapping = mapping) +
      geom_point(data = df1, color = "blue") +
      geom_line(data = df2, color = "red")
}

plot_custom_ggplot(data1,data2, aes(x = v1,y = v2))

In this example, the mapping variable for each of the geom_* layer functions are left blank and instead the mapping is inherited from the main ggplot call.

This is usually how each layer function knows what data to use, because generally it is inherited in the main ggplot function. Whenever you specify a data argument or a mapping argument, you are generally overriding the inherited values. Any missing required aes mappings are attempted to be found in the main call.

library(ggplot2)
data1 <- data.frame(v1=rnorm(10, 50, 20), v2=rnorm(10,30,5))
data2 <- data.frame(v1=rnorm(10, 100, 20), v2=rnorm(10,50,10), z = c("A","B"))
plot_custom_ggplot <- function(df1, df2, mapping) {
    ggplot(data = NULL, mapping = mapping) +
      geom_point(data = df1, color = "blue") +
      geom_line(data = df2, mapping = aes(color = z)) #inherits x and y mapping from main ggplot call.
}

plot_custom_ggplot(data1,data2, aes(x = v1,y = v2))

But adding additional aes mappings is risky if you are also specifying data. This is because you data variable may not always contain the correct columns.

plot_custom_ggplot(df1 = data2, df2 = data1, aes(x = v1, y = v2))
#Error in FUN(X[[i]], ...) : object 'z' not found
#
#the column z is not present in data1 object - 
#R then looked globally for a z object and didnt find anything.

I believe it is best practices to use tidy data when working with ggplot because things become so much easier. There is usually no reason to use multiple data frames. Especially if you plan to use one set of mapping for all data frames. A good exception is if you are writing a plotting function for a custom R object, in which you know how it is defined.

Otherwise, consider and compare how these two functions work in this example:

data1 <- data.frame(v1=rnorm(20, 50, 20), v2=rnorm(20,30,5), letters= letters[1:20], id = "df1")
data2 <- data.frame(v1=rnorm(20, 100, 20), v2=rnorm(20,50,10), letters = letters[17:26], id = "df2")

set.seed(76)
plot_custom_ggplot2 <- function(df, mapping) {
  ggplot(data = df, mapping = mapping) +
    geom_bar(stat = "identity",
             position="stack") 
}

plot_custom_ggplot <- function(df1, df2, mapping) {
  ggplot(data = NULL, mapping = mapping) +
    geom_bar(data = df1, stat = "identity",
         position="stack") +
    geom_bar(data = df2, stat = "identity",
         position="stack")
}

plot_custom_ggplot(data1,data2, aes(x = letters,y = v2, fill = id))
plot_custom_ggplot2(rbind(data1,data2), aes(x = letters, y = v2, fill = id))

In the first plot, the red bars for q, r, s, and t are hidden behind the blue bars. This is because they are added on top of each other as layers. In the second plot, these values actually stack because these values were added together in a single layer rather than two separate ones.

I hope this gives you enough information to write your ggplot function.

On struggling with aes(): an intro to writing functions with ggplot , On struggling with aes(): an intro to writing functions with ggplot outputs freedom ## Multiple R-squared: 0.8793, Adjusted R-squared: 0.8782� Graph created by a custom ggplot function and then tweaked with ggplot code outside the function. Data from Zillow. For more R tips, head to the “Do More With R” page at InfoWorld or the “Do

library(tidyverse)

testplot <- function(df1, df2, mapping){

  a <- ggplot() + 
    geom_point(data = df1, mapping = mapping) +
    geom_point(data = df2, mapping = mapping)

  return(a)

}

mtcars2 <- mtcars / 100 # creating a separate dataframe to provide the function

testplot(mtcars, mtcars2, mapping = aes(x = drat, y = vs))

From your example you have "data2=data2" - geom_bar doesn't have an argument 'data2', only data. I got the above to work, so an adaptation for your purposes should work too!

writing R function with ggplot, Most of the first arguments to the ggplot2 layer functions are reserved for the mapping argument, which is from aes . So in your function� As you'll see, this doesn't work---it seems to print out the data frame that the plot is based on (?). My guess is that I'm misunderstanding something pretty basic about how objects work in R or the nature of ggplot2 plots. Thanks for any advice (or perhaps recommendations on better ways to do what I'm trying to do).

The reason I split my dataframe was because I wanted a grouped and stacked plot, and used this question: How to plot a Stacked and grouped bar chart in ggplot?

The mapping has to be different so that they don't end up on top on each other (so it's x=var1, and then x=var1+barwidth)

Anyway, I can make a plot with multiple geom_bar, but it's the subsequent geom_errorbar that doesn't work in a single function. I just added the error bars separately in the end, and maybe I'll look into the other options some other time.

I realise these are already functions so probably not meant to be used this way, and maybe that's why I can't do multiple geom_errorbar in one function. I just wanted my code to be more readable because I had to plot the same thing 12 times, with very minor differences and it was very long. Perhaps there is a more elegant way to do it though.

Writing functions for dplyr and ggplot2 – April 2, 2018, Today I'll take it another step and show how to produce the same graphs in R using ggplot2 as well as how to write some simple functions to� same graphs in R using ggplot2 as well as how to write some simple functions to make your programming life easier. Background and catch-up. My colleague wanted to be able to do some simple analysis around health care using the Centers for Disease Control and Prevention, National Center for Health Statistics, National Health Interview Survey. They

Programming with ggplot2, If you're not that familiar with how functions work in R, you might want to Creating small reusable components is most in line with the ggplot2� Since every plot theme in ggplot2 is a function, you can easily save your favorite theme settings as a custom-made function. Making a theme is easier than writing functions to generate multiple plots, as you won’t have to write any loops.

ggplot function, ggplot() initializes a ggplot object. It can be used to declare the input data frame for a graphic and to specify the set of plot aesthetics intended to be common� Writing ggplot functions in R with optional arguments. Ask Question Asked 8 years, 7 months ago. Active 6 years, 11 months ago. Viewed 8k times 7. 4. I have a series

Using ggplot2 in packages • ggplot2, As of this writing, this includes over 2,000 packages on CRAN and many more within an R package changes the way you refer to functions from ggplot2 and� R is a collaborative open source project with many contributors and citing R and its packages supports the development of such fantastic and free tools. R makes it easy to do this! The citation() function. This function outputs the reference for R. citation() ## ## To cite R in publications use: ## ## R Core Team (2017).

Comments
  • I'm confused. Which version of testplot are you actually running? Where have you defined df here? I don't seen how output is related to p here.
  • data2 is not a parameter, only data, thus your second line should be geom_bar(data=data2, mapping = ... See the rest of my edit for a full explanation on this.
  • that works in principle but what do I call the second dataframe? I'll edit the post to account for it
  • oh this makes sense! it works with geom_bar, but for some reason doesn't work the same way with geom_errorbar (keeps saying "can't add ggproto object"). Any idea what that means?
  • Can you provide a reproducable example? And are you sure that you're adding everything to a ggplot()? (No missing plus sign)