【问题标题】:How to add a point on the y-intercept (y-axis) using ggplot2如何使用 ggplot2 在 y 截距(y 轴)上添加一个点
【发布时间】:2020-08-04 11:42:04
【问题描述】:

我有一个散点图,其中 y 轴缩放在某个点发生变化,以绘制具有一些极值的数据。我正在尝试在 y 轴上添加某种视觉提示,表明该点的缩放比例发生了变化。

这是一个情节的例子

library(scales)
library(ggplot2)

set.seed(104)

ggdata <- data.frame('x' = rep('a',100),
                     'y' = c(runif(90, 0, 20), runif(10, 90, 100)))

transformation <- trans_new(
  "my_transformation", 
  transform = function(x) ifelse(x <= 30, x / 5, (x - 30) / 20 + 30 / 5),
  inverse = function(x) ifelse(x <= 30 / 5, x * 5, (x - 30 / 5) * 20 + 30)
)

ggplot(data = ggdata) + 
  geom_jitter(aes(x = x, y = y)) +
  scale_y_continuous(trans = transformation, breaks = c(0, 10, 20, 30, 50, 70, 90, 110))  

我想在 y 轴上为“刻度 30”添加一些标记以更改比例。

我想在轴上添加一个双勾,但没有看起来像双线的linetype。产品应该类似于this。我知道像 scale_y_log10 这样的转换,但我更愿意使用随数据动态变化的自定义缩放。

编辑:根据@Tjebo 的建议,我使用annotate 将“=”添加到y 轴断点:

library(scales)
library(ggplot2)

set.seed(104)

ggdata <- data.frame('x' = rep('a',100),
                     'y' = c(runif(90, 0, 20), runif(10, 90, 100)))

transformation <- trans_new(
  "my_transformation", 
  transform = function(x) ifelse(x <= 30, x / 5, (x - 30) / 20 + 30 / 5),
  inverse = function(x) ifelse(x <= 30 / 5, x * 5, (x - 30 / 5) * 20 + 30)
)

mybreaks <- c(0, 10, 20, 30, 50, 70, 90, 110)
tick_linetype <- rep("solid", length(mybreaks))
tick_linetype[4] <- "blank"

ggplot(data = ggdata) + 
  geom_jitter(aes(x = x, y = y)) +
  annotate(geom = "point", shape = "=", x = -Inf, y = 30, size = 3) +
  scale_y_continuous(trans = transformation, breaks = mybreaks) +
  theme(axis.ticks.y = element_line(linetype = tick_linetype)) + 
  coord_cartesian(clip = 'off')

【问题讨论】:

  • 以下是一些相关主题:stackoverflow.com/questions/7194688/…
  • @bs93 谢谢你的链接。我猜想产生两个有&没有极值的图可能是一个解决方案。不过,我希望看到一种将所有信息合并到一个情节中的方法。我正在处理遗传数据,所以我会有数万个数据,所以该表不是一种有效的方法。准确地说,我正在使用的“散点图”是曼哈顿图,我希望看到较低 -log10(pval) 的分布以及极值

标签: r ggplot2 plot data-visualization scatter-plot


【解决方案1】:

我想在轴上加一个双勾,但没有 看起来像双线的线型。

您可以使用任何字符作为点形状。还有等号、反斜杠等。

例如:

library(scales)
library(ggplot2)

set.seed(104)

ggdata <- data.frame('x' = rep('a',100),
                     'y' = c(runif(90, 0, 20), runif(10, 90, 100)))

transformation <- trans_new(
  "my_transformation", 
  transform = function(x) ifelse(x <= 30, x / 5, (x - 30) / 20 + 30 / 5),
  inverse = function(x) ifelse(x <= 30 / 5, x * 5, (x - 30 / 5) * 20 + 30)
)

ggplot(data = ggdata) + 
  geom_jitter(aes(x = x, y = y)) +
  annotate(geom = "point", shape = "=", x = -Inf, y = 30, size = 8, color = 'red') +
  scale_y_continuous(trans = transformation, breaks = c(0, 10, 20, 30, 50, 70, 90, 110))+
  coord_cartesian(clip = 'off')

我删除了剪辑,但您也可以保留它。颜色只是为了突出显示而选择的。

或者,更好的是,使用文本注释。然后你也可以改变角度——很好。

