1

I am interested in creating plots exploring a range of variables in columns within a dataframe. So far, I have a function that successfully calls a plot, and now hoping to apply this in a tidyverse format with map.

require(dplyr)
library(purrr)
# create dataframe
mydf <- data.frame("category" = as.factor(sample(c("type1", "type2"), 10, replace = TRUE)),
                   "var1" = runif(10, min = 0, max = 100),
                   "var2" = runif(10, min = 50, max = 150))

# create function
make_plot <- function(data, var)  {
  data %>% 
    ggplot() +
    aes(x = .data$category, y = {{var}}, color = .data$category) + 
  geom_boxplot(width = 0.2, notch = FALSE, position = position_dodge(1), lwd = 1.8, outlier.shape = NA)
}
plot <- make_plot(mydf, var1)
plot

This works and I am now trying to use map to run this code over a range of variables *var1, var2, etc) and generate a list of plot objects, as in https://wilkelab.org/SDS375/slides/functional-programming.html#1 . I have reviewed https://www.rdocumentation.org/packages/purrr/versions/0.2.5/topics/map and tried variations on

vars <- c("var1", "var2")
plots <- mydf %>% map(vars, make_plot) %>% pull(plots) %>% walk(print)

However, I get errors like "no applicable method for 'pull' applied to an object of class "list". I have so far not used map much, interested in any solutions for this.

marcel
  • 389
  • 1
  • 8
  • 21

2 Answers2

2

An approach using as.symbol to reference the vars.

require(dplyr)
library(purrr)
library(ggplot2)

make_plot <- function(data, var)  {
  data %>% 
    ggplot() +                                                    
    aes(x = category, y = !!as.symbol(var), color = category) + 
  geom_boxplot(width = 0.2, notch = FALSE, position = position_dodge(1), lwd = 1.8, outlier.shape = NA)
}

Generate plots

vars <- c("var1", "var2")
plots <- map(vars, ~ make_plot(mydf, .x))

Plot

plots[[1]] # or plots[[2]] etc
Andre Wildberg
  • 12,344
  • 3
  • 12
  • 29
0

Either you change your function to make it work with character column names (see Andre's answer) or you change the input to map my iterating over you vars character vector and turning it into a list of symbols with as.name (or alternatively as.symbol or rlang::sym).

library(dplyr)
library(ggplot2)
library(purrr)

vars <- c("var1", "var2")

plots <- map(map(vars, as.name),
             \(col) make_plot(mydf, !! col)) 

Data from OP

# create dataframe
mydf <- data.frame("category" = as.factor(sample(c("type1", "type2"), 10, replace = TRUE)),
                   "var1" = runif(10, min = 0, max = 100),
                   "var2" = runif(10, min = 50, max = 150))
# create function
make_plot <- function(data, var)  {
  data %>% 
    ggplot() +
    aes(x = category, y = {{ var }}, color = category) + 
    geom_boxplot(width = 0.2, notch = FALSE, position = position_dodge(1), lwd = 1.8, outlier.shape = NA)
}

Created on 2023-08-01 with reprex v2.0.2

TimTeaFan
  • 17,549
  • 4
  • 18
  • 39