Search code examples
rggplot2dplyrinteractionnse

How to mix non-standard and standard evaluation in arguments to interaction(...) inside ggplot()?


I am seeking for a way to use NSE inside argument (in this case, intersect) in dplyr using rlang package.

Data frame:

df <- data.frame(time=as.factor(c(10,10,10,10,20,20,20,20,10,10,10,10,20,20,20,20)),
                 cost=as.factor(c(10,20,30,40,10,20,30,40,10,20,30,40,10,20,30,40)),
                 type=c("a","a","a","a","a","a","a","a","b","b","b","b","b","b","b","b"),
                 value=c(40,20,25,10,80,50,30,60,15,70,80,10,50,20,30,40))

## Set variables for NSE
a <- "time"
b <- "cost"
c <- "type"
d <- "value"

nse_a <- sym(a)
nse_b <- sym(b)
nse_c <- sym(c)
nse_d <- sym(d)

I can plot properly in SE.

## Plot in SE
df %>% ggplot(aes(x=cost, y=value, group=interaction(time,type), color=time, linetype=type)) + geom_line(size=1.2)

enter image description here

However, when I use NSE, it occurs an error:

## Plot in NSE
df %>% ggplot(aes_(x=nse_b, y=nse_d, group=interaction(nse_a,nse_c), color=nse_a, linetype=nse_c)) + geom_line(size=1.2)

Error: unique.default(x, nmax = nmax)
unique() applies only to vectors

It works if I remove group=intersection(...). I suppose the reason may be using NSE in a nested argument 'intersect(...)' inside aes_.

Do you have any solution to avoid this error?

I searched similar topics and tried to apply some examples such as unquoting by !!nse_a but it did not not work. I am new to 'NSE' and still do not well understand its manipulation manner.


Solution

  • You can only pass quoted arguments to aes_(), so the interaction has to be quoted, but it itself needs unquoted arguments (not really sure about the terminology here, sorry for any confusion)

    library(rlang)
    library(ggplot2)
    
    
    interact <- quo(interaction(!!nse_a, !!nse_c))
    
    df %>%
    ggplot(aes_(x=nse_b, 
                y=nse_d, 
                group=interact, 
                color=nse_a, 
                linetype=nse_c)) + 
        geom_line(size=1.2)
    
    # or equally
    
    df %>% 
      ggplot(aes_(x=nse_b, 
                  y=nse_d, 
                  group=quo(interaction(!!nse_a, !!nse_c)), 
                  color=nse_a, 
                  linetype=nse_c)) + 
      geom_line(size=1.2)
    

    Created on 2018-05-09 by the reprex package (v0.2.0).