Reputation: 1430
I'm trying to write a function with patchwork
package in which plots are displayed according to the arguments passed in the function. I tried the approach below, setting objects not passed in the function as NULL. However, it only works if the first object is different from NULL. Any thoughts?
# 1. PACKAGES
library(tidyverse)
library(patchwork)
# 2. DATA
data = starwars
# 3. FUNCTION
plot_people = function (homeworld = c("Tatooine", "Naboo", "Alderaan")) {
p1 = if (is.element("Tatooine", homeworld)) {
data %>%
filter(homeworld == "Tatooine") %>%
ggplot(aes(x = mass, y = height,
label = ifelse(species == "Human", name, NA))) +
geom_point() +
geom_label()
} else {
NULL
}
p2 = if (is.element("Naboo", homeworld)) {
data %>%
filter(homeworld == "Naboo") %>%
ggplot(aes(x = mass, y = height,
label = ifelse(species == "Human", name, NA))) +
geom_point() +
geom_label()
} else {
NULL
}
p3 = if (is.element("Alderaan", homeworld)) {
data %>%
filter(homeworld == "Alderaan") %>%
ggplot(aes(x = mass, y = height,
label = ifelse(species == "Human", name, NA))) +
geom_point() +
geom_label()
} else {
NULL
}
# how to write this line in order to plot only objects in homeworld argument?
p1 + p2 + p3
}
# 4. RESULTS
plot_people(homeworld = c("Naboo", "Tatooine"))
plot_people(homeworld = c("Naboo", "Alderaan"))
#> NULL
Created on 2020-06-07 by the reprex package (v0.3.0)
Upvotes: 1
Views: 260
Reputation: 43344
Since you need to run the same code for each element of homeworld
, you can iterate across it with purrr::map
(or lapply
, if you prefer). This returns a list with an element for each iteration, here containing a plot (like p1
, p2
, etc.). This list can be reduce
d (or Reduce
d) to iteratively combine each element with +
:
library(tidyverse)
library(patchwork)
plot_people = function (homeworld = c("Tatooine", "Naboo", "Alderaan")) {
plots <- map(homeworld, function(hw){
starwars %>%
filter(homeworld == hw) %>%
ggplot(aes(x = mass, y = height,
label = ifelse(species == "Human", name, NA))) +
geom_point() +
geom_label()
})
reduce(plots, `+`)
}
plot_people(homeworld = c("Naboo", "Tatooine"))
plot_people(homeworld = c("Naboo", "Alderaan"))
Alternatively, instead of reduce(plots, `+`)
, you could write wrap_plots(plots)
, using the wrap_plots()
function from patchwork which accepts a list of plots. The results are the same.
More generally, you should consider facetting before resorting to patchwork:
library(tidyverse)
plot_people = function (homeworld = c("Tatooine", "Naboo", "Alderaan")) {
starwars %>%
filter(homeworld %in% !!homeworld) %>%
ggplot(aes(x = mass, y = height,
label = ifelse(species == "Human", name, NA))) +
geom_point() +
geom_label() +
facet_wrap(~homeworld)
}
plot_people(homeworld = c("Naboo", "Tatooine"))
plot_people(homeworld = c("Naboo", "Alderaan"))
Note you get nice panel strip labels identifying which planet is which for free with this approach.
Upvotes: 1