Как построить точки с двумя разными диапазонами оси Y на одной панели на одной оси X?

Я пытаюсь создать диаграмму рассеяния, используя ggplot, которая разделяет ось X, но имеет ось Y с двумя разными масштабами.

Нижняя часть оси Y имеет три шкалы от 0% до 0,1%, затем от 0,1% до 1% и, наконец, регулярные интервалы на 10%.

Пример отсюда:

Есть ли способ создать что-то подобное в R, используя ggplot? Буду ли я изменять оси? Наложение нескольких графиков на одну панель? Или что-то другое?

1 ответ

Решение

Обычно прерывистые оси не рекомендуются в ggplot2 по причинам, рассмотренным в этом вопросе. Хэдли Уикхэм (создатель ggplot2) объясняет здесь:

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

Однако это действительно возможно! Вы должны создать собственное преобразование оси, которое не для слабонервных.

Вот пример. Предположим, у нас есть данные, где y находится в лог-нормальном масштабе.

set.seed(20)
dat <- data.frame(x = c(0, rnorm(50)), y = c(0, exp(rnorm(50, -2, 1.5))))
ggplot(dat, aes(x, y)) + geom_point()

оригинал

Многие точки сгущены в нижней части: предположим, я хотел поместить все значения ниже 1 в логарифмическую шкалу, а значения выше 1 в линейную шкалу. Таким образом, я создаю собственное преобразование, называемое combine_trans, который объединяет логарифмическую шкалу с линейной шкалой (это не совсем то , что делает ваш пример графика выше, так как он, кажется, идет к 0, но, вероятно, достаточно близко)

combine_trans <- function(breakpoint, tr1, tr2,
                          br1 = tr1$breaks,
                          br2 = tr2$breaks) {
    # combine two transformations.
    # can also be given functions to determine tick marks
    trans_breakpoint <- tr1$transform(breakpoint)
    trans <- function(x) {
        # choose which transformation to apply
        ifelse(x < breakpoint,
               tr1$transform(x),
               tr2$transform(x - breakpoint) - trans_breakpoint)
    }
    inv <- function(x) {
        # inverse of both transformations
        ifelse(x < trans_breakpoint,
               tr1$inverse(x),
               breakpoint + tr2$inverse(x + trans_breakpoint))
    }
    br <- function(x) {
        # combine break choices from both scales
        br1 <- br1(c(x[x < breakpoint], breakpoint))
        br2 <- br2(c(breakpoint, max(x[x > breakpoint])))
        br <- c(br1, br2)
        br[br > 0]
    }
    # combine domains
    dom <- c(max(tr1$domain[1], tr2$domain[1]), min(tr1$domain[2], tr2$domain[2]))
    trans_new("combined", trans, inv, breaks = br, domain = dom)
}

# combine log10 transformation and identity transformation
combined <- combine_trans(1, log10_trans(), identity_trans())

ggplot(dat, aes(x, y)) +
    geom_point() +
    scale_y_continuous(trans = combined) +
    geom_hline(yintercept = 1, lty = 2)

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

Вы можете увидеть еще один пример прерывистого преобразования здесь, которое вводит простой разрыв в оси.

Обратите внимание, что этот код сложен и может потребовать настройки. Более того, это все еще несколько вводит в заблуждение: в общем, вам, вероятно, следует просто разделить ваши данные на отдельные графики или поместить все в масштаб журнала. Тем не менее, стоит знать, что ggplot2 дает вам доступ к этим инструментам, даже если вы "выстрелите себе в ногу" с ними!

Другие вопросы по тегам