#r #ggplot2 #patchwork
Вопрос:
У меня часто есть цифры, у которых одна и та же общая ось x, но разные оси y. Они не могут быть гранеными, так как некоторые оси y нуждаются в сложных именах и/или имеют перевернутые координаты по историческим/интерпретационным причинам.
Ниже я приведу пример такой фальшивой записи и покажу, как я хотел бы, чтобы этот сюжет выглядел после настройки в Inkscape. Есть ли какой-либо способ достичь этого результата изнутри R/patchwork?
library(tidyverse)
library(patchwork)
set.seed(123)
dat <- tibble::tibble(a = 1:10,
b = c(0, 2, 5, 8, 5, 4, 6, 4, 3, 2),
c = -stats::rnorm(10, b, 3),
d = sample(letters[1:3], 10, TRUE))
shared_x <- c(0, 11)
pl1 <- dat %>%
ggplot(aes(x = a, y = b))
geom_point(colour = "indianred")
coord_cartesian(xlim = shared_x)
scale_y_continuous("B is awesome", position = "right")
pl2 <- dat %>%
ggplot(aes(x = a, y = c))
geom_point(colour = "steelblue")
scale_y_reverse("C is inversely related to B")
coord_cartesian(xlim = shared_x, ylim = c(3, -13))
theme_set(theme_classic())
(pl1 amp; theme(axis.title.x = element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.line.x = element_blank())) / pl2
ggsave("overlapping_axes.pdf", width = 10, height = 8, units = "cm")
Создано 2021-07-09 с помощью пакета reprex (версия 2.0)
Комментарии:
1. Обратите внимание, что мне пришлось использовать
theme_classic()
здесь, потому что в противном случае сетки перекрывались бы, что еще больше затрудняло бы выполнение этой задачи.2. Потребовалось несколько лет, чтобы убедить
ggplot2
авторов дополнитьsec_axis
его сюжеты, в основном по той причине, что наличие двух осей с разными единицами может слишком легко сбить с толку. Ваша «измененная вручную версия» (по моему мнению) — это именно та путаница, о которой они говорили: в вертикальном размещении между красными и синими точками подразумевается релевантность. Можно ли это сделать? Возможно, хотя линии осей, вероятно, придется рисовать вручную, и все координаты нужно будет нормализовать с помощью переопределенных вручную меток оси.3. Сказав это, я предполагаю, что грани и
patchwork
для меня гораздо яснее. Вы уже выполняетеpatchwork
свою часть, я предлагаю добавить содержащие блоки фасеток, которые четко разделяли бы эти два аспекта. Если это то, чего вы не хотите, и вы хотите, чтобы синие/красные точки смешивались, тогда (опять же, имо) потребуется много объяснений, чтобы оправдать это таким образом. (Субъективно, я признаю.)4. Спасибо за ответ! В моей области (палеоцеанография) у нас есть много различных типов данных, которые генерируются для одних и тех же интервалов глубины/возраста (обычно по оси x). Часто мы хотим изучить, показывают ли восстановленные температуры те же самые закономерности, что и в разных прокси, например, для CO2. Таким образом, это совершенно разные оси y с разными значениями, но мы хотим поместить их рядом друг с другом, чтобы лучше визуально сравнить узоры. См., например .
5. Или, возможно, другой пример изображения . Но у них у всех есть коробки вокруг… хммм
Ответ №1:
Я вижу, что r2evans уже дал вам предупреждения, которые следует учитывать каждый раз, когда можно подумать, что вторичная ось решит ваши проблемы. Я согласен с ними, однако, это не значит, что этого нельзя сделать.
Пока вы можете думать о преобразовании, и оно обратное, вы, вероятно, могли бы сделать это с помощью вторичных осей (не путать с «вы должны это сделать»). Усеченный вид оси можно воспроизвести с ggh4x::axis_truncated()
помощью (отказ от ответственности, я являюсь автором этой функции).
В приведенном ниже примере преобразование для вторичной оси -x * 0.5
, таким образом, является обратным - x / 0.5
, но, вероятно, вы можете сделать это лучше в соответствии с вашими потребностями.
library(ggplot2)
library(ggh4x)
set.seed(123)
dat <- tibble::tibble(a = 1:10,
b = c(0, 2, 5, 8, 5, 4, 6, 4, 3, 2),
c = -stats::rnorm(10, b, 3),
d = sample(letters[1:3], 10, TRUE))
ggplot(dat, aes(a))
geom_point(aes(y = b, colour = "b"))
geom_point(aes(y = -c * 0.5, colour = "c"))
scale_y_continuous(
position = "right", breaks = seq(0, 8, by = 2),
guide = guide_axis_truncated(),
name = "B is awesome",
sec.axis = sec_axis(
trans = ~ -.x/0.5, breaks = c(0, -5, -10),
guide = guide_axis_truncated(trunc_lower = -Inf),
name = "C is inversely related to B"
)
)
scale_colour_manual(values = c("indianred", "steelblue"))
theme_classic()
theme(
axis.title.y.left = element_text(colour = "steelblue"),
axis.title.y.right = element_text(colour = "indianred")
)
Создано 2021-07-09 пакетом reprex (v1.0.0)
Вероятно, вы можете немного изменить расположение названий осей, установив соответствующие hjust
s.
Комментарии:
1. Спасибо за решение. Это действительно кажется слишком сложным для графиков с >5 панелями, где эти отношения не очень понятны. Я думаю, что либо оставлю их разделенными как есть, либо при желании вручную настрою их в inkscape.