Пользовательские разрывы осей в фасетах ggplot2 на основе других столбцов - PullRequest
3 голосов
/ 11 февраля 2020

У меня есть данные для построения графика, где ось X находится в одном столбце, а главные разрывы оси X находятся в других столбцах.

Для моих данных выборки я изменю iris набор данных из ggplot2. Примечание: low и high вычисляются здесь произвольно - я выбрал min & max только для простоты воспроизведения.

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

Я надеюсь построить x = Sepal.Length огранки для Species, но только с двумя основными перерывами: df$min и df$max.

У меня проблемы с получением разрывов в правильном фасете.

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

enter image description here

Как видите, значения от df$low и df$high применяются ко всем фасетам. Я надеялся, что фасет setosa будет иметь только большие разрывы только в 4,3 и 5,8, versicolor только в 4,9 и 7,0 и virginica только в 4,9 и 7,9.

Есть ли способ пройти переменная фасета до breaks в scale_x_continuous? Или я должен отказаться от этого подхода и создать три отдельных ggplots и объединить их вместе с gridExtra?

Любая помощь будет признательна!

Ответы [ 2 ]

2 голосов
/ 11 февраля 2020

Вот возможное решение с использованием лоскутное одеяло :

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(`+`)

enter image description here

Я думаю, что это самый простой способ, который не не надо возиться с ggproto

1 голос
/ 11 февраля 2020

Аргументы break в масштабах не поддерживают аккуратную оценку в контексте data.frame, передаваемого основному вызову ggplot2. Если ваши разрывы могут быть рассчитаны по границам фасетов (обычно это пределы данных + расширение, когда scales = "free"), вы можете передать функцию в аргумент разрывов, который вычисляет разрывы по пределам.

Если вы действительно настроенный на наличие отдельных масштабов для фасета, на 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)

Создано в 2020-02-11 пакетом Представления (v0.3.0)

...