2012-04-04 1 views
28

Sto tentando di visualizzare alcune informazioni sui dati sotto la trama creata in ggplot2. Vorrei tracciare la variabile N usando la coordinata dell'asse X del grafico, ma la coordinata Y deve essere del 10% dal fondo dello schermo. Infatti, le coordinate Y desiderate sono già nel frame di dati come variabile y_pos.Visualizzazione del testo sotto il grafico generato da ggplot2

mi viene in mente 3 approcci utilizzando ggplot2:

1) Creare un complotto vuota sotto la trama vera e propria, utilizzare la stessa scala e quindi utilizzare geom_text per tracciare i dati sopra la trama vuoto. This approach funziona ma è estremamente complicato.

2) Utilizzare geom_text per tracciare i dati, ma in qualche modo utilizzare la coordinata come percentuale dello schermo (10%). Ciò costringerebbe i numeri a essere visualizzati sotto la trama. Non riesco a capire la sintassi corretta.

3) Utilizzare grid.text per visualizzare il testo. Posso facilmente impostarlo al 10% dalla parte inferiore dello schermo, ma non riesco a capire come impostare il coordindate X per adattarlo alla trama. Ho provato ad usare grconvert per catturare la posizione iniziale di X, ma non riuscivo a farlo funzionare.

Di seguito la trama di base con i dati manichino:

graphics.off()  # close graphics windows 

library(car) 
library(ggplot2) #load ggplot 
library(gridExtra) #load Grid 
library(RGraphics) # support of the "R graphics" book, on CRAN 

#create dummy data 
test= data.frame(
    Group = c("A", "B", "A","B", "A", "B"), 
    x = c(1 ,1,2,2,3,3), 
    y = c(33,25,27,36,43,25), 
    n=c(71,55,65,58,65,58), 
    y_pos=c(9,6,9,6,9,6) 
) 

#create ggplot 
p1 <- qplot(x, y, data=test, colour=Group) + 
    ylab("Mean change from baseline") + 
    geom_line()+ 
    scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1)) + 
    opts( 
     legend.position=c(.1,0.9)) 

#display plot 
p1 

Il gplot modificato di seguito visualizza i numeri di soggetti, tuttavia essi vengono visualizzati all'interno della trama. Forzano la scala Y ad essere estesa. Mi piacerebbe mostrare questi numeri SOTTO la trama.

p1 <- qplot(x, y, data=test, colour=Group) + 
    ylab("Mean change from baseline") + 
    geom_line()+ 
    scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1)) + 
    opts(plot.margin = unit(c(0,2,2,1), "lines"), 
     legend.position=c(.1,0.9))+ 
    geom_text(data = test,aes(x=x,y=y_pos,label=n)) 

p1 

Un approccio diverso di visualizzare i numeri comporta la creazione di una trama fittizia sotto la trama vera e propria. Ecco il codice:

graphics.off()  # close graphics windows 

library(car) 
library(ggplot2) #load ggplot 
library(gridExtra) #load Grid 
library(RGraphics) # support of the "R graphics" book, on CRAN 

#create dummy data 
test= data.frame(
    group = c("A", "B", "A","B", "A", "B"), 
    x = c(1 ,1,2,2,3,3), 
    y = c(33,25,27,36,43,25), 
    n=c(71,55,65,58,65,58), 
    y_pos=c(15,6,15,6,15,6) 
) 


p1 <- qplot(x, y, data=test, colour=group) + 
    ylab("Mean change from baseline") + 
    opts(plot.margin = unit(c(1,2,-1,1), "lines")) + 
    geom_line()+ 
    scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1)) + 
    opts(legend.position="bottom", 
     legend.title=theme_blank(), 
     title.text="Line plot using GGPLOT") 
p1 

p2 <- qplot(x, y, data=test, geom="blank")+ 
    ylab(" ")+ 
    opts( plot.margin = unit(c(0,2,-2,1), "lines"), 
      axis.line = theme_blank(), 
      axis.ticks = theme_segment(colour = "white"),   
      axis.text.x=theme_text(angle=-90,colour="white"), 
      axis.text.y=theme_text(angle=-90,colour="white"), 
      panel.background = theme_rect(fill = "transparent",colour = NA), 
      panel.grid.minor = theme_blank(),  
      panel.grid.major = theme_blank() 
      )+ 
    geom_text(data = test,aes(x=x,y=y_pos,label=n)) 
