R/ggplot2:从散点图中塌陷或移除y轴段 [英] R/ggplot2: Collapse or remove segment of y-axis from scatter-plot

查看:78
本文介绍了R/ggplot2:从散点图中塌陷或移除y轴段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用ggplot2在R中绘制散点图,其中y轴的中心被折叠或移除,因为那里没有数据.我是在下面的photoshop中完成的,但是有没有办法用ggplot创建类似的图呢? 这是具有连续范围的数据:

I'm trying to make a scatter plot in R with ggplot2, where the middle of the y-axis is collapsed or removed, because there is no data there. I did it in photoshop below, but is there a way to create a similar plot with ggplot? This is the data with a continuous scale:

但是我试图做这样的事情:

But I'm trying to make something like this:

这是代码:

ggplot(data=distance_data) +
    geom_point(
        aes(
            x = mdistance,
            y = maxZ,
            shape = factor(subj),
            color = factor(side),
            size = (cSA)
        )
    ) +
    scale_size_continuous(range = c(4, 10)) +
    theme(
        axis.text.x = element_text(colour = "black", size = 15),
        axis.text.y = element_text(colour = "black", size = 15),
        axis.title.x = element_text(colour = "black", size= 20, vjust = 0),
        axis.title.y = element_text(colour = "black", size= 20),
        legend.position = "none"
    ) +
    ylab("Z-score") +
    xlab("Distance")

推荐答案

您可以通过定义坐标变换来做到这一点.一个标准示例是对数坐标,可以使用scale_y_log10()ggplot中实现.

You could do this by defining a coordinate transformation. A standard example are logarithmic coordinates, which can be achieved in ggplot by using scale_y_log10().

但是,您还可以通过向scale_y_continuous()提供trans参数(以及对于scale_x_continuous()类似地)来定义自定义转换函数.为此,可以使用scales包中的函数trans_new().它以变换函数及其逆为参数.

But you can also define custom transformation functions by supplying the trans argument to scale_y_continuous() (and similarly for scale_x_continuous()). To this end, you use the function trans_new() from the scales package. It takes as arguments the transformation function and its inverse.

我首先讨论OP的示例的特殊解决方案,然后说明如何将其推广.

I discuss first a special solution for the OP's example and then also show how this can be generalised.

OP希望缩小-2和2之间的间隔.下面定义了一个函数(及其逆函数),该函数将该间隔缩小4倍:

The OP wants to shrink the interval between -2 and 2. The following defines a function (and its inverse) that shrinks this interval by a factor 4:

library(scales)
trans <- function(x) {
  ifelse(x > 2, x - 1.5, ifelse(x < -2, x + 1.5, x/4))
}
inv <- function(x) {
  ifelse(x > 0.5, x + 1.5, ifelse(x < -0.5, x - 1.5, x*4))
}
my_trans <- trans_new("my_trans", trans, inv)

这定义了转换.为了查看效果,我定义了一些示例数据:

This defines the transformation. To see it in action, I define some sample data:

x_val <- 0:250
y_val <- c(-6:-2, 2:6)
set.seed(1234)
data <- data.frame(x = sample(x_val, 30, replace = TRUE),
                   y = sample(y_val, 30, replace = TRUE))

我首先将其绘制而无需变换:

I first plot it without transformation:

p <- ggplot(data, aes(x, y)) + geom_point()
p + scale_y_continuous(breaks = seq(-6, 6, by = 2))

现在我将scale_y_continuous()用于转换:

p + scale_y_continuous(trans = my_trans,
                       breaks = seq(-6, 6, by = 2))

如果要进行其他转换,则必须更改trans()inv()的定义,然后再次运行trans_new().您必须确保inv()确实是inv()的反函数.我对此进行了如下检查:

If you want another transformation, you have to change the definition of trans() and inv() and run trans_new() again. You have to make sure that inv() is indeed the inverse of inv(). I checked this as follows:

x <- runif(100, -100, 100)
identical(x, trans(inv(x)))
## [1] TRUE

一般解决方案

下面的函数定义了一个转换,您可以在其中选择要压缩的区域的下端和上端以及要使用的因子.它直接返回可以在scale_y_continuous内部使用的trans对象:

library(scales)
squish_trans <- function(from, to, factor) {
  
  trans <- function(x) {
    
    if (any(is.na(x))) return(x)

    # get indices for the relevant regions
    isq <- x > from & x < to
    ito <- x >= to
    
    # apply transformation
    x[isq] <- from + (x[isq] - from)/factor
    x[ito] <- from + (to - from)/factor + (x[ito] - to)
    
    return(x)
  }

  inv <- function(x) {
    
    if (any(is.na(x))) return(x)

    # get indices for the relevant regions
    isq <- x > from & x < from + (to - from)/factor
    ito <- x >= from + (to - from)/factor
    
    # apply transformation
    x[isq] <- from + (x[isq] - from) * factor
    x[ito] <- to + (x[ito] - (from + (to - from)/factor))
    
    return(x)
  }
  
  # return the transformation
  return(trans_new("squished", trans, inv))
}

trans()inv()中的第一行处理使用x = c(NA, NA)调用转换时的情况. (当我最初编写此问题时,ggplot2的版本似乎没有发生这种情况.不幸的是,我不知道此入门版的版本是什么.)

The first line in trans() and inv() handles the case when the transformation is called with x = c(NA, NA). (It seems that this did not happen with the version of ggplot2 when I originally wrote this question. Unfortunately, I don't know with which version this startet.)

现在可以使用此功能方便地从第一部分重做绘图:

This function can now be used to conveniently redo the plot from the first section:

p + scale_y_continuous(trans = squish_trans(-2, 2, 4),
                       breaks = seq(-6, 6, by = 2))

以下示例显示您可以将比例缩放到任意位置,这也适用于除点以外的其他几何图形:

The following example shows that you can squish the scale at an arbitrary position and that this also works for other geoms than points:

df <- data.frame(class = LETTERS[1:4],
                 val = c(1, 2, 101, 102))
ggplot(df, aes(x = class, y = val)) + geom_bar(stat = "identity") +
  scale_y_continuous(trans = squish_trans(3, 100, 50),
                     breaks = c(0, 1, 2, 3, 50, 100, 101, 102))

让我结束发言,强调其他已在评论中提及的内容:这种情节可能会产生误导,应谨慎使用!

Let me close by stressing what other already mentioned in comments: this kind of plot could be misleading and should be used with care!

这篇关于R/ggplot2:从散点图中塌陷或移除y轴段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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