在geom_text到符号匹配传奇色彩的文字在geom_text到符号匹配传奇色彩的文字(Match

2019-05-12 02:37发布

我试图颜色匹配传奇通过使用因式分解的变量产生的文本颜色的文本geom_text 。 下面是一个最小的工作示例:

df <- data.frame(a=rnorm(10),b=1:10,c=letters[1:10],d=c("one","two"))
p1 <-ggplot(data=df,aes(x=b,y=a))
p1 <- p1 + geom_text(aes(label = c, color=d, fontface="bold"))
p1 <- p1 + scale_color_hue(name="colors should match",breaks=c("one", "two"),
                 labels=c("should be pink", "should be blue"))
p1

我相信它是一个简单的解决。 任何建议或参考之前的帖子会有所帮助。 我没有找到具体到这样的东西。

Answer 1:

从上面joran的评论继,你可以直接编辑grobs。 这是一个代码比较难看一点,所以道歉[将会有一个更优雅的方式来做到这一点使用grid命令-希望有人会发表。

library(grid)

gglabcol <- function(plot1){

         g <- ggplotGrob(plot1)

         # legend grobs
         g.b <- g[["grobs"]][[which(g$layout$name=="guide-box")]]
         l <- g.b[[1]][[1]][["grobs"]]

         # get grobs for legend symbols (extract colour)
         lg <- l[sapply(l, function(i) grepl("GRID.text", i))]

         # get grobs for legend labels 
         lb <- g.b[[1]][[1]][["grobs"]][grepl("label", g.b[[1]][[1]]$layout$name)]

         # get change colour of labels to colour of symbols
         for(i in seq_along(lg)) {

           g.b[[1]][[1]][["grobs"]][grepl("label", g.b[[1]][[1]]$layout$name)][[i]][["children"]][[1]][["children"]][[1]]$gp$col <- lg[[i]]$gp$col

           }

         # overwrite original legend
         g[["grobs"]][[which(g$layout$name=="guide-box")]] <- g.b

         grid.draw(g)

         invisible(g)
   }

情节

gglabcol(p1)



Answer 2:

有时,它更容易编辑使用GROB grid的编辑功能-如果可以找到相关grobs的名称。 在这种情况下,他们可以发现,和编辑很简单 - 从黑色标签的颜色改变,红色或蓝色。

library(ggplot2)
library(grid)

df <- data.frame(a=rnorm(10),b=1:10,c=letters[1:10],d=c("one","two"))
p1 <-ggplot(data=df,aes(x=b,y=a))
p1 <- p1 + geom_text(aes(label = c, color=d, fontface="bold"))
p1 <- p1 + scale_color_hue(name="colors should match",breaks=c("one", "two"),
                 labels=c("should be salmon", "should be sky blue"))
p1

# Get the ggplot grob
g <- ggplotGrob(p1)

# Check out the grobs
grid.ls(grid.force(g))

通过看grobs列表。 我们要编辑的grobs是对列表的底部,在设置grobs的“导盒子” - 所有以“标签”开头的名称。 有两种grobs:

标签3-3.4-4-4-4
标签4-3.5-4-5-4

# Get names of 'label' grobs.
names.grobs <- grid.ls(grid.force(g))$name 
labels <- names.grobs[which(grepl("label", names.grobs))]

# Get the colours
# The colours are the same as the colours of the plotted points.
# These are available in the ggplot build data.
gt <- ggplot_build(p1)
colours <- unique(gt$data[[1]][, "colour"])

# Edit the 'label' grobs - change their colours
# Use the `editGrob` function
for(i in seq_along(labels)) {
    g <- editGrob(grid.force(g), gPath(labels[i]), grep = TRUE,  
         gp = gpar(col = colours[i]))
}

# Draw it
grid.newpage()
grid.draw(g)

如果有人需要什么,该键是点,而不是信吗? 因为“A”是在情节的象征,它是传说中的关键标志,可以使用它。 这不是一个简单的编辑,像上面。 我需要一个点GROB把文本GROB的地方。 我画grobs在视口中,但是如果我能找到相关的视口的名字,它应该是简单的作出改变。

# Find the names of the relevant viewports
current.vpTree()  # Scroll out to the right to find he relevant 'key' viewports.

视[密钥4-1-1.5-2-5-2],视[密钥3-1-1.4-2-4-2]

# Well, this is convenient. The names of the viewports are the same 
# as the names of the grobs (see above). 
# Easy enough to get the names from the 'names.grobs' list (see above). 
# Get the names of 'key' viewports(/grobs)
keys <- names.grobs[which(grepl("key-[0-9]-1-1", names.grobs))]

# Insert points grobs into the viewports:
#    Push to the viewport;
#    Insert the point grob;
#    Pop the viewport.
for(i in seq_along(keys)) {
   downViewport(keys[i])
   grid.points(x = .5, y = .5, pch = 16, gp = gpar(col = colours[i]))
   popViewport()
}
popViewport(0)

# I'm not going to worry about removing the text grobs. 
# The point grobs are large enough to hide them. 

plot = grid.grab()
grid.newpage()
grid.draw(plot)

更新

考虑到@ user20650的建议来改变图例项(见下面的评论):

p1 <-ggplot(data=df,aes(x=b,y=a))
p1 <- p1 + geom_text(aes(label = c, color=d, fontface="bold"))
p1 <- p1 + scale_color_hue(name="colors should match",breaks=c("one", "two"),
                 labels=c("should be salmon", "should be sky blue"))

GeomText$draw_key <- function (data, params, size) { 
   pointsGrob(0.5, 0.5, pch = 16, 
   gp = gpar(col = alpha(data$colour, data$alpha), 
   fontsize = data$size * .pt)) }

p1

然后继续像以前一样更改图例文本的颜色。



Answer 3:

在图中的颜色是一样的,在传说中的颜色,但即使你的情节符号fontface设置为粗体(或斜体)的传奇fontface依然平淡。 我不知道这是否是在设计监督ggplot2或预期的行为。 对于一些的色彩,大胆的fontface看起来比普通fontface更饱和,使得它看起来像一个不同的颜色。

在任何情况下,这里的杂牌组装电脑,这比用grobs来得容易了很多,但可能会得到你想要的东西。 使用geom_text与普通fontface,但这样做两到三次连续(或更多),所以你会得到overplotting。 这将使这两个符号和图例出现类似大胆fontface,因为两者都将被overplotted和图标符号总是会一样的绘图符号。

下面是一个例子:

library(ggplot2)
library(gridExtra)

# Original plot (with larger font size)
p1 <- ggplot(data=df) +
  geom_text(aes(x=b, y=a, label=c, color=d), fontface='bold', size=8)
p1 <- p1 + scale_color_hue(name="colors should match",breaks=c("one", "two"),
                              labels=c("should be pink", "should be blue")) +
           ggtitle("Original Plot with Bold Symbols and Plain Legend")

# New version with overplotting. (You don't need to specify 'plain' fontface. 
# I've just included that to emphasize what the code is doing.)
p1.overplot <- ggplot(data=df) +
  geom_text(aes(x=b, y=a, label=c, color=d), fontface='plain', size=8) +
  geom_text(aes(x=b, y=a, label=c, color=d), fontface='plain', size=8) +
  geom_text(aes(x=b, y=a, label=c, color=d), fontface='plain', size=8)
p1.overplot <- p1.overplot + 
  scale_color_hue(name="colors should match",
                  breaks=c("one", "two"),
                  labels=c("should be pink", "should be blue")) +
  ggtitle("Both symbols and legend are overplotted 3 times")



Answer 4:

这个答案是基于给出的答案麦克H.从这里的问题 ,并通过user20650从这个问题。

为了让颜色:

  pGrob <- ggplotGrob(p1)
  g.b   <- pGrob[["grobs"]][[which(pGrob$layout$name=="guide-box")]]
  l     <- g.b[[1]][[1]][["grobs"]]
  # get grobs for legend symbols (extract colour)
  lg    <- l[sapply(l, function(i) grepl("GRID.text", i))]
  clr   <- mapply(FUN=function(x){x$gp$col},x=lg)

然后使用下面的方法

   gb  <- which(grepl("guide-box", pGrob$layout$name))
   gb2 <- which(grepl("guides", pGrob$grobs[[gb]]$layout$name))
   label_text <- which(grepl("label",pGrob$grobs[[gb]]$grobs[[gb2]]$layout$name))

   pGrob$grobs[[gb]]$grobs[[gb2]]$grobs[label_text] <- 
   mapply(FUN = function(x, y) {x[["children"]][[1]][["children"]][[1]]$gp <- gpar(col =y); return(x)},
          x =   pGrob$grobs[[gb]]$grobs[[gb2]]$grobs[label_text],
          y =  clr, SIMPLIFY = FALSE)

它之后,你会得到相同的输出文件

grid.draw(pGrob)

我提供这个答案,因为在代码的第二块,参数,分配给x$gpmapply功能,应该是一个gpar对象。 这是一个错误麦克H.的回答,我修复它。

谢谢。



文章来源: Match legend text color in geom_text to symbol
标签: r ggplot2 legend