2014-05-11 12 views
10

Sto cercando di abbinare il testo della legenda al colore del testo prodotto da una variabile fattorizzata utilizzando geom_text. Ecco un esempio di lavoro minima:Colore del testo della legenda della corrispondenza in geom_text al simbolo

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

io sono sicuro che la sua una semplice correzione. Qualsiasi suggerimento o riferimento a post precedenti potrebbe aiutare. Non ho trovato nulla di specifico a questo.

risposta

11

In seguito al commento di Joran sopra, è possibile modificare direttamente le grobs. Questo è un po 'brutto di codice quindi scuse [ci sarà un modo molto più elegante per farlo usando i comandi grid - e spero che qualcuno pubblichi).

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

Trama

gglabcol(p1) 


enter image description here

+3

+1 per fare il duro lavoro, anche se OP dovrebbe valutare se ne vale veramente la pena. – BrodieG

+0

BrodieG - Come OP sono d'accordo con te, ma stavo cercando di rispondere alla richiesta dei revisori in un manoscritto dato che ci sono più di 2 livelli di fattori e il colore testuale può essere fuorviante. Forse c'è un modo migliore per tracciare questo. Lo esaminerò. –

3

I colori nella trama sono gli stessi della legenda, ma il carattere della legenda rimane chiaro anche quando si imposta il carattere del carattere di stampa su grassetto (o corsivo). Non sono sicuro che si tratti di una svista nella progettazione di ggplot2 o del comportamento previsto. Per alcuni colori, il carattere grassetto sembra più saturo del carattere semplice, facendolo sembrare un colore diverso.

In ogni caso, ecco un gioco che è molto più facile che scherzare con i grobs, ma questo potrebbe farti ottenere quello che vuoi. Usa geom_text con il carattere semplice, ma fallo due o tre volte di fila (o più), in modo da ottenere un overplotting. Questo farà sì che i simboli e la legenda appaiano simili al carattere in grassetto, poiché entrambi saranno sovrapposti e i simboli delle legende avranno sempre lo stesso aspetto dei simboli del grafico.

Ecco un esempio:

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

Grazie per questo bel trucco per abbinare il carattere, ma - In realtà stavo cercando di abbinare il testo della legenda, "dovrebbe essere rosa" e "dovrebbe essere blu", alla legenda e al simbolo del grafico. ad esempio il testo "dovrebbe essere rosa" dovrebbe avere lo stesso colore delle lettere "a", "c", "e", "g" e "i" mentre il testo "dovrebbe essere blu" deve essere dello stesso colora come "b", "d", "f", "h" e "j" –

+0

Bene, suppongo di dover leggere la domanda un po 'più attentamente la prossima volta! – eipi10

+0

@ eipi10, non è stato facile capire la domanda, OP avrebbe dovuto scrivere '' "questo carattere del testo della legenda dovrebbe essere rosa" ''. Dopo aver letto la prima metà del commento sopra, ho pensato che volesse che il testo "fosse rosa" fosse stampato sulla trama. Immagino che le possibilità siano infinite :-) Il tuo kludge è in realtà molto utile per me btw! – PatrickT

4

A volte è più facile modificare un Grob utilizzando grid 's funzioni di editing - se i nomi dei grobs rilevanti possono essere trovati . In questo caso, possono essere trovati e la modifica è immediata: cambia il colore dell'etichetta dal nero al rosso o al blu.

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

Guardare attraverso l'elenco di ghiotti. I grobs che vogliamo modificare sono verso la fine dell'elenco, nel set di "groove" della guida, con nomi che iniziano con "label". Ci sono due grobs:

etichetta-3-3.4-4-4-4
etichetta-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

Cosa se fosse necessario che le chiavi fossero punti anziché lettere? Potrebbe essere utile perché la 'a' è un simbolo nella trama, ed è un simbolo nella chiave della legenda. Questa non è una semplice modifica, come sopra. Ho bisogno di un punto grob per prendere il posto del testo grob.Traggo delle gobbe nelle finestre, ma se riesco a trovare i nomi delle finestre pertinenti, dovrebbe essere semplice effettuare la modifica.

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

finestra [tasto-4-1-1.5-2-5-2], finestra [tasto-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

Aggiornamento

Tenuto conto di 's @ user20650 consiglio di cambiare la lege tasto nd (vedere il commento seguente):

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 

Quindi procedere come prima per modificare il colore del testo della legenda.

+1

@ user20650 Grazie mille per questo. E 'molto utile. –

+1

sì, è una bella nuova funzionalità - peccato che le etichette non siano così facili – user20650

Problemi correlati