1

I have a data set where I need to generate multiple plots based on different columns, so instead of copy/pasting, I am trying to write a function, where I pass the function the dataframe and the column name. I am pretty sure that this requires a quosure, but I don't seem to be able to get it to work in ggplot2.

Ideally, I would be able to pass the dataframe, RawData, and the column name (B in this case) and it would generate a bar plot using column B, and including the column B label on the plot. For example.

RawData = data.frame(A = runif(12, 0, 5), B = LETTERS[seq(1,4)], C = letters[seq(3,1)])

ggplot(RawData, aes(x=A,y=B))+
  geom_bar(stat="identity",position="dodge")+
  xlab("Group")+ylab("B")

The function I wrote is effectively this...

PlotFn  = function(df, VarName) {
  VarName = quo(VarName)
  ggplot(df, aes(x=A,y=!!VarName))+
  geom_bar(stat="identity",position="dodge")+
  xlab("Group")+ylab(as_label(!!VarName))
}

PlotFn(RawData, B)

Which throws the error:

Error: Quosures can only be unquoted within a quasiquotation context.

# Bad: list(!!myquosure)

# Good: dplyr::mutate(data, !!myquosure)

Ideally I would be able to have my plot function run

PlotFn(RawData, B)

PlotFn(RawData, C)

and give bar plots that are labeled appropriately, like the one here.

1

1 Answer 1

3

You don't need to unquote (!!) VarName

library(rlang)
library(tidyverse)

RawData = data.frame(A = runif(12, 0, 5), 
                     B = LETTERS[seq(1,4)], 
                     C = letters[seq(3,1)])

PlotFn <- function(df, .VarName) {
  VarName <- enquo(.VarName)
  ggplot(df, aes(x = A, y = !!VarName)) +
    geom_bar(stat = "identity", position = "dodge") +
    ylab(as_label(VarName)) +
    xlab("Group")
}
PlotFn(RawData, C)

I personally prefer .data[[]] like this

PlotFn2 <- function(df, .VarName) {
  ggplot(df, aes(x = A, y = .data[[.VarName]])) +
    geom_col(position = "dodge") +
    ylab(.VarName) +
    xlab("Group")
}

plot_list <- c("B", "C") %>% 
  map(~ PlotFn2(RawData, .x))
plot_list
#> [[1]]

#> 
#> [[2]]

Created on 2019-08-06 by the reprex package (v0.3.0)

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

4 Comments

Another option you could add to your answer is PlotFn <- function(df, .VarName) { ggplot(df, aes(x = A, y = {{ .VarName. }})) }.
@TimTeaFan: thanks for the reminder! I kept forgetting about the new rlang's function
@Tung, thank you, this is pretty confusing, somehow I couldn't get this to go the way I thought it might. You use the rlang to say .VarName right? I just tried to run with PlotFn = function(df, VarName) { VarName = enquo(VarName) ggplot(df, aes(x=A,y=!!VarName))+ geom_bar(stat="identity",position="dodge")+ xlab("Group")+ylab(as_label(VarName)) } and it worked, but didn't need rlang, am I right on this?
@EBrewe: no you don't need rlang. Only needed if you use curly-curly {{ }} as TimTeaFan mentioned above

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.