1

I have a dataset that I want to make simple bar charts for each variable that has their appropriate title by using map() from purrr.

My dataset has 4 variables, and I have a vector with 4 titles. How do I pass these titles through so R outputs a plot that has the appropriate title for each? For my end result, I want 4 plots, each with the appropriate title (and not 16 plots that are each possible permutation of title and plot).

I've tried looking at this answer, but my titles are contained in another vector. This post got me as far as I have so far.

Here's my data and vector of titles:

library(dplyr)
test <- tibble(s1 = c("Agree", "Neutral", "Strongly Disagree"),
               s2rl = c("Agree", "Neutral", "Strongly Disagree"),
               f1 = c("Strongly Agree", "Disagree", "Strongly Disagree"),
               f2rl = c("Strongly Agree", "Disagree", "Strongly Disagree"))

titles <- c("S1 results", "Results for S2RL", "Fiscal Results for F1", "Financial Status of F2RL")

And here's the custom function that I'm building that takes 2 inputs, the variable and the title (the dataset is hardcoded in), and my map function that does not work:

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

my_plots = function(variable) {
  test %>%
    count({{variable}}) %>%
    mutate(percent = 100*(n / sum(n, na.rm = T))) %>%
    ggplot(aes(x = {{variable}}, y = percent, fill = {{variable}})) + 
    geom_bar(stat = "identity") +
    ylab("Percentage") +
    ggtitle(paste(title, "N =", n)) +
    coord_flip() +
    theme_minimal() +
    scale_fill_manual(values = c("Strongly disagree" = "#CA001B", "Disagree" = "#1D28B0", "Neutral" = "#D71DA4", "Agree" = "#00A3AD", "Strongly agree" = "#FF8200")) +
    scale_x_discrete(labels = c("Strongly disagree" = "Strongly\nDisagree", "Disagree" = "Disagree", "Neutral" = "Neutral", "Agree" = "Agree", "Strongly agree" = "Strongly\nAgree"), drop = FALSE) + 
    theme(axis.title.y = element_blank(),
          axis.text = element_text(size = 9, color = "gray28", face = "bold", hjust = .5),
          axis.title.x = element_text(size = 12, color = "gray32", face = "bold"),
          legend.position = "none",
          text = element_text(family = "Arial"),
          plot.title = element_text(size = 14, color = "gray32", face = "bold", hjust = .5)) +
    ylim(0, 100)
}

test%>%
  map(~my_plots(variable = .x, titles))
J.Sabree
  • 2,280
  • 19
  • 48

1 Answers1

2

It may be better to convert to symbol and evaluate (!!) instead of {{}} or use .data

library(dplyr)
library(purrr)
library(ggplot2)
library(ggpubr)
my_plots = function(variable, title) {
  test %>%
    count(!! rlang::sym(variable)) %>%
    mutate(percent = 100*(n / sum(n, na.rm = TRUE))) %>%
    ggplot(aes(x = !! rlang::sym(variable), y = percent, fill = .data[[variable]])) + 
    geom_bar(stat = "identity") +
    ylab("Percentage") +
    ggtitle(title) +
    coord_flip() +
    theme_minimal() +
    scale_fill_manual(values = c("Strongly disagree" = "#CA001B", "Disagree" = "#1D28B0", "Neutral" = "#D71DA4", "Agree" = "#00A3AD", "Strongly agree" = "#FF8200")) +
    scale_x_discrete(labels = c("Strongly disagree" = "Strongly\nDisagree", "Disagree" = "Disagree", "Neutral" = "Neutral", "Agree" = "Agree", "Strongly agree" = "Strongly\nAgree"), drop = FALSE) + 
    theme(axis.title.y = element_blank(),
          axis.text = element_text(size = 9, color = "gray28", face = "bold", hjust = .5),
          axis.title.x = element_text(size = 12, color = "gray32", face = "bold"),
          legend.position = "none",
          text = element_text(family = "Arial"),
          plot.title = element_text(size = 14, color = "gray32", face = "bold", hjust = .5)) +
    ylim(0, 100)
}

Then loop over the column names and titles in map2 and apply the function

out <- map2(names(test), titles, ~ my_plots(variable = .x, title = .y))
ggarrange(plotlist = out, ncol = 2, nrow = 2)

-output

enter image description here

akrun
  • 874,273
  • 37
  • 540
  • 662
  • thank you! One question, in my original title, I wanted it to have the name and the sample size n. When I try your code but add in my original paste argument in ggtitle, I get this error--any ideas? Error in paste(title, "n", n) : cannot coerce type 'closure' to vector of type 'character' – J.Sabree Aug 18 '21 at 00:04
  • @J.Sabree That part I am not sure what you really wanted beacuse `n` is a vector of values, you may need to collapse or take the first one – akrun Aug 18 '21 at 00:20
  • I'll try collapsing. In my actual data, some survey responses have NAs, so I wanted to show the number of non-missing responses. In this example, they'd all be 3, but in the real one they will almost certainly vary. Thanks again! – J.Sabree Aug 18 '21 at 00:55
  • @J.Sabree Also, when you try with `ggtitle`, the `n` may not be available as such. You may need `toString(unique(.data[["n"]]))` or so. I haven't tested it – akrun Aug 18 '21 at 00:57