R语言 旋转geom_abline的图例关键点

rqcrx0a6  于 2023-04-27  发布在  其他
关注(0)|答案(3)|浏览(108)

我想将geom_abline的图例键旋转到水平图例键,或者如果可能的话,基于它们的斜率。下面是一些可复制的代码(下面的dput df):

library(ggplot2)
p = ggplot(df, mapping = aes(x = x, y = y)) +
  geom_point() +
  geom_abline(df, mapping = aes(slope = slope, intercept = 0, color = factor(group))) +
  coord_cartesian(xlim = c(0, 3), ylim = c(0, 3)) 
p

创建于2023-04-19带有reprex v2.0.2
我尝试使用@桑迪Muspratt他的答案heregrid函数,但这也旋转了ablines和图例键。所以我想知道是否有人知道如何旋转geom_abline的图例键?
dput df:

df<-structure(list(x = c(0, 0, 0), y = c(0, 0, 0), slope = c(0.5, 
1, 0.75), group = c("A", "B", "C")), class = "data.frame", row.names = c(NA, 
-3L))
tmb3ates

tmb3ates1#

这里的解决方案在于定义一个新的绘制键。然而,正如Tjebo在评论中指出的,很难以这种方式自定义斜率,因为传递给draw_key_*函数的数据不包含所有的美学数据-只有制作标准绘制键所需的数据(线宽,颜色,填充等)。
一种解决方法是利用ggplots是使用ggproto系统构建的,而ggproto系统本身是基于嵌套环境的。可以编写一个自定义的draw_key_*函数,查找适当的祖先帧以找到整个美学数据集:

draw_key_custom <- function (data, params, size) {
  colour <- data$colour 
  datalist <- get("data", parent.frame((10)))
  i <- which(sapply(datalist, function(x) "slope" %in% names(x)))[1]
  data <- datalist[[i]]
  data <- data[data$colour == colour,]
  slope <- data$slope
  intercept <- (1 - slope)/2
  y1 <- ifelse(abs(slope) > 1, (sign(slope) + 1)/2, intercept)
  y2 <- ifelse(abs(slope) > 1, 1 - (sign(slope) + 1)/2, intercept + slope)
  x1 <- ifelse(abs(slope) > 1, (y1 - intercept)/slope, 0)
  x2 <- ifelse(abs(slope) > 1, (y2 - intercept)/slope, 1)
  grid::segmentsGrob(x1, y1, x2, y2,
               gp = grid::gpar(col = data$colour, 
                               lwd = data$linewidth * 2))
}

这允许:

ggplot(df, mapping = aes(x = x, y = y)) +
  geom_point() +
  geom_abline(aes(slope = slope, intercept = 0, color = factor(group)),
              key_glyph = draw_key_custom) +
  coord_cartesian(xlim = c(0, 3), ylim = c(0, 3))

我想指出的几件事是:
1.在图例中更改坡度是不寻常的,也是不必要的
1.除非图例键的纵横比适合绘图面板的纵横比,否则生成的坡度不一定与图中的坡度匹配。除非在theme中指定了纵横比,否则在调整图大小时此比率不稳定
1.上面的实现对于ggplot内的变化是脆弱的,并且如果多条线具有相同的颜色,则可能无法工作。
不过,很高兴知道这是可以做到的,我想...

ftf50wuq

ftf50wuq2#

这不是对这个问题的真实的答案,我明白这也更多地是关于概念的证明。想到由此产生的所有可能性,这绝对是令人惊讶的。然而,我相信提供一个替代方案是很重要的,特别是对于未来的读者,他们可能会有一个奇特的传说,尽管可以说更好的解决方案可能是:
没有传说。
您可以通过简单的直接标注来完全避免图例,这里基本上是使用Allan自己的geomtextpath包改进Allan的答案。

library(geomtextpath)

ggplot(df, mapping = aes(x = x, y = y)) +
  geom_point() +
  geom_textabline(aes(label = group, slope = slope, intercept = 0, color = group), hjust = .8) +
  coord_cartesian(xlim = c(0, 3), ylim = c(0, 3)) +
  theme(legend.position = "none")

pieyvz9o

pieyvz9o3#

在同一个网站上,有一个@user20650的回答和评论。根据他在这里的回答How to change angle of line in customized legend in ggplot2和阅读这个https://ggplot2.tidyverse.org/reference/draw_key.html,我们可以这样做:
要使其工作,我们必须将lwd = data$size替换为lwd = 0.5

library(ggplot2)
library(grid)

library(ggplot2)
library(grid)
df<-structure(list(x = c(0, 0, 0), y = c(0, 0, 0), slope = c(0.5, 
1, 0.75), group = c("A", "B", "C")), class = "data.frame", row.names = c(NA, 
-3L))

GeomAbline$draw_key <- function(data, params, size) 
{
  segmentsGrob(0, 0.5, 1, 0.5,
               gp = gpar(col = alpha(data$colour, 
                                     data$alpha), 
                         lwd = 0.5* .pt, lty = data$linetype, 
                         lineend = "butt"))
}

ggplot(df, mapping = aes(x = x, y = y)) +
  geom_point() +
  geom_abline(df, mapping = aes(slope = slope, intercept = 0, color = factor(group))) +
  coord_cartesian(xlim = c(0, 3), ylim = c(0, 3))

相关问题