Exibindo o texto abaixo da plotagem gerada pelo ggplot2

Eu estou tentando exibir algumas informações sobre os dados abaixo do gráfico criado no ggplot2 . Eu gostaria de plotar a variável N usando a coordenada do eixo X do gráfico, mas a coordenada Y precisa ser 10% a partir da parte inferior da canvas. De fato, as coordenadas Y desejadas já estão no quadro de dados como variável y_pos.

Eu posso pensar em 3 abordagens usando ggplot2 :

1) Crie um gráfico vazio abaixo do gráfico real, use a mesma escala e, em seguida, use geom_text para plotar os dados sobre o gráfico em branco. Essa abordagem funciona, mas é extremamente complicada.

2) Use geom_text para plotar os dados, mas de alguma forma use coordenada y como porcentagem da canvas (10%). Isso forçaria os números a serem exibidos abaixo do gráfico. Eu não consigo descobrir a syntax adequada.

3) Use grid.text para exibir o texto. Eu posso facilmente configurá-lo nos 10% a partir da parte inferior da canvas, mas não consigo definir como definir a coordenada X para corresponder ao gráfico. Eu tentei usar o grconvert para capturar a posição X inicial, mas não consegui fazer com que ela funcionasse também.

Abaixo está o gráfico básico com os dados fictícios:

 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 

O gplot modificado abaixo exibe números de assuntos, porém eles são exibidos dentro da plotagem. Eles forçam a escala Y a ser estendida. Eu gostaria de exibir esses números abaixo do enredo.

  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 

Uma abordagem diferente de exibir os números envolve a criação de um gráfico fictício abaixo do gráfico real. Aqui está o código:

 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 ) 

No entanto, isso é muito complicado e seria difícil de modificar para dados diferentes. Idealmente, gostaria de poder passar coordenadas Y como porcentagem da canvas.

Os opts foram substituídos, substituídos por theme ; element_blank substituiu theme_blank ; e ggtitle() é usado no lugar de opts(title = ...

Sandy- muito obrigado !!!! Isso faz exatamente o que eu quero. Eu gostaria que pudéssemos controlar o recorte em geom.text ou geom.annotate.

Eu montei o seguinte programa se alguém estiver interessado.

  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) 

insira a descrição da imagem aqui

A versão atual (> 2.1) possui um + labs(caption = "text") , que exibe uma anotação abaixo do gráfico. Isso é personalizável (propriedades da fonte, … esquerda / direita alinhadas). Veja https://github.com/hadley/ggplot2/pull/1582 para exemplos.

Atualizado opts() foi substituído por theme()

No código abaixo, um gráfico básico é desenhado, com uma margem maior na parte inferior do gráfico. O textGrob é criado e inserido no gráfico usando annotation_custom (). Exceto o texto não é visível porque está fora do painel de plotagem – a saída é cortada no painel. Mas usando o código de baptiste daqui , o recorte pode ser substituído. A posição é em termos de unidades de dados e os dois labels de texto são centralizados.

 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) 

insira a descrição da imagem aqui

Ou, usando funções de grid para criar e posicionar o label.

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

insira a descrição da imagem aqui

Editar Ou adicione grob de texto usando funções gtables.

 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) 

insira a descrição da imagem aqui

Na verdade, a melhor resposta e solução mais fácil é usar o pacote cowplot.

A versão 0.5.0 do pacote cowplot (no CRAN) manipula as legendas ggplot2 usando a function add_sub.

Use assim:

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