根据另一个因素,在facet_wrap / facet_grid中重新排列面板,并多次出现

时间:2019-05-22 09:37:46

标签: r ggplot2 forcats

请考虑以下示例。我想通过将两列连接到一个字符串中来为面板创建自定义标签。

通过构面创建的面板按字母顺序排列,但实际上,我希望它们按src进行排列,因此应该先出现SRC01,然后再出现SRC02,等等。

library(tidyverse)

tibble::tibble(
  src = rep(c("SRC03", "SRC04", "SRC01", "SRC02"), 2),
  data = runif(8)
) %>% 
  mutate(
    foo = case_when(src %in% c("SRC01", "SRC02") ~ "foo", TRUE ~ "bar"),
    label = paste(foo, src)
  ) %>% 
  ggplot(aes(x = data)) +
  geom_density() +
  facet_wrap(~label)

reprex package(v0.3.0)于2019-05-22创建

我知道此顺序取决于基础因素级别的顺序,但是this question显示了如何手动指定我不希望的级别(还有更多的SRC值,而我不知道不想输入所有这些…)。

我找到了使用fct_reorder的解决方案,其中可以指定:

mutate(label = fct_reorder(label, src, .fun = identity))

但这仅在每个src/label组合只有一行时有效。如果我添加数据(即每个组合有多个数据点),则会失败并显示以下信息:

Error: `fun` must return a single value per group

实现我所需的最简洁的方法是什么?

1 个答案:

答案 0 :(得分:1)

您可以使用src的数字部分,然后使用reorder()

tibble::tibble(
  src = rep(c("SRC03", "SRC04", "SRC01", "SRC02"), 2),
  data = runif(8)
) %>% 
  mutate(
    foo = case_when(src %in% c("SRC01", "SRC02") ~ "foo", TRUE ~ "bar"),
    label = paste(foo, src)
  ) %>% 
  mutate(label_order = as.numeric(str_extract(src, "\\d+"))) %>% 
# use str_extract() to find the "01" inside "SRC01", turn it to numeric.
  ggplot(aes(x = data)) +
  geom_density() +
  facet_wrap(~reorder(label, label_order)) 
# user reorder to change the ordering based on the numbers

enter image description here


关于str_extract()的注释,它可用于您的示例,因为:

str_extract("SRC01", "\\d+")给出"01",然后转换为1。但是:

str_extract("2SRC01", "\\d+")将返回2,这可能不太理想。

幸运的是,有很多方法可以使用正则表达式提取您可能需要的内容。