每当向 ggplot 添加垂直/水平线时,如何向 x / y 轴添加标签?

una*_*der 1 r ggplot2 geom-hline geom-vline

x 轴和 y 轴根据 ggplot 设置的特定间隔进行标记。

如果将水平线或垂直线添加到图中,目标是在该线的精确值处标记 x 或 y 轴。

如何才能做到这一点?

All*_*ron 5

这并不完全简单,但这是可能的。我可能会使用这两个小函数来自动化棘手的部分:

add_x_break <- function(plot, xval) {
  
  p2 <- ggplot_build(plot)
  breaks <- p2$layout$panel_params[[1]]$x$breaks
  breaks <- breaks[!is.na(breaks)]
  
  plot +
    geom_vline(xintercept = xval) +
    scale_x_continuous(breaks = sort(c(xval, breaks)))
}

add_y_break <- function(plot, yval) {
  
  p2 <- ggplot_build(plot)
  breaks <- p2$layout$panel_params[[1]]$y$breaks
  breaks <- breaks[!is.na(breaks)]
  
  plot +
    geom_hline(yintercept = yval) +
    scale_y_continuous(breaks = sort(c(yval, breaks)))
}
Run Code Online (Sandbox Code Playgroud)

这些会像这样工作。从基本情节开始:

library(ggplot2)

set.seed(1)

df <- data.frame(x = 1:10, y = runif(10))

p <- ggplot(df, aes(x, y)) + 
  geom_point() +
  ylim(0, 1)

p
Run Code Online (Sandbox Code Playgroud)

添加一条垂直线add_x_break

p <- add_x_break(p, 6.34)

p
Run Code Online (Sandbox Code Playgroud)

添加一条水平线add_y_break

p <- add_y_break(p, 0.333)
#> Scale for 'y' is already present. Adding another scale for 'y', which will
#> replace the existing scale.

p
Run Code Online (Sandbox Code Playgroud)


附录

如果由于某种原因您没有生成绘图的代码,或者 vline 已经存在,您可以使用以下函数提取 xintercept 并将其添加到轴中断处:

add_x_intercepts <- function(p) {
  
  p2 <- ggplot_build(p)
  breaks <- p2$layout$panel_params[[1]]$x$breaks
  breaks <- breaks[!is.na(breaks)]
  
  vals <- unlist(lapply(seq_along(p$layers), function(x) {
    d <- layer_data(p, x)
    if('xintercept' %in% names(d)) d$xintercept else numeric()
  }))
  
  p + scale_x_continuous(breaks = sort(c(vals, breaks)))
}
Run Code Online (Sandbox Code Playgroud)

因此,例如:

set.seed(1)

df <- data.frame(x = 1:10, y = runif(10))

p <- ggplot(df, aes(x, y)) + 
  geom_point() +
  geom_vline(xintercept = 6.34) +
  ylim(0, 1)

p
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

那么我们可以这样做:

add_x_intercepts(p)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

的 y 截距geom_hline可以通过类似的方式获得,这应该可以从代码中看出add_x_intercepts