ggplot2 3.1.0中的自定义y轴比例和次要y轴标签 [英] Custom y-axis scale and secondary y-axis labels in ggplot2 3.1.0

查看:79
本文介绍了ggplot2 3.1.0中的自定义y轴比例和次要y轴标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑2

ggplot2-package的当前开发版本确实解决了我下面的问题中提到的错误.使用

The current developmental version of the ggplot2-package does solve the bug mentioned in my question below. Install the dev version using

devtools::install_github("tidyverse/ggplot2")

修改

似乎ggplot2 3.1.0中sec_axis的错误行为是一个错误.开发人员已经意识到了这一点,他们正在努力解决(请参见 thread GitHub).

It seems as the faulty behaviour of sec_axis in ggplot2 3.1.0 is a bug. This has been recognized by the devs and they are working on a fix (see thread on GitHub).

目标

我有一个图形,其中y轴的范围是0到1.我想添加一个辅助y轴的范围是0到0.5(正好是主要y轴值的一半).到目前为止没有问题.

I have a graphic where the y-axis ranges from 0 to 1. I'd like to add a secondary y-axis that ranges from 0 to 0.5 (so exactly half the values of the primary y-axis). So far no problem.

使问题复杂化的是,我对y轴进行了自定义转换,其中y轴的一部分以线性方式显示,其余部分以对数方式显示(请参见下面的示例代码).作为参考,请参见这篇文章

What complicates the matter is that I have a custom transformation for the y-axis where part of the y-axis is displayed linearly and the rest logarithmically (see code below for an example). For reference, see this post or this one.

问题

使用ggplot2版本3.0.0可以很好地工作,但是使用最新版本(3.1.0)不再有效.请参见下面的示例.我不知道如何在最新版本中修复它.

This worked beautifully using ggplot2 version 3.0.0 but doesn't work anymore using the newest version (3.1.0). See example below. I don't know how to fix it in the newest version.

来自更改日志:

sec_axis()和dup_axis()现在返回相应的中断 二次轴应用于对数转换标度

sec_axis() and dup_axis() now return appropriate breaks for the secondary axis when applied to log transformed scales

在混合变换的y轴的情况下,此新功能似乎无法使用.

This new functionality seems to break in the case of mixed-transformed y-axes.

可复制的示例

以下是使用ggplot2最新版本(3.1.0)的示例:

Here is an example using the newest version (3.1.0) of ggplot2:

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)
  )

这将产生以下情节:

第二个y轴的标签对于该轴的对数部分正确(低于0.5),但对于该轴的线性部分是错误的.

The labelling of the secondary y-axis is correct for the logarithmic part of the axis (below 0.5) but wrong for the linear part of the axis.

如果我使用安装ggp​​lot2 3.0.0

If I install ggplot2 3.0.0 using

require(devtools)
install_version("ggplot2", version = "3.0.0", repos = "http://cran.us.r-project.org")

并运行与上面相同的代码,我得到下面的图,这就是我想要的:

and run the same code as above, I get the following graph, which is what I want:

问题

  1. 是否有办法在最新版本的ggplot2(3.1.0)中解决此问题?理想情况下,我要避免使用旧版本的ggplot2(即3.0.0).
  2. 在这种情况下,是否可以使用sec_axis的替代方法?
  1. Is there a way to fix this issue in the newest version of ggplot2 (3.1.0)? Ideally, I would like to refrain from using an older version of ggplot2 (i.e. 3.0.0).
  2. Are there alternatives to sec_axis that would work in this case?

推荐答案

以下是使用sec_axis()ggplot2版本3.1.0配合使用的解决方案,只需要创建一个图即可.我们仍然像以前一样使用sec_axis(),而不是将辅助轴的转换比例缩放为1/2,而我们相反地对辅助轴上的中断点进行比例缩放.

Here is a solution that works with ggplot2 version 3.1.0 using sec_axis(), and which only requires creating a single plot. We still use sec_axis() as before, but rather than scaling the transform by 1/2 for the secondary axis, we inverse scale the breaks on the secondary axis instead.

在这种特殊情况下,我们非常容易,因为我们只需要将所需的断点位置乘以2.然后,可以对图形的对数和线性部分正确地定位得到的断点.之后,我们要做的就是用所需的值重新标记这些中断.这回避了ggplot2在必须缩放混合变换时会被中断位置弄糊涂的问题,因为我们自己进行缩放.粗暴,但有效.

In this particular case we have it fairly easy, as we simply have to multiply the desired breakpoint positions by 2. The resulting breakpoints are then correctly positioned for both the logarithmic and linear portions of your graph. After that, all we have to do is to relabel the breaks with their desired values. This sidesteps the problem of ggplot2 getting confused by the break placement when it has to scale a mixed transform, as we do the scaling ourselves. Crude, but effective.

不幸的是,目前看来,除了dup_axis()之外,没有其他任何替代sec_axis()的方法(对dup_axis()的帮助不大).不过,我很乐意在这一点上得到纠正!祝你好运,我希望这个解决方案对您有帮助!

Unfortunately, at the present moment there don't appear to be any other alternatives to sec_axis() (other than dup_axis() which will be of little help here). I'd be happy to be corrected on this point, however! Good luck, and I hope this solution proves helpful for you!

以下是代码:

# 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))

以及生成的图:

这篇关于ggplot2 3.1.0中的自定义y轴比例和次要y轴标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