1

我正在尝试使用patchwork包编写一个函数,其中根据函数中传递的参数显示图。我尝试了下面的方法,将未在函数中传递的对象设置为 NULL。但是,它仅在第一个对象不同于 NULL 时才有效。有什么想法吗?

# 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

reprex 包于 2020-06-07 创建(v0.3.0)

4

1 回答 1

1

由于您需要为 的每个元素运行相同的代码homeworld,因此您可以使用purrr::map(或者lapply,如果您愿意)遍历它。这将返回一个列表,其中包含每次迭代的元素,此处包含一个图(如p1p2等)。此列表可以是reduced(或Reduced)以迭代地组合每个元素+

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"))

reduce(plots, `+`)或者,您可以wrap_plots(plots)使用 patchwork 中的函数来代替,该wrap_plots()函数接受绘图列表。结果是一样的。

更一般地说,您应该在拼凑之前考虑刻面:

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"))

请注意,您可以通过这种方法免费获得漂亮的面板条标签,以确定哪个星球是哪个星球。

于 2020-06-08T03:13:39.410 回答