Functional programming with dplyr

Look for a more efficient / elegant way to pass multiple arguments to a group - using a non-standard function evaluation using dplyr. I do not want to use the operator ... but to specify functions separately.

My specific use case is a function that takes a data frame and creates a ggplot object with simpler syntax. Here is an example of the code I want to automate using my function:

# create data frame
my_df <- data.frame(month = sample(1:12, 1000, replace = T),
                    category = sample(head(letters, 3), 1000, replace = T),
                    approved = as.numeric(runif(1000) < 0.5))

my_df$converted <- my_df$approved * as.numeric(runif(1000) < 0.5)

my_df %>%
  group_by(month, category) %>%
  summarize(conversion_rate = sum(converted) / sum(approved)) %>%
  ggplot + geom_line(aes(x = month, y = conversion_rate, group = category, 
  color = category))

I want to combine this group_by, summarize, ggplot and geom_line into a simple function so that I can feed x, y and the group, and do all the dirty work under the hood. Here is what I started to work:

# create the function that does the grouping and plotting
plot_lines <- function(df, x, y, group) {

  x <- enquo(x)
  group <- enquo(group)
  group_bys <- quos(!! x, !! group)

  df %>%
    group_by(!!! group_bys) %>%
    my_smry %>%
    ggplot + geom_line(aes_(x = substitute(x), y = substitute(y), 
    group = substitute(group), color = substitute(group)))
}

# create a function to do the summarization
my_smry <- function(x) {
  x %>% 
    summarize(conversion_rate = sum(converted) / sum(approved))
}

# use my function
my_df %>% 
  plot_lines(x = month, y = conversion_rate, group = category)

, group_by : x group enquo, !! quos, unquote !!! , , . ?

, ggplot !! substitute? , , .

+6
2

, ggplot , quosures, , quosures rlang::quo_expr:

library(tidyverse)
set.seed(47)

my_df <- data_frame(month = sample(1:12, 1000, replace = TRUE),
                    category = sample(head(letters, 3), 1000, replace = TRUE),
                    approved = as.numeric(runif(1000) < 0.5),
                    converted = approved * as.numeric(runif(1000) < 0.5))

plot_lines <- function(df, x, y, group) {
    x <- enquo(x)
    y <- enquo(y)
    group <- enquo(group)

    df %>%
        group_by(!! x, !! group) %>%
        summarise(conversion_rate = sum(converted) / sum(approved)) %>%
        ggplot(aes_(x = rlang::quo_expr(x), 
                    y = rlang::quo_expr(y), 
                    color = rlang::quo_expr(group))) + 
        geom_line()
}

my_df %>% plot_lines(month, conversion_rate, category)

, ggplot lazyeval rlang, , , , , , .

+4

eval.parent(substitute(...)), . R, R . aes.

plot_lines <- function(df, x, y, group) eval.parent(substitute(
   df %>%
      group_by(x, group) %>%
      my_smry %>%
      ggplot + geom_line(aes(x = x, y = y, group = group, color = group))
))
plot_lines(my_df, month, conversion_rate, category)
+5

All Articles