p2 

grid.arrange(p1, p2, heights = c(8.5, 1.5),    nrow=2) 
enter code here 

Tuttavia, questo è molto complicato e sarebbe difficile da modificare per dati diversi. Idealmente, mi piacerebbe essere in grado di passare le coordinate Y come percentuale dello schermo. Grazie in anticipo!

+0

annotation_custom() e codice [da qui] (http://stackoverflow.com/questions/9690648/point-clipped-on-x-axis-in-ggplot) potrebbero aiutarti. Vedi sotto. –

+0

Vedere la mia risposta qui sotto. È decisamente più semplice della risposta accettata. –

+0

Le versioni recenti di ggplot2 ora hanno questa funzionalità integrata come da seguente risposta: http://stackoverflow.com/a/36036479/170352 –

risposta

18

Modificatoopts è sconsigliata, sostituito da theme; element_blank ha sostituito theme_blank; e ggtitle() viene utilizzato al posto di opts(title = ...

Sandy- grazie mille !!!! Questo fa esattamente quello che voglio. Vorrei poter controllare il clipping in geom.text o geom.annotate.

Ho messo insieme il seguente programma se qualcun altro è interessato.

rm(list = ls())  # clear objects 
graphics.off()  # close graphics windows 

library(ggplot2) 
library(gridExtra) 

#create dummy data 
test= data.frame(
    group = c("Group 1", "Group 1", "Group 1","Group 2", "Group 2", "Group 2"), 
    x = c(1 ,2,3,1,2,3), 
    y = c(33,25,27,36,23,25), 
    n=c(71,55,65,58,65,58), 
    ypos=c(18,18,18,17,17,17) 

) 


p1 <- qplot(x=x, y=y, data=test, colour=group) + 
    ylab("Mean change from baseline") + 
    theme(plot.margin = unit(c(1,3,8,1), "lines")) + 
    geom_line()+ 
    scale_x_continuous("Visits", breaks=seq(-1,3)) + 
    theme(legend.position="bottom", 
     legend.title=element_blank())+ 
    ggtitle("Line plot") 


# Create the textGrobs 
for (ii in 1:nrow(test)) 
{ 
    #display numbers at each visit 
    p1=p1+ annotation_custom(grob = textGrob(test$n[ii]), 
          xmin = test$x[ii], 
          xmax = test$x[ii], 
          ymin = test$ypos[ii], 
          ymax = test$ypos[ii]) 

    #display group text 
    if (ii %in% c(1,4)) #there is probably a better way 
     { 
    p1=p1+ annotation_custom(grob = textGrob(test$group[ii]), 
          xmin = 0.85, 
          xmax = 0.85, 
          ymin = test$ypos[ii], 
          ymax = test$ypos[ii]) 
    } 

    } 




    # Code to override clipping 
    gt <- ggplot_gtable(ggplot_build(p1)) 
    gt$layout$clip[gt$layout$name=="panel"] <- "off" 
    grid.draw(gt) 

enter image description here

+1

Molto bello !! Non dimenticare di accettare la tua risposta. –

+0

Non sembra proprio qui, il codice funziona ancora per te? – PatrickT

13

Updatedopts() è stato sostituito con theme()

Nel seguente codice, un terreno di base è disegnato, con un margine più ampio nella parte inferiore del grafico. Il textGrob viene creato, quindi inserito nel grafico usando annotation_custom(). Tranne che il testo non è visibile perché è all'esterno del pannello di stampa: l'output viene ritagliato sul pannello. Ma usando il codice di battesimo from here, il ritaglio può essere sovrascritto. La posizione è in termini di unità di dati e entrambe le etichette di testo sono centrate.

library(ggplot2) 
library(grid) 

# Base plot 
df = data.frame(x=seq(1:10), y = seq(1:10)) 
p = ggplot(data = df, aes(x = x, y = y)) + geom_point() + ylim(0,10) + 
    theme(plot.margin = unit(c(1,1,3,1), "cm")) 
p 

# Create the textGrobs 
Text1 = textGrob(paste("Largest x-value is", round(max(df$x), 2), sep = " ")) 
Text2 = textGrob(paste("Mean = ", mean(df$x), sep = "")) 

p1 = p + annotation_custom(grob = Text1, xmin = 4, xmax = 4, ymin = -3, ymax = -3) + 
     annotation_custom(grob = Text2, xmin = 8, xmax = 8, ymin = -3, ymax = -3) 
p1 

# Code to override clipping 
gt <- ggplotGrob(p1) 
gt$layout$clip[gt$layout$name=="panel"] <- "off" 
grid.draw(gt) 

enter image description here

Oppure, utilizzando grid funzioni per creare e posizionare l'etichetta.

p 
grid.text((paste("Largest x-value is", max(df$x), sep = " ")), 
    x = unit(.2, "npc"), y = unit(.1, "npc"), just = c("left", "bottom"), 
    gp = gpar(fontface = "bold", fontsize = 18, col = "blue")) 

enter image description here

Modifica Oppure, aggiungere Grob testo con le funzioni gtable.

library(ggplot2) 
library(grid) 
library(gtable) 

# Base plot 
df = data.frame(x=seq(1:10), y = seq(1:10)) 
p = ggplot(data = df, aes(x = x, y = y)) + geom_point() + ylim(0,10) 

# Construct the text grob 
lab = textGrob((paste("Largest x-value is", max(df$x), sep = " ")), 
    x = unit(.1, "npc"), just = c("left"), 
    gp = gpar(fontface = "bold", fontsize = 18, col = "blue")) 


gp = ggplotGrob(p) 

# Add a row below the 2nd from the bottom 
gp = gtable_add_rows(gp, unit(2, "grobheight", lab), -2) 

# Add 'lab' grob to that row, under the plot panel 
gp = gtable_add_grob(gp, lab, t = -2, l = gp$layout[gp$layout$name == "panel",]$l) 

grid.newpage() 
grid.draw(gp) 

enter image description here

+0

Grazie mille !!! Mi rendo conto che le funzioni Grid consentono di posizionare il testo ovunque sul dispositivo. Mi sto solo chiedendo se è possibile inserire del testo SOTTO la trama, ma in qualche modo usare le coordinate X dalla trama. ho qualcosa di simile a quello che potevi con la funzione di testo nella base R. –

+0

Grazie! Ricevo l'errore: impossibile trovare la funzione "ggplot_gtable" > gt $ layout $ clip [gt $ layout $ name == "panel"] <- "off" –

+0

È una funzione in 'ggplot2'. Quale versione di ggplot2 stai usando? Potrebbe essere necessario aggiornare. L'ultima versione è 0.9.0 –

5

In realtà la migliore risposta e la soluzione più semplice è quello di utilizzare il pacchetto cowplot.

La versione 0.5.0 del pacchetto cowplot (su CRAN) gestisce i sottotitoli ggplot2 utilizzando la funzione add_sub.

Utilizzare in questo modo:

diamondsCubed <-ggplot(aes(carat, price), data = diamonds) + 
    geom_point() + 
    scale_x_continuous(trans = cuberoot_trans(), limits = c(0.2, 3), 
        breaks = c(0.2, 0.5, 1, 2, 3)) + 
    scale_y_continuous(trans = log10_trans(), limits = c(350, 15000), 
        breaks = c(350, 1000, 5000, 10000, 15000)) + 
    ggtitle('Price log10 by Cube-Root of Carat') + 
    theme_xkcd() 


    ggdraw(add_sub(diamondsCubed, "This is an annotation.\nAnnotations can span multiple lines.")) 
12

La versione attuale (> 2.1) ha un + labs(caption = "text"), che visualizza un'annotazione di seguito la trama. Questo è a tema (proprietà dei caratteri, ... allineati a sinistra/destra). Vedi https://github.com/hadley/ggplot2/pull/1582 per esempi.