将ggplot2 :: geom_line图例形状更改为类似于ggplot2 :: geom_point的图例形状的“点”

时间:2019-01-07 01:37:40

标签: r ggplot2

此处最重要的工作是将geom_line的图例形状更改为geom_point“点”,但在图中保留geom_line。如果有人可以演示如何创建更清晰的geom_line2()函数(请参见下文),请在图例中显示geom_point“点”对象,我将不胜感激。

我知道有人可以将geom_point放在guides(color = FALSE)上并为geom_line产生ggproto。但是,我想在geom_point代码中了解如何执行此操作。我还知道使用geom_line可以覆盖图例形状,但是这种方法不适用于 GeomPath

我尝试修改draw_key = draw_key_path对象,将draw_key = draw_key_point更改为guides(color = guide_geom()),但是由于许多原因而失败。

我还认为使用# this is the default library(tidyverse) library(grid) mydf <- tibble(month = rep(seq(1, 10, 1), 4), olympian = sort(rep(c("apollo", "jove", "mercury", "minerva"), 10)), weight = c(seq(51, 60, 1), seq(60, 78, 2), seq(69.5, 56, -1.5), seq(55, 46, -1))) ggplot(mydf, aes(month, weight, color = olympian)) + geom_line(size = 1) + theme_light() + labs(title = "Default geom_line legend shape") 也许可以达到预期的效果,但是,正如广为宣传的那样,这是一个未记录的功能。即使查看了GitHub上的源代码,我也无法取得进展。

底部的代码段产生了预期的效果,但是很笨拙。

# here is what worked to achieve the effect

GeomLine2 <- GeomPath

GeomLine2$draw_key <- function(data, params, size) {
  data$linetype[is.na(data$linetype)] <- 0

  segmentsGrob(0.5, 0.5, 0.5, 0.5, # NOTE CHG HERE
               gp = gpar(
                 col = alpha(data$colour, data$alpha),
                 lwd = 5, # NOTE CHG HERE
                 lty = data$linetype,
                 lineend = "round" # NOTE CHG HERE
               ),
               arrow = params$arrow
  )
}

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

ggplot(mydf, aes(month, weight, color = olympian)) +
  geom_line2(size = 1) +
  theme_light() +
  labs(subtitle = "Hacked geom_line legend shape")

enter image description here

ggplot2::geom_line

enter image description here

此代码还会产生不良后果,即将以后所有对ggplot2的调用都设置为相同的图例效果。

PS ... this answer会有所帮助,但它适用于旧的%calculate the length len([],0). len([_|T],N) :- len(T,X), N is X+1. %check the length isEmpty(L) :- len(L,X),X=:=0.

1 个答案:

答案 0 :(得分:1)

选项1:

不要这样做! (注意,这是我的最爱,并不是要刻薄或无益)。 ggplot试图迫使您以特定的方式做事,通常是因为有充分的理由。用点表示线不如使用线清晰,因此通常应避免使用。图的最重要方面是它传达信息的清晰程度,而不是看起来的美观程度。不要为了美观而牺牲清晰度。

但是,如果您确实有理由确定点会更好,那么...

选项2

不要使用ggplot。如前所述,ggplot倾向于使用自己的图应如何哲学。其他工具更宽容,可以轻松地适应这一点。例如。在基本图形中这很容易做到

选项3

如果您确实需要ggplot,并且确实需要点来表示线,则可以创建一个使用geom_point而不是geom_line的图,然后使用gtable将线图中的图例替换为点图中的图例

g = ggplot(mydf, aes(month, weight, color = olympian)) + theme_light()

gt.l = ggplot_gtable(ggplot_build(g + geom_line(size = 1)))
gt.p = ggplot_gtable(ggplot_build(g + geom_point(size = 2)))
gt.l$grobs[15] = gt.p$grobs[15]
grid.draw(gt.l)

enter image description here

注意:如果您不知道需要替换哪个grob,则可以在grob名称中搜索"guide"来找到正确的grob:

gt.l$grobs[grep('guide', gt.l$layout$name)] = gt.p$grobs[grep('guide', gt.p$layout$name)]