Reputation: 1102
df <- tibble(question_text = c('Did they do the thing?', 'Did they do the thing?','Did they do the thing?', 'Did they do the thing?'),
answer_text = c('They did', 'They did', 'They did not', 'They did not'),
answer_numeric = c(3, 3, 2, 2),
gender = c('Female', 'Male', 'Female', 'Male'),
n = c(82000, 41000, 12000, 39000))
df
# A tibble: 4 x 5
question_text answer_text answer_numeric gender n
<chr> <chr> <dbl> <chr> <dbl>
1 Did they do the thing? They did 3 Female 82000
2 Did they do the thing? They did 3 Male 41000
3 Did they do the thing? They did not 2 Female 12000
4 Did they do the thing? They did not 2 Male 39000
I want to write a function that prints a ggplot graph and which passes through the value of question_text
to the title. (in practice my dataset has many more question-answer combinations than in the tibble shown, but the code below replicates the error i'm getting).
library(tidyverse)
library(scales)
library(viridis)
graph_fcn <- function(catvar, ft_size=12, title, scales){
df %>%
ggplot() +
geom_col(aes(x = reorder(answer_text, answer_numeric), y = n, fill = answer_text)) +
scale_y_continuous(labels = comma) +
theme(legend.position = 'none',
axis.title = element_blank(),
axis.text=element_text(size={{ft_size}})) +
scale_fill_viridis(discrete = TRUE, alpha=0.6) +
ggtitle(paste0("\"", question_text, "\"", {{title}})) +
facet_wrap(vars({{catvar}}), scales={{scales}})
}
graph_fcn(catvar = gender,
ft_size = 8,
title = 'by gender',
scales = 'fixed')
If you run the above it will return the error:
Error in paste0("\"", { : object 'question_text' not found
I've tried numerous things to try and solve this:
question_text
inside double curly brackets, i.e. {{}}
question_text
through to the function argument and setting the default as question_text
question_text
through to the function argument and then explicitly setting question_text = question_text
in the function callNone of the above work though. Does anyone know what i'm doing wrong here? And how I can pass the value of question_text
through to ggtitle()
?
If I remove question_text
from the line ggtitle(paste0("\"", question_text, "\"", {{title}}))
the graph looks like this:
As my df
actually contains many more question-answer combinations, in practice what i'm doing is performing various mutations and then piping that directly into the ggplot() command, within the function. I.e.
graph_fcn <- function(que_id, catvar, ft_size=12, title, scales){
df %>%
filter(question_id=={{que_id}}) %>%
group_by(question_text, answer_text, answer_numeric, {{catvar}}) %>% count() %>%
filter(!is.na({{catvar}})) %>%
ggplot() +
geom_col(aes(x = reorder(answer_text, answer_numeric), y = n, fill = answer_text)) +
scale_y_continuous(labels = comma) +
theme(legend.position = 'none',
axis.title = element_blank(),
axis.text=element_text(size={{ft_size}})) +
scale_fill_viridis(discrete = TRUE, alpha=0.6) +
ggtitle(paste0("\"", question_text, "\"", {{title}})) +
facet_wrap(vars({{catvar}}), scales={{scales}})
}
graph_fcn(catvar = gender,
ft_size = 8,
title = 'by gender',
scales = 'fixed')
So if I put df$question_text[1]
inside ggtitle() it pulls the first value from the main df
rather than the much smaller one that only contains a single question value.
The below solutions work well for a small df with only one question-answer combination, and Sonak's is great if you want to make plots for all questions. I found the simplest though is actually to assign the dplyr transformations to a temp_df
within the function, then separately within the function pass the temp_df
into the ggplot
call.
I.e.
graph_fcn <- function(que_id, catvar, ft_size=12, title, scales){
temp_df <- df %>%
filter(question_id=={{que_id}}) %>%
group_by(question_text, answer_text, answer_numeric, {{catvar}}) %>% count() %>%
filter(!is.na({{catvar}}))
temp_df %>%
ggplot() +
geom_col(aes(x = reorder(answer_text, answer_numeric), y = n, fill = answer_text)) +
scale_y_continuous(labels = comma) +
theme(legend.position = 'none',
axis.title = element_blank(),
axis.text=element_text(size={{ft_size}})) +
scale_fill_viridis(discrete = TRUE, alpha=0.6) +
ggtitle(paste0("\"", temp_df$question_text[1], "\"", {{title}})) +
facet_wrap(vars({{catvar}}), scales={{scales}})
}
Upvotes: 3
Views: 2115
Reputation: 388807
library(tidyverse)
library(scales)
library(viridis)
graph_fcn <- function(df, catvar, ft_size=12, title, scales){
ggplot(df) +
geom_col(aes(x = reorder(answer_text, answer_numeric),
y = n, fill = answer_text)) +
scale_y_continuous(labels = comma) +
theme(legend.position = 'none',
axis.title = element_blank(),
axis.text=element_text(size=ft_size)) +
scale_fill_viridis(discrete = TRUE, alpha=0.6) +
ggtitle(paste(df$question_text[1], title)) +
facet_wrap(vars({{catvar}}), scales=scales)
}
You don't need
scales={{scales}}
size={{ft_size}})
{{title}})
Those values can be directly passed.
df$question_text
has multiple values , it is better to select specific one which you are interested in.
To apply the function to multiple question id use -
df %>%
group_split(question_id) %>%
purrr::map(~graph_fcn(.x, catvar = gender,
ft_size = 8,
title = 'by gender',
scales = 'fixed')) -> list_plots
list_plots
Upvotes: 2
Reputation: 6206
Adding df$question_text works:
graph_fcn <- function(catvar, ft_size=12, title, scales){
df %>%
ggplot() +
geom_col(aes(x = reorder(answer_text, answer_numeric), y = n, fill = answer_text)) +
# scale_y_continuous(labels = 'comma') +
theme(legend.position = 'none',
axis.title = element_blank(),
axis.text=element_text(size={{ft_size}})) +
scale_fill_viridis(discrete = TRUE, alpha=0.6) +
ggtitle(paste0("\"", df$question_text, "\"", {{title}})) +
facet_wrap(vars({{catvar}}), scales={{scales}})
}
Upvotes: 1