How to Pass Aes Parameters of Ggplot to Function

R - How to pass variables to ggplot

Using of aes_string is deprecated, you can use sym with !! :

library(ggplot2)
library(rlang)

scatterWithRegLine = function(df, xColName, yColName, regMethod, showSe, showFullrange, size, yAxisLim) {

ggplot(df, aes(x = !!sym(xColName), y = !!sym(yColName))) +
geom_point() +
geom_smooth(method= regMethod, se=showSe, fullrange=showFullrange, size=size) + ylim(yAxisLim)
}

and then call it with

scatterWithRegLine(mtcars, "mpg", "wt", "loess", TRUE, FALSE, 1, c(0,5))

R ggplot2 - Understanding the parameters of the aes function

Consider the code chunk below:

library(ggplot2)

df <- data.frame(
x = c(1, 2), y = c(2, 1)
)

ggplot(df, aes(x, y + 1)) +
geom_point(colour = "green") +
geom_line(aes(colour = "blue"))

Here, the aes(x, y + 1) means aes(x = x, y = y + 1) which sets the x and y aesthetics that some layers understand to the x and y columns of the dataframe. This is because aes() has three arguments, x, y and .... By not declaring x = x for example, the first variable x is matched to the x parameter through the position in the function call. Other parameters than x or y must be named, for example aes(size = 10) and get passed trough ... to become part of the mapping (which are name-expression pairs).

Because the expression y = y + 1 is evaluated using 'non standard evaluation' in aes(), the scoping rules change and the variable y will first be attempted to be evaluated in the context of the data columns and not in the global environment, and hence we can 'calculate' the +1 on the dataframe columns.

It's not the aes() function that determines what are valid argument = value mappings, it is the layers that accept or reject parameters. You can find the parameters a layer accepts in the documentation of the layer, for example in ?geom_point, you see that it understands x, y, alpha, colour, fill, group, shape, size and stroke. You should be able to find these back if you call your_geom_layer$geom$aesthetics(). Extension packages can define their own layers with their own aesthetics, such as the area in the {treemap} package.

Additionally, because we've defined aes(x, y + 1) in the main ggplot() call, it will applied to every geometry or stat layer in that plot, in this case the points and the line. Hence, we do not need to repeat the same mapping in every layer but it is inherited unless you set inherit.aes = FALSE in a layer.

In the point layer we've defined colour = "green" outside the aes() function, so it will be interpreted literally (and follows standard evaluation with the usual scoping rules). People also call this a 'static' mapping, and you can only use this in layers and not globally. In contrast, because we've defined aes(colour = "blue") in the line layer, the "blue" will be interpreted as a categorical variable that participates in a colour scale that has it's own palette (a 'dynamic' mapping). If you execute the code, you'll see that the line is not blue, but a salmon-ish colour with a legend that maps the categorical value "blue" to a discrete scale with a 1-colour palette. Because "blue" is not a column in the dataframe, nor a variable in the global environment, it will be interpreted as a length 1 vector that will be recycled to fit the number of rows in the dataframe.

In general, if you want to map something to a scale (including position scales such as x and y), you put it inside aes(). If you want to have a literal interpretation, you put it outside aes() at the relevant layer.

passing parameters to ggplot

One solution would be to pass x and y as string names of columns in data frame DS.

f <- function(DS, x, y) {    
ggplot(DS, aes_string(x = x, y = y)) + geom_point()
}

And then call the function as:

f(cars, "speed", "dist")

However, it seems that you don't want that? Can you provide an example why you would need different functionality? Is it because you don't want to have the arguments in the same data frame?

R: How to pass parameters to ggplot geom_ within a function?

I like MSM's approach, but if you want to be able to add my_geom_y to a ggplot you've already made, this is an alternative that might suit what you're after:

library(ggplot2)
x <- 1:100

my_geom_y <- function(yy, colour = "black"){
list(
geom_line(mapping = aes(y= yy),
col = colour),
data = data.frame(x, yy),
geom_point(mapping = aes(y = yy),
col = colour,
data = data.frame(x, yy))
)
}

ggplot(mapping = aes(x)) +
my_geom_y(x, "red") +
my_geom_y(dlnorm(x), "blue") +
my_geom_y((x^1.1), "black") +
my_geom_y(x/2, "yellow")

Sample Image

R- pass argument to ggplot in function

Based on the function arguments, it seems like convert is flip. Instead of using get to modify the 'x' argument, we can do this with mutate after converting the arguments to quosures

myfunction<- function(mydata, x, y, convert = FALSE){
x <- enquo(x)
y <- enquo(y)
xnew <- quo_name(x)
if (convert) {
mydata %>%
mutate(!! (xnew) := 1- !!(x)) %>%
ggplot(., aes_string(xnew, quo_name(y))) +
geom_line() +
xlab(paste0("1 - ", xnew))

} else {

ggplot(mydata, aes_string(xnew, quo_name(y))) +
geom_line()

}

}

myfunction(df1, x1, x2, convert = TRUE)

-output

Sample Image

myfunction(df1, x1, x2, convert = FALSE)

-output

Sample Image

data

df1 <- structure(list(x1 = c(0.1, 0.3, 0.4), x2 = c(0.2, 0.5, 0.6), 
x3 = c(0.3, 0.7, 0.8), x4 = c(0.4, 0.9, 0.2)), .Names = c("x1",
"x2", "x3", "x4"), class = "data.frame", row.names = c(NA, -3L
))

Create ggplot2 function and specify arguments as variables in data as per ggplot2 standard functionality

With the devel version of ggplot2, we can pass unquoted arguments, convert it to quosure (with enquo) and evaluate it (!!)

ggfun <- function(dat, x.var, y.var){
x.var <- enquo(x.var)
y.var <- enquo(y.var)
ggp <- ggplot(data = dat,
aes(x = !! x.var,
y = !! y.var)) +
geom_point()

return(ggp)
}

ggfun(dat = mtcars, x.var = drat, y.var = hp)

For quoted strings, convert it to symbol with sym (from rlang) and do the evaluation

ggfun <- function(dat, x.var, y.var){
x.var <- rlang::sym(x.var)
y.var <- rlang::sym(y.var)
ggp <- ggplot(data = dat,
aes(x = !! x.var,
y = !! y.var)) +
geom_point()

return(ggp)
}

ggfun(dat = mtcars, x.var = "drat", y.var = "hp")

Sample Image


If we want to pass either quoted or unquoted, the quosure is changed to character (quo_name), then to symbol (sym) and evaluate (!!)

ggfun <- function(dat, x.var, y.var){
x.var <- rlang::sym(quo_name(enquo(x.var)))
y.var <- rlang::sym(quo_name(enquo(y.var)))
ggp <- ggplot(data = dat,
aes(x = !! x.var,
y = !! y.var)) +
geom_point()

return(ggp)
}

p1 <- ggfun(dat = mtcars, x.var = drat, y.var = hp)
p2 <- ggfun(dat = mtcars, x.var = "drat", y.var = "hp")

all.equal(p1, p2)
#[1] TRUE

ggplot2 pass variable to plot to a function

Use aes_string for this kind of programming:

library(ggplot2)

plothist <- function(data, column) {
ggplot(data, aes_string(x = column)) + geom_histogram()
}

plothist(data, "fixed.acidity")


Related Topics



Leave a reply



Submit