2014-05-11 78 views
10

我試圖使用geom_text將因數文本的顏色與因子變量生成的文本顏色相匹配。下面是一個最小的工作例如:將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 

enter image description here

我相信它是一個簡單的解決。任何建議或參考以前的職位將有所幫助。我沒有找到任何具體的東西。

回答

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[["grobs"]][[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 <- l[sapply(l, function(i) grepl("guide.label", i))] 

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

      lb[[i]]$gp$col <- lg[[i]]$gp$col 

      g.b[["grobs"]][[1]][["grobs"]][sapply(g.b[["grobs"]][[1]][["grobs"]], 
          function(i) grepl("guide.label", i))][[i]] <- lb[[i]] 
      } 

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

     grid.draw(g) 

     invisible(g) 
    } 

情節

gglabcol(p1) 


enter image description here

+3

+1,儘管OP應該評估它是否真的值得。 – BrodieG

+0

BrodieG - 作爲OP我同意你的看法,但我試圖迴應審稿人在手稿中的要求,因爲有超過2個等級的因素和文字顏色可能會引起誤解。也許有更好的方式來繪製這個。我會仔細看看的。 –

3

圖中的顏色與圖例中的顏色相同,但即使將圖形符號fontface設置爲粗體(或斜體),圖例字體仍保持原樣。我不確定這是否是ggplot2的設計或預期行爲的疏忽。對於某些顏色,粗體字體看起來比普通字體更飽和,使其看起來像不同的顏色。

在任何情況下,這是一個混亂比grobs更容易,但這可能會讓你想要什麼。使用geom_text與純字體,但連續兩次或三次(或更多),所以你會得到overplotting。這將使符號和圖例看起來類似於粗體字體,因爲兩者都將被疊加,並且圖例符號將總是與劇情符號相同。

下面是一個例子:

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") 

enter image description here

+0

感謝這個漂亮的技巧來匹配字體的臉部,但 - 我實際上是試圖匹配傳奇文字,「應該是粉紅色的」和「應該是藍色的」,以圖例和情節符號。 例如,文本「應該是粉紅色的」應該帶有與字母'a','c','e','g'和'i'相同的顏色,而文本「應該是藍色的」必須是相同的顏色爲'b','d','f','h'和'j' –

+0

嗯,我想我需要在下次更仔細地閱讀這個問題! – eipi10

+0

@ eipi10,這個問題不容易理解,OP應該寫''「這個傳奇文字字體應該是粉紅色的'''。在閱讀了上述評論的前半部分之後,我認爲他希望將文本「應該是粉紅色的」打印在情節中。我想可能性是無止境的:-)你的kludge對我來說實際上是非常有用的! – PatrickT

4

有時更容易編輯使用grid的編輯功能GROB - 如果能找到相關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是在名單的底部,在'guide-box'集合中,名稱以「label」開頭。有兩種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) 

enter image description here

什麼如果要求鍵是點而不是字母?它可能很有用,因爲'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) 

enter image description here

更新

考慮到@ user20650的建議改變罪nd鍵(請參閱下面的註釋):

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 

然後按照以前一樣繼續更改圖例文本的顏色。

+1

@ user20650非常感謝您的支持。這非常有用。 –

+1

是的,它的一個不錯的新功能 - 羞愧的標籤不是那麼容易 – user20650

相關問題