Reputation: 107
I have a function that creates a list of plots based on unique values of 'gear' from mtcars
library(datasets)
library(magrittr)
library(ggplot2)
library(dplyr)
make_plots <- function(data) {
### create list of plot objects for every unique value of 'gear' (from mtcars)
p_list <- lapply(sort(unique(data$gear)), function(i) {
ggplot2::ggplot(data[data$gear == i,], ggplot2::aes(x = wt, y = mpg, color = factor(cyl))) +
ggplot2::geom_point() +
ggplot2::facet_wrap(~ gear) +
ggplot2::scale_color_discrete(name = "cyl")
})
p_list
}
### output list of plots
example_output <- make_plots(mtcars)
What I would like: A list of plots based on unique values of 'gear', but have a different type of plot output depending on each 'gear' value's associated 'plot_type', which I created as another column in the mtcars dataframe. So same number of plots, but different types of plots.
### create new column of 'plot_type', where every unique gear value has the same 'plot_type', i.e.,
### all gears of 3 are of type 'scatter', all gears of 4 are of type 'bar', and all gear of 5 are of type
### 'log'
mtcars %>%
dplyr::mutate(plot_type = case_when(
gear == 3 ~ "scatter",
gear == 4 ~ "bar",
gear == 5 ~ "log"
))
I envisioned something roughly like below, but am obviously having trouble.
make_plots <- function(data) {
### creates list of dataframes, with one dataframe per unique value of 'plot_type'
split_data <- data %>%
dplyr::group_split(plot_type)
p_type <- lapply(split_data[split_data$plot_type == i,], function(i) {
if(split_data[split_data$plot_type == "scatter"]) {
p_list <- lapply(sort(unique(split_data$gear)), function(i) {
ggplot2::ggplot(split_data[split_data$gear == i,], ggplot2::aes(x = wt, y = mpg, color = factor(cyl))) +
ggplot2::geom_point() +
ggplot2::facet_wrap(~ gear)
})
p_list
}
})
p_type
}
Upvotes: 1
Views: 175
Reputation: 125268
Instead of putting everything inside one function you could
make use separate functions for each plot type along the lines of your first make_plots
function.
make a wrapper for the outer loop which calls the plot type functions were I make use of purrr::imap
instead of lapply to pass the name of the plot type.
Note: I dropped the log type and just illustrate the approach with a scatter and bar chart.
library(ggplot2)
library(dplyr)
library(purrr)
mtcars2 <- mtcars %>%
dplyr::mutate(plot_type = case_when(
gear == 3 ~ "scatter",
gear %in% c(4, 5) ~ "bar"
))
make_scatter <- function(data) {
lapply(sort(unique(data$gear)), function(i) {
ggplot2::ggplot(data[data$gear == i, ], ggplot2::aes(x = wt, y = mpg, color = factor(cyl))) +
ggplot2::geom_point() +
ggplot2::facet_wrap(~gear) +
ggplot2::scale_color_discrete(name = "cyl")
})
}
make_bar <- function(data) {
lapply(sort(unique(data$gear)), function(i) {
ggplot2::ggplot(data[data$gear == i, ], ggplot2::aes(x = cyl, fill = factor(cyl))) +
ggplot2::geom_bar() +
ggplot2::facet_wrap(~gear) +
ggplot2::scale_color_discrete(name = "cyl")
})
}
make_plots <- function(data) {
split_data <- split(data, data$plot_type)
p_type <- purrr::imap(split_data, function(x, plot_type) {
if (plot_type == "scatter") {
make_scatter(x)
} else if (plot_type == "bar") {
make_bar(x)
}
})
p_type
}
make_plots(mtcars2)
#> $bar
#> $bar[[1]]
#>
#> $bar[[2]]
#>
#>
#> $scatter
#> $scatter[[1]]
Upvotes: 1