Проблема здесь связана с сочетанием двух факторов:
Ваши значения по оси x (после преобразования) попадают в диапазон [-1, 0], поэтому любое расширение (аддитивное или мультипликативное) подтолкнет окончательный диапазон к положительным и отрицательным значениям.
Ваше пользовательское преобразование не является однозначным в [<some negative number>, <some positive number>]
регионе.
Как это произошло
Где-то глубоко внутри всего кода, используемого для создания объекта ggplot (вы можете запустить ggplot2:::ggplot_build.ggplot
перед печатью графика и перейти к layout$setup_panel_params()
, но я не рекомендую это для случайных пользователей ... кроличья нора проходит очень глубоко там), разрывы по оси X рассчитываются следующим образом:
- Получить пределы для преобразованных значений (для
c(1, .5, .1, .01, .001, 0)
в вопросе это будет (-1, 0)
).
- Добавьте расширение к пределам, если применимо (расширение по умолчанию для непрерывной оси составляет 5% с обеих сторон, поэтому ограничения становятся
(-1.05, 0.05)
).
- Применение обратного преобразования к пределам (взятие
x^4
для пределов дает (1.215506, 0.000006)
).
- Примените преобразование для обоих введенных пользователем перерывов и пределов (для перерывов
c(1, .5, .1, .01, .001, 0)
становится (-1.0000000, ..., 0.0000000)
, но для пределов (1.215506, 0.000006)
теперь становится (-1.05, -0.05)
, что на уже , чем (-1.05, 0.05)
).
- Разрывы за пределами диапазона ограничения сбрасываются (поскольку ограничения теперь останавливаются на -0,05, разрыв на 0 сбрасывается).
Как обойти это
Вы можете изменить свое преобразование с помощью sign()
, чтобы сохранить положительные / отрицательные значения, так, чтобы преобразование было один к одному во всем диапазоне, как это было предложено Хэдли в дискуссии по проблеме GH, которую вы связали , Например:
# original
forth_root_trans_rev <- scales::trans_new(
name = "sign_fourth_root_rev",
transform = function (x) { - abs(x)^(1/4) },
inverse = function (x) { x^4 }
)
# new
forth_root_trans_rev2 <- scales::trans_new(
name = "sign_fourth_root_rev",
transform = function (x) { -sign(x) * abs(x)^(1/4) },
inverse = function (x) { -sign(x) * abs(x)^4 }
)
library(dplyr)
library(tidyr)
# comparison of two transformations
# y1 shows a one-to-one mapping in either (-Inf, 0] or [0, Inf) but not both;
# y2 shows a one-to-one mapping in (-Inf, Inf)
data.frame(x = seq(-1, 1, 0.01)) %>%
mutate(y1 = x %>% forth_root_trans_rev$transform() %>% forth_root_trans_rev$inverse(),
y2 = x %>% forth_root_trans_rev2$transform() %>% forth_root_trans_rev2$inverse()) %>%
gather(trans, y, -x) %>%
ggplot(aes(x, y, colour = trans)) +
geom_line() +
geom_vline(xintercept = 0, linetype = "dashed") +
facet_wrap(~trans)

Использование
p <- ggplot(ds, aes(x = myx, y = myy)) +
geom_line() +
geom_point() +
theme(panel.grid.minor = element_blank())
p +
scale_x_continuous(
trans = forth_root_trans_rev2,
breaks = sort(unique(ds$myx))
)
p +
scale_x_continuous(
trans = forth_root_trans_rev2,
breaks = sort(unique(ds$myx)),
expand = expand_scale(mult = c(.1, .6)) # with different expansion factor, if desired
)
