将geom_text中的图例文本颜色与符号匹配

Vij*_*uri 11 r legend ggplot2

我试图将图例的文本与使用的因子变量生成的文本颜色进行颜色匹配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
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我确信这是一个简单的解决方案.对先前帖子的任何建议或参考都会有所帮助.我没有发现任何特定的内容.

use*_*650 11

继上面的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)
   }
Run Code Online (Sandbox Code Playgroud)

情节

gglabcol(p1)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


San*_*att 5

有时使用grid编辑功能编辑grob 更容易- 如果可以找到相关grob的名称.在这种情况下,可以找到它们,编辑很简单 - 将标签的颜色从黑色更改为红色或蓝色.

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))
Run Code Online (Sandbox Code Playgroud)

查看grobs列表.我们要编辑的grobs位于列表的底部,在"guide-box"集合中,名称以"label"开头.有两个grobs:

label-3-3.4-4-4-4
label-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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果要求键是点而不是字母怎么办?它可能很有用,因为'a'是图中的符号,它是图例键中的符号.这不是一个简单的编辑,如上所述.我需要一个点grob来代替文本grob.我在视口中绘制凹凸,但如果我能找到相关视口的名称,则应该直接进行更改.

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

视口[key-4-1-1.5-2-5-2],视口[key-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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

更新

考虑@ 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
Run Code Online (Sandbox Code Playgroud)

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


A. *_* K. 4

这是一个使用ggtext并避免直接编辑 grobs 的解决方案。(它确实涉及从图中提取颜色,但后续步骤更加用户友好。)

# Original code, but with a stripped-down call to `scale_color_hue` (since
# we're going to replace it).
library(ggplot2)
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(breaks=c("one", "two"))

# Load the `ggtext` library, which lets us style (parts of) text labels.
library(ggtext)
# Build the plot so we can extract the colors that were actually used.  (If you
# supply colors manually instead, this step isn't necessary.)
g1 = ggplot_build(p1)
# Add a scale with labels that are colored appropriately, using <span> tags.
# Also specify that legend labels should be processed with `element_markdown`.
p1 +
  scale_color_hue(name = "colors should match",
                  breaks = c("one", "two"),
                  labels = paste("<span style='color:",
                                 unname(unlist(unique(g1$data[[1]]["colour"]))),
                                 "'>",
                                 c("should be pink", "should be blue"),
                                 "</span>",
                                 sep = "")) +
  theme(legend.text = element_markdown())
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述