Подтвердить что ты не робот

Используя ggplot2, могу ли я вставить разрыв по оси?

Я хочу сделать гистограмму, где одно из значений намного больше, чем все другие значения. Есть ли способ иметь прерывистую ось Y? Мои данные таковы:

df <- data.frame(a = c(1,2,3,500), b = c('a1', 'a2','a3', 'a4'))

p <- ggplot(data = df, aes(x = b, y = a)) + geom_bar() 
p <- p + opts(axis.text.x=theme_text(angle= 90, hjust=1))  + coord_flip()
p

enter image description here

Есть ли способ заставить мою ось работать от 1- 10, затем от 490 до 500? Я не могу придумать какой-либо другой способ построения данных (кроме преобразования, которое я не хочу делать)

[Изменить 2019-05-06]:

Спустя 8 лет вышеприведенный код необходимо изменить, чтобы он работал с версией 3.1.1 ggplot2 для создания той же диаграммы:

library(ggplot2)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip()
4b9b3361

Ответ 1

Как уже упоминалось в другом месте, это не то, что ggplot2 будет хорошо работать, поскольку сломанные оси обычно считаются сомнительными.

Другие стратегии часто считаются лучшими решениями этой проблемы. Брайан упомянул несколько (огранки, два сюжета, посвященные различным наборам ценностей). Еще один вариант, который люди слишком часто пропускают, особенно для штрих-кодов, - это сделать таблицу:

enter image description here

Глядя на фактические значения, 500 не скрывает различия в других значениях! По какой-то причине таблицы не получают достаточного уважения в качестве метода визуализации. Вы можете возразить, что ваши данные имеют много и много категорий, которые становятся громоздкими в таблице. Если это так, вероятно, ваша гистограмма будет иметь слишком много баров, чтобы быть разумным.

И я не спорю о таблицах все время. Но они определенно должны что-то учитывать, если вы создаете баррикады с относительно небольшим количеством баров. И если вы делаете барчарты с множеством баров, вам может потребоваться переосмыслить это в любом случае.

Наконец, в пакете plotrix есть функция axis.break, которая реализует сломанные оси. Однако из того, что я собираюсь, вам придется вручную указать метки и позиции оси.

Ответ 2

Нет, не используйте ggplot. См. Обсуждение в разделе http://groups.google.com/group/ggplot2/browse_thread/thread/8d2acbfc59d2f247, где Хэдли объясняет, почему это невозможно, но дает предложенную альтернативу (граненый график, один со всеми данными, один увеличенный конкретный регион).

Ответ 3

Не с ggplot, но с помощью графика вы можете легко сделать это:

library(plotrix)
gap.barplot(df$a, gap=c(5,495),horiz=T)

Ответ 4

нет, к сожалению нет

Страх в том, что возможность прерывистых осей приведет к обману аудитории. Однако бывают случаи, когда отсутствие прерывистой оси приводит к искажению.

Например, если ось усечена, но обычно лежит в пределах некоторого интервала (скажем [0,1]), аудитория может не заметить усечение и сделать искаженные выводы о данных. В этом случае явная прерывистая ось будет более подходящей и прозрачной.

Для сравнения:

Example of good use of continuous vs discontinuous axis

Ответ 5

Я сомневаюсь, что что-нибудь с полки в R, но вы можете показать данные как серию 3D частичных кубов. 500 составляет всего 5 * 10 * 10, поэтому он будет хорошо масштабироваться. Точным значением может быть метка.

Это, вероятно, следует использовать только в том случае, если по какой-то причине вы должны иметь графическое представление.

Ответ 6

Одна стратегия состоит в том, чтобы изменить ось, чтобы построить масштаб журнала. Таким образом, вы можете уменьшить экспоненциально более высокое значение в 10 раз

Ответ 7

Восемь лет спустя пакет ggforce предлагает расширение facet_zoom() которое является реализацией предложения Хэдли Уикхема, чтобы показать два графика (как указано в ответе Брайана Диггса).

Увеличить грань

library(ggforce)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  facet_zoom(ylim = c(0, 10))

enter image description here

К сожалению, текущая версия ggforce 0.2.2 выдает ошибку coord_flip() поэтому могут отображаться только вертикальные полосы.

Увеличенный фасет показывает изменения малых значений, но по-прежнему содержит большой - теперь обрезанный - a4. Параметр zoom.data определяет, какие значения отображаются в увеличенном фасете:

library(ggforce)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  facet_zoom(ylim = c(0, 10), zoom.data = ifelse(a <= 10, NA, FALSE))

enter image description here

Два участка

Хэдли Уикхем предложил

Я думаю, что гораздо более уместно показать два графика - один из всех данных, а другой - только небольшие значения.

Этот код создает два участка

library(ggplot2)
g1 <- ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip()
g2 <- ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip() +
  ylim(NA, 10)

которые могут быть объединены в один сюжет

cowplot::plot_grid(g1, g2) # or ggpubr::ggarrange(g1, g2)

enter image description here

или же

gridExtra::grid.arrange(g1, g2) # or egg::ggarrange(g1, g2)

enter image description here

Две грани

Это было предложено в комментарии Чейза, а также Брайана Диггса в его ответе, который интерпретировал предложение Хэдли использовать

граненые участки, один со всеми данными, один увеличенный в определенном регионе

но пока не было предоставлено никакого кода для этого подхода.

Поскольку не существует простого способа отдельно масштабировать фасеты (см., Например, связанный вопрос), необходимо манипулировать данными:

library(dplyr)
library(ggplot2)
ggplot() + 
  aes(x = b, y = a) +
  geom_col(data = df %>% mutate(subset = "all")) +
  geom_col(data = df %>% filter(a <= 10) %>% mutate(subset = "small")) +
  coord_flip() + 
  facet_wrap(~ subset, scales = "free_x")

enter image description here