【问题标题】:How does `geom_abline()` not affect the x and y scales?`geom_abline()` 如何不影响 x 和 y 比例?
【发布时间】:2021-10-20 14:44:42
【问题描述】:

有谁知道geom_abline() 中的哪个参数不影响 x 和 y 比例?

函数draw_panel() w/i GeomAbline 获取基础“范围”,但该线通常应该位于原始比例之外:

GeomAbline <- ggproto("GeomAbline", Geom,
  draw_panel = function(data, panel_params, coord) {
    ranges <- coord$backtransform_range(panel_params)

    data$x    <- ranges$x[1]
    data$xend <- ranges$x[2]
    data$y    <- ranges$x[1] * data$slope + data$intercept
    data$yend <- ranges$x[2] * data$slope + data$intercept

    GeomSegment$draw_panel(unique(data), panel_params, coord)
  },

  default_aes = aes(colour = "black", size = 0.5, linetype = 1, alpha = NA),
  required_aes = c("slope", "intercept"),

  draw_key = draw_key_abline
)

我的猜测是geom_abline()ggplot2:layer() 中设置的参数/函数ggplot2::StatIdentityggplot2::PositionIdentity。但我不明白这是如何工作的?我的动机是写一个新的geom_*,它也不会影响 x 和 y 比例。

【问题讨论】:

  • geom_abline() 的构造函数将数据重新参数化为不具有与 x 或 y 比例 here 相关的任何美学。请注意slopeintercept 不会出现在scale_x_continuous()$aesthetics 中(y 相同)。
  • 感谢您的正确回答。如果您想将其写为答案,我当然会接受。我不知道只有某些美学会影响 x/y 缩放。你知道,是否可以添加额外的美学考虑,或者是否有办法告诉某个 geom_*() 不影响缩放?
  • 我不确定是否可以在不编写自定义比例构造函数的情况下添加额外的位置美学。我不知道如何将一个层排除在参与规模训练之外。我认为比例控制这个而不是层,所以我不知道层的选择退出方法。
  • 好的,谢谢!仍然是一个非常有帮助的评论。我发现了一个非常尴尬的解决方法。我有两个自定义的stat_*()geom_*(),其中stat_*() 使用required_aes = c("x", "y") 但返回c("x_noaes", "y_noaes")。后者相当于geom_*() 中使用的required_aes。因此,我不需要新的映射,但比例不受我的geom_*() 的影响。

标签: r ggplot2 ggproto


【解决方案1】:

根据@teunbrand 的评论,解决方法如下:

ggplot2::scale_x_continuous() 内部,只有以下美学会影响 x 缩放:c("x", "xmin", "xmax", "xend", "xintercept", "xmin_final", "xmax_final", "xlower", "xmiddle", "xupper", "x0")。但是,由于geom_abline() 不包含任何这些美学,因此比例不受影响。

这同样适用于 y 缩放。顺便说一句,变量对应于ggplot2:::ggplot_global$x_aesggplot2:::ggplot_global$y_aes中的字符,但我不知道这些没有使用。

为了说明,我重写了geom_point(),但带有美学c("x_new", "y")

geom_my_point <- function(mapping = NULL, data = NULL, stat = "identity",
                            position = "identity", na.rm = FALSE,
                            show.legend = NA, inherit.aes = TRUE, ...) {
  ggplot2::layer(
    geom = GeomMyPoint, mapping = mapping,
    data = data, stat = stat, position = position,
    show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)
  )
}


GeomMyPoint <- ggplot2::ggproto("GeomMyPoint", ggplot2::GeomPoint,
  required_aes = c("x_new", "y"),
  
  draw_panel = function(data, panel_scales, coord) {
    if (is.character(data$shape)) {
      data$shape <- translate_shape_string(data$shape)
    }

    ## Transform the data first
    coords <- coord$transform(data, panel_scales)

    ## Construct a grid grob
    grid::pointsGrob(
      x = coords$x_new,
      y = coords$y,
      pch = coords$shape,
      gp = grid::gpar(
        col = alpha(coords$colour, coords$alpha),
        fill = alpha(coords$fill, coords$alpha),
        fontsize = coords$size * ggplot2::.pt + coords$stroke * ggplot2::.stroke / 2,
        lwd = coords$stroke * ggplot2::.stroke / 2
      )
    )
  }
)

没有x审美的geom_my_point()的输出对应图“gg2”;因此红点不会影响 x 比例:

d <- data.frame(x = runif(200))
d$y <- 1 * d$x + rnorm(200, 0, 0.2)
d$x2 <- d$x * 2

require("ggplot2")
gg1 <- ggplot(d) + geom_point(aes(x, y)) + geom_point(aes(x = x2, y = y), col = 2) + ggtitle("gg1")
gg2 <- ggplot(d) + geom_point(aes(x, y)) + geom_my_point(aes(x_new = x2, y = y), col = 2) + ggtitle("gg2")

【讨论】:

  • 这里讨论了为什么不使用全局设置的这些未知原因:github.com/tidyverse/ggplot2/issues/4135。 TL;DR 这是一个实现细节。
  • 感谢您的链接。好的,所以它基本上是计划好的,但尚未实施(而不是他们的待办事项;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多