基于其他列的 ggplot2 构面中的自定义轴中断

Custom axis breaks in ggplot2 facets based on other columns

我有要绘制的数据,其中 x 轴位于一列中,x 轴主要中断位于其他列中。

对于我的示例数据,我将从 ggplot2 修改 iris 数据集。注意:lowhigh 在这里是任意计算的——我只选择了最小值和最大值以便于重现。

library(dplyr)
library(ggplot2)


df <- iris %>% 
  group_by(Species) %>% 
  mutate(low = min(Sepal.Length),
         high = max(Sepal.Length)) %>% 
  ungroup()
> df
# A tibble: 150 x 7
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species   low  high
          <dbl>       <dbl>        <dbl>       <dbl> <fct>   <dbl> <dbl>
 1          5.1         3.5          1.4         0.2 setosa    4.3   5.8
 2          4.9         3            1.4         0.2 setosa    4.3   5.8
 3          4.7         3.2          1.3         0.2 setosa    4.3   5.8
 4          4.6         3.1          1.5         0.2 setosa    4.3   5.8
 5          5           3.6          1.4         0.2 setosa    4.3   5.8
 6          5.4         3.9          1.7         0.4 setosa    4.3   5.8
 7          4.6         3.4          1.4         0.3 setosa    4.3   5.8
 8          5           3.4          1.5         0.2 setosa    4.3   5.8
 9          4.4         2.9          1.4         0.2 setosa    4.3   5.8
10          4.9         3.1          1.5         0.1 setosa    4.3   5.8
# ... with 140 more rows

我希望为 Species 绘制 x = Sepal.Length 分面,但只有两个主要突破点是 df$mindf$max

我无法在正确的方面取得突破。

df %>% 
  ggplot(aes(x = Sepal.Length,
             y = Petal.Length)) + 
  geom_point() + 
  facet_wrap(. ~ Species) + 
  scale_x_continuous(breaks = c(df$low, df$high))

如您所见,df$lowdf$high 中的值应用于所有方面。我希望 facet setosa 仅在 4.3 和 5.8 处有重大突破,versicolor 仅在 4.9 和 7.0 处出现重大突破,virginica 仅在 4.9 和 7.9 处出现重大突破。

有没有办法将 facet 变量传递给 scale_x_continuous 中的 breaks?或者我应该放弃这种方法并创建三个单独的 ggplots 并将它们与 gridExtra?

合并在一起

如有任何帮助,我们将不胜感激!

这是一个可能的解决方案,使用 patchwork:

library(ggplot2)
library(purrr)
library(patchwork)

df %>% 
  split(.$Species) %>% 
  map(~{
    .x %>% 
      ggplot(aes(x = Sepal.Length,
                 y = Petal.Length)) + 
        geom_point() + 
        facet_wrap(~ Species) + 
        scale_x_continuous(breaks = c(max(.x$low), max(.x$high))) +
        # assuming you want to use same y axis for each plot
        scale_y_continuous(limits = c(min(df$Petal.Length), max(df$Petal.Length)))
  }) %>% 
  reduce(`+`)

我认为这是最简单的方法,不需要弄乱 ggproto

在传递给主 ggplot2 调用的 data.frame 上下文中,比例尺的 break 参数不支持整洁评估。如果您的中断可以从 facet 限制计算(通常是数据限制 + 扩展,当 scales = "free" 时),您可以将一个函数传递给 breaks 参数,该参数根据限制计算中断。

如果您真的希望每个方面都有单独的比例尺,github 上有一些软件包支持为图的各个方面提供自定义比例尺。两者都要求您手动为每个方面指定比例。免责声明:我为第一个包做出了贡献,并且是第二个包的作者。

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(ggplot2)


df <- iris %>% 
  group_by(Species) %>% 
  mutate(low = min(Sepal.Length),
         high = max(Sepal.Length)) %>% 
  ungroup()

# Forgive the clunky tidyverse syntax
scale_list <- df$Species %>% levels() %>% setNames(.,.) %>% lapply(., function(i) {
  scale_x_continuous(breaks = unique(unlist(df[df$Species == i, c("low", "high")])))
})

#devtools::install_github("zeehio/facetscales")
library(facetscales)

df %>% 
  ggplot(aes(x = Sepal.Length,
             y = Petal.Length)) + 
  geom_point() + 
  facet_grid_sc(cols = vars(Species), scales = list(x = scale_list))


#devtools::install_github("teunbrand/ggnomics")
library(ggnomics)

df %>% 
  ggplot(aes(x = Sepal.Length,
             y = Petal.Length)) + 
  geom_point() + 
  facet_wrap(. ~ Species, scales = "free_x") +
  facetted_pos_scales(x = scale_list)

reprex package (v0.3.0)

于 2020 年 2 月 11 日创建