ggplot(data = ggdata) +
  geom_jitter(aes(x = x, y = y)) +
  annotate(geom = "text", label = "=", x = -Inf, y = 30, size = 8, color = "red", angle = 45) +
  scale_y_continuous(trans = transformation, breaks = c(0, 10, 20, 30, 50, 70, 90, 110)) +
  coord_cartesian(clip = "off")

reprex package (v0.3.0) 于 2020 年 4 月 21 日创建

【讨论】:

  • 好的,谢谢!这是最接近我一直在寻找的。我不知道我可以将annotate() 中的x 设置为-Inf,更不用说包括它不会改变整体x 比例。
【解决方案2】:

此解决方案应该有助于您希望轴的外观。 FWIW 我想告诫不要打破轴,除非你明确告诉你的听众。在下面的代码中,我创建了两个图,一个用于 30 以下的数据,另一个用于极值点(并删除其 x 轴和标签)。然后我使用 plot.margin 设置绘图边距,以便当我将它们放入 grid.arrange 时它们会重叠一点。您可能必须弄乱边距才能使标签对齐。

library(scales)
library(ggplot2)
library(gridExtra)
set.seed(104)

ggdata <- data.frame('x' = rep('a',100),
                     'y' = c(runif(90, 0, 20), runif(10, 90, 100)))

p1 <- ggplot(data = ggdata) + 
  geom_jitter(aes(x = x, y = y)) +
  scale_y_continuous(breaks = seq(0,30,5), limits = c(0,30))+
  theme(plot.margin=unit(c(0,.83,0,1), "cm")) 




p2 <- ggplot(data = ggdata) + 
  geom_jitter(aes(x = x, y = y)) +
  scale_y_continuous( breaks = seq(60,100,10), limits = c(60,100)) +
  scale_x_discrete()+
  theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        plot.margin=unit(c(0,1,-0.1,1), "cm"))


grid.arrange(p2,p1)

【讨论】:

    【解决方案3】:

    我无法得到您链接到的确切外观,但也许其中一些想法对您有用。

    您可以将指定的值设为次要中断,并仅在次要中断处添加一行(这里我无法选择 20 的确切值,因为那已经是一个重大中断,但也许您可以使用数字来得到你喜欢的东西):

    ggplot(data = ggdata) + 
      geom_jitter(aes(x = x, y = y)) +
      scale_y_continuous(trans = transformation, minor_breaks=20.05,breaks = c(0, 10,20, 30, 50, 70, 90, 110))+
      theme(
        panel.grid.minor.y = element_line(1)
      )
    

    另一种选择是自行更改标签。这里我将() 20 值加粗并包裹起来,但您也可以添加其他符号:

    ggplot(data = ggdata) + 
      geom_jitter(aes(x = x, y = y)) +
      scale_y_continuous(trans = transformation, minor_breaks = c(0, 10, 20, 30, 50, 70, 90, 110),
                           breaks  = c(0, 10, 20, 30, 50, 70, 90, 110), labels=c(0, 10, expression(bold(("20"))), 30, 50, 70, 90, 110))
    

    您可以在绘图中添加一个片段,这不是最漂亮的选项,因为 x 轴不是连续的,但也许它会激发灵感:

    ggplot(data = ggdata) + 
      geom_jitter(aes(x = x, y = y)) +
      scale_y_continuous(trans = transformation, breaks = c(0, 10, 20, 30, 50, 70, 90, 110))+
      geom_segment(aes(x=-.01,y=19.5,xend=.01,yend=20.5),size=1.5)
    

    也许您也可以只遮蔽绘图的底部(或顶部)部分:

    ggplot(data = ggdata,aes(x = x, y = y)) + 
      geom_jitter() +
      scale_y_continuous(trans = transformation,breaks = c(0, 10,20, 30, 50, 70, 90, 110))+
      annotate("rect", xmin = .4, xmax = 1.6, ymin = 0, ymax = 21,
               alpha = .2)
    

    【讨论】:

    • 感谢您的想法,迪伦。事实上,我们也有类似的想法 :) !添加一条水平线可能会引起一些混乱,因为我已经用虚线表示 p 值。现在,我在“断点”处将轴涂成红色。虽然不能直观的说那个时候尺度发生了变化,但还是很突出的。我仍然认为在轴上带有“/”或“X”标记会更具视觉冲击力。
    • @J.Lee,我刚刚有了一个额外的想法,您可以在其中遮蔽一个区域。这与剧情中的其他台词等可能不会太难看。查看修改后的答案。
    猜你喜欢
    • 1970-01-01
    • 2017-09-23
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多