R语言 ggplot -如何绘制一条完美的对角线?

ryoqjall  于 2023-05-26  发布在  其他
关注(0)|答案(2)|浏览(335)

考虑以下两种绘制对角线的方法,此处显示在同一图上:

ggplot(iris,
       aes(x=Petal.Length,
           y=Petal.Width))+
  geom_point()+
  geom_abline() +
  geom_smooth(method = "lm", se = F)

然而,我需要一条线,从图的左下角(除了页边距)到图的右上角(除了页边距)。在这里,我展示了在Paint中绘制的线,以与其他两条线进行比较。

如何绘制这条线,而不必手动计算左下角和右上角的坐标或线的斜率?

p1tboqfb

p1tboqfb1#

有三个限制你可能想要使用。
1.图角(绿色);
1.最后一次突破(红点);
1.实际的xlim和ylim(蓝色点)。

“1.”可以用Allan的annotation_custom答案来实现。对于“2.”和“3.”,我们必须提取限制和中断。这可以通过使用ggplot_build()访问绘图元数据来完成。我创建了自定义函数,以geom_segment友好的格式保存元数据:

get_lims <- function(graph){
  ggplot_build(graph)$layout$panel_params[[1]][c('x.range', 'y.range')] %>%
    flatten() %>%
    set_names(c('x', 'xend', 'y', 'yend'))
}

极限/范围在这些...$x.range...$y.range向量上,我们只是将它们展平,并与geom_segment的参数名称一起保存。

get_breaks <- function(graph){
  ggplot_build(graph)$layout$panel_params[[1]][c('x.sec', 'y.sec')] %>%
    map(~ c(.x$breaks, .x$minor_breaks) %>% na.omit() %>% {c(min(.), max(.))}) %>%
    flatten() %>%
    set_names(c('x', 'xend', 'y', 'yend'))
}

这里,断点信息位于...$x.sec$breaks...$x.sec$minor_breaks向量下(主要和次要断点)。因此,这里的map连接了major和minor(因为它们中的任何一个都可能是第一个/最后一个),省略了NA,并获得了最小值和最大值。然后,我们进行扁平化和重命名。
最后,您可能会对扩展示例中的红线感兴趣,这可以通过手动计算它的abline(紫色线)来实现。
现在来比较这些方法:

g <- ggplot(iris, aes(x=Petal.Length, y=Petal.Width))+
  geom_point() +
  geom_smooth(method = "lm", se = F, color = 'black')

breaks <- get_breaks(g)
b <- (breaks$yend - breaks$y)/(breaks$xend - breaks$x)
a <- breaks$y - b*breaks$x

g +
  annotation_custom(grid::linesGrob(gp = grid::gpar(col = 'green'))) +
  geom_abline(slope = b, intercept = a, color = 'purple') +
  geom_segment(do.call(aes, get_breaks(g)), color = 'red') +
  geom_segment(do.call(aes, get_lims(g)), color = 'blue')

观察结果:这些点是后来添加的。

pieyvz9o

pieyvz9o2#

实际上,使用annotation_customgrid::linesGrob并使用grid::gpar对其进行样式化,可以非常简单地得到一条精确地穿过面板对角线的线

library(ggplot2)

ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
  geom_point() +
  annotation_custom(
    grid::linesGrob(gp = grid::gpar(col = 'red', lty = 2, lwd = 3)))

绘制一条不穿过图的“边缘”的对角线是 * 更 * 困难的(并且定义得不那么好),因为这些实际上不是 * 边缘,而只是图区域的适当扩展。您在输出上绘制的所需直线不是面板上的完美对角线,而是x轴和y轴刻度最外侧断点上的对角线。这些是由ggplot在绘制时从您的数据中计算出来的,并且可以由用户通过scale_*_continuous进行更改,此时您对“正确”对角线的概念可能会发生变化。例如,如果我们改变中断,我们最终会改变表观所需的对角线:

ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
  geom_point() +
  annotate('path', color = 'red', x = c(2.4, 6.2), y = c(0.4, 2.2)) +
  scale_x_continuous(breaks = c(2.4, 6.2)) +
  scale_y_continuous(breaks = c(0.4, 1.3, 2.2))

相关问题