COO*_*ash 12 r ggplot2 coordinate-transformation axis-labels
编辑
似乎sec_axisggplot2 3.1.0中的错误行为是一个错误.这已得到开发人员的认可,他们正在修复(参见 GitHub上的线程).
目标
我有一个图形,其中y轴的范围从0到1.我想添加一个从0到0.5的辅助y轴(所以正好是主y轴的一半值).到目前为止没问题.
使问题复杂化的是,我对y轴进行了自定义变换,其中y轴的一部分线性显示,其余部分以对数方式显示(参见下面的代码示例).供参考,请参阅此文章或本文.
问题
这使用ggplot2版本3.0.0非常漂亮,但使用最新版本(3.1.0)不再有效.见下面的例子.我不知道如何在最新版本中修复它.
来自更改日志:
当应用于日志转换后的比例时,sec_axis()和dup_axis()现在返回辅助轴的适当中断
在混合变换的y轴的情况下,这种新功能似乎打破了.
可重复的例子
以下是使用ggplot2的最新版本(3.1.0)的示例:
devtools::install_github("tidyverse/ggplot2")
Run Code Online (Sandbox Code Playgroud)
这会产生以下情节:
次级y轴的标记对于轴的对数部分(低于0.5)是正确的,但对于轴的线性部分是错误的.
如果我使用安装ggplot2 3.0.0
library(ggplot2)
library(scales)
#-------------------------------------------------------------------------------------------------------
# Custom y-axis
#-------------------------------------------------------------------------------------------------------
magnify_trans_log <- function(interval_low = 0.05, interval_high = 1, reducer = 0.05, reducer2 = 8) {
trans <- Vectorize(function(x, i_low = interval_low, i_high = interval_high, r = reducer, r2 = reducer2) {
if(is.na(x) || (x >= i_low & x <= i_high)) {
x
} else if(x < i_low & !is.na(x)) {
(log10(x / r)/r2 + i_low)
} else {
log10((x - i_high) / r + i_high)/r2
}
})
inv <- Vectorize(function(x, i_low = interval_low, i_high = interval_high, r = reducer, r2 = reducer2) {
if(is.na(x) || (x >= i_low & x <= i_high)) {
x
} else if(x < i_low & !is.na(x)) {
10^(-(i_low - x)*r2)*r
} else {
i_high + 10^(x*r2)*r - i_high*r
}
})
trans_new(name = 'customlog', transform = trans, inverse = inv, domain = c(1e-16, Inf))
}
#-------------------------------------------------------------------------------------------------------
# Create data
#-------------------------------------------------------------------------------------------------------
x <- seq(-1, 1, length.out = 1000)
y <- c(x[x<0] + 1, -x[x>0] + 1)
dat <- data.frame(
x = x
, y = y
)
#-------------------------------------------------------------------------------------------------------
# Plot using ggplot2
#-------------------------------------------------------------------------------------------------------
theme_set(theme_bw())
ggplot(dat, aes(x = x, y = y)) +
geom_line(size = 1) +
scale_y_continuous(
, trans = magnify_trans_log(interval_low = 0.5, interval_high = 1, reducer = 0.5, reducer2 = 8)
, breaks = c(0.001, 0.01, 0.1, 0.5, 0.6, 0.7, 0.8, 0.9, 1)
, sec.axis = sec_axis(
trans = ~.*(1/2)
, breaks = c(0.001, 0.01, 0.1, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5)
)
) + theme(
axis.text.y=element_text(colour = "black", size=15)
)
Run Code Online (Sandbox Code Playgroud)
并运行与上面相同的代码,我得到以下图表,这是我想要的:
问题
sec_axis在这种情况下,是否有其他替代方案可行?这是一个适用于ggplot23.1.0版本的解决方案,sec_axis()只需创建一个图表.我们仍然sec_axis()像以前一样使用,但是不是将次要轴的变换缩放1/2,而是反向缩放次轴上的断点.
在这种特殊情况下,我们相当容易,因为我们只需要将所需的断点位置乘以2.然后,为图形的对数和线性部分正确定位得到的断点.在那之后,我们所要做的就是将休息时间重新标记为所需的值.ggplot2当我们自己进行缩放时,这会避免在必须缩放混合变换时被中断位置弄糊涂的问题.原油,但有效.
不幸的是,目前似乎没有任何其他替代方案sec_axis()(除此之外没有dup_axis()什么帮助).不过,我很高兴在这一点上得到纠正!祝你好运,我希望这个解决方案对您有所帮助!
这是代码:
# Vector of desired breakpoints for secondary axis
sec_breaks <- c(0.001, 0.01, 0.1, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5)
# Vector of scaled breakpoints that we will actually add to the plot
scaled_breaks <- 2 * sec_breaks
ggplot(data = dat, aes(x = x, y = y)) +
geom_line(size = 1) +
scale_y_continuous(trans = magnify_trans_log(interval_low = 0.5,
interval_high = 1,
reducer = 0.5,
reducer2 = 8),
breaks = c(0.001, 0.01, 0.1, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
sec.axis = sec_axis(trans = ~.,
breaks = scaled_breaks,
labels = sprintf("%.3f", sec_breaks))) +
theme_bw() +
theme(axis.text.y=element_text(colour = "black", size=15))
Run Code Online (Sandbox Code Playgroud)
由此产生的情节: