Anotar texto en una faceta individual en ggplot2

Resuelto MYaseen208 asked hace 54 años • 6 respuestas

Quiero anotar algo de texto en la última faceta del gráfico con el siguiente código:

library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p <- p + facet_grid(. ~ cyl)
p <- p + annotate("text", label = "Test", size = 4, x = 15, y = 5)
print(p)

ingrese la descripción de la imagen aquí

Pero este código anota el texto en cada faceta. ¿Cómo puedo obtener el texto anotado en una sola faceta?

MYaseen208 avatar Jan 01 '70 08:01 MYaseen208
Aceptado

La función annotate()agrega la misma etiqueta a todos los paneles en un gráfico con facetas. Si la intención es agregar diferentes anotaciones a cada panel, o anotaciones solo a algunos paneles, se debe usar geom_ en lugar de annotate(). Para usar una geom, como por ejemplo, geom_text()necesitamos ensamblar un marco de datos que contenga el texto de las etiquetas en una columna y columnas para que las variables se asignen a otras estéticas, así como las variables utilizadas para el facetado.

Normalmente harías algo como esto:

ann_text <- data.frame(mpg = 15,wt = 5,lab = "Text",
                       cyl = factor(8,levels = c("4","6","8")))
p + geom_text(data = ann_text,label = "Text")

Debería funcionar sin especificar completamente la variable del factor, pero probablemente generará algunas advertencias:

ingrese la descripción de la imagen aquí

joran avatar Aug 09 '2012 18:08 joran

La función annotate()agrega la misma etiqueta a todos los paneles en un gráfico con facetas. Si la intención es agregar diferentes anotaciones a cada panel, o anotaciones solo a algunos paneles, se debe usar una geometríaannotate() en lugar de . Para usar una geometría como esta, geom_text()necesitamos ensamblar un marco de datos que contenga el texto de las etiquetas en una columna y columnas para que las variables se asignen a otras estéticas, así como las variables utilizadas para el facetado. Esta respuesta ejemplifica esto tanto para facet_wrap()como para facet_grid().

Aquí está la trama sin anotaciones de texto:

library(ggplot2)

p <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point() +
  facet_grid(. ~ cyl) +
  theme(panel.spacing = unit(1, "lines"))
p

trama sin anotaciones de texto

Creemos un marco de datos adicional para contener las anotaciones de texto:

dat_text <- data.frame(
  label = c("4 cylinders", "6 cylinders", "8 cylinders"),
  cyl   = c(4, 6, 8)
)
p + geom_text(
  data    = dat_text,
  mapping = aes(x = -Inf, y = -Inf, label = label),
  hjust   = -0.1,
  vjust   = -1
)

trazar con anotaciones de texto en los bordes

Alternativamente, podemos especificar manualmente la posición de cada etiqueta:

dat_text <- data.frame(
  label = c("4 cylinders", "6 cylinders", "8 cylinders"),
  cyl   = c(4, 6, 8),
  x     = c(20, 27.5, 25),
  y     = c(4, 4, 4.5)
)

p + geom_text(
  data    = dat_text,
  mapping = aes(x = x, y = y, label = label)
)

trazar con etiquetas de texto colocadas manualmente

También podemos etiquetar gráficos en dos facetas:

dat_text <- data.frame(
  cyl   = c(4, 6, 8, 4, 6, 8),
  am    = c(0, 0, 0, 1, 1, 1)
)
dat_text$label <- sprintf(
  "%s, %s cylinders",
  ifelse(dat_text$am == 0, "automatic", "manual"),
  dat_text$cyl
)
p +
  facet_grid(am ~ cyl) +
  geom_text(
    size    = 5,
    data    = dat_text,
    mapping = aes(x = Inf, y = Inf, label = label),
    hjust   = 1.05,
    vjust   = 1.5
  )

faceta por dos variables

Notas:

  • Puede utilizar -Infy Infpara colocar texto en los bordes de un panel.
  • Puede utilizar hjusty vjustpara ajustar la justificación del texto.
  • El marco de datos de la etiqueta de texto dat_textdebe tener una columna que funcione con su facet_grid()o facet_wrap().
Kamil Slowikowski avatar Dec 15 '2017 16:12 Kamil Slowikowski

Si alguien está buscando una manera fácil de etiquetar facetas para informes o publicaciones, el paquete egg( CRAN ) tiene funciones bastante tag_facet()ingeniosas tag_facet_outside().

library(ggplot2)

p <- ggplot(mtcars, aes(qsec, mpg)) + 
  geom_point() + 
  facet_grid(. ~ am) +
  theme_bw(base_size = 12)

# install.packages('egg', dependencies = TRUE)
library(egg)

Etiqueta dentro

Por defecto

tag_facet(p)

Nota: si desea conservar el texto y el fondo de la tira, intente agregarlos strip.textnuevamentestrip.background o themeeliminarlos de la función theme(strip.text = element_blank(), strip.background = element_blank())original .tag_facet()

tag_facet <- function(p, open = "(", close = ")", tag_pool = letters, x = -Inf, y = Inf, 
                      hjust = -0.5, vjust = 1.5, fontface = 2, family = "", ...) {

  gb <- ggplot_build(p)
  lay <- gb$layout$layout
  tags <- cbind(lay, label = paste0(open, tag_pool[lay$PANEL], close), x = x, y = y)
  p + geom_text(data = tags, aes_string(x = "x", y = "y", label = "label"), ..., hjust = hjust, 
                vjust = vjust, fontface = fontface, family = family, inherit.aes = FALSE) 
}

Alinear arriba a la derecha y usar números romanos

tag_facet(p, x = Inf, y = Inf, 
          hjust = 1.5,
          tag_pool = as.roman(1:nlevels(factor(mtcars$am))))

Alinee la parte inferior izquierda y use letras mayúsculas

tag_facet(p, 
          x = -Inf, y = -Inf, 
          vjust = -1,
          open = "", close = ")",
          tag_pool = LETTERS)

Defina sus propias etiquetas

my_tag <- c("i) 4 cylinders", "ii) 6 cyls")
tag_facet(p, 
          x = -Inf, y = -Inf, 
          vjust = -1, hjust = -0.25,
          open = "", close = "",
          fontface = 4,
          size = 5,
          family = "serif",
          tag_pool = my_tag)

Etiqueta afuera

p2 <- ggplot(mtcars, aes(qsec, mpg)) + 
  geom_point() + 
  facet_grid(cyl ~ am, switch = 'y') +
  theme_bw(base_size = 12) +
  theme(strip.placement = 'outside')

tag_facet_outside(p2)

Editar : agregar otra alternativa usando el paquete stickylabeller

- `.n` numbers the facets numerically: `"1"`, `"2"`, `"3"`...
- `.l` numbers the facets using lowercase letters: `"a"`, `"b"`, `"c"`...
- `.L` numbers the facets using uppercase letters: `"A"`, `"B"`, `"C"`...
- `.r` numbers the facets using lowercase Roman numerals: `"i"`, `"ii"`, `"iii"`...
- `.R` numbers the facets using uppercase Roman numerals: `"I"`, `"II"`, `"III"`...

# devtools::install_github("rensa/stickylabeller")
library(stickylabeller)

ggplot(mtcars, aes(qsec, mpg)) + 
  geom_point() + 
  facet_wrap(. ~ am, 
             labeller = label_glue('({.l}) am = {am}')) +
  theme_bw(base_size = 12)

Creado por el paquete reprex (v0.2.1)

Tung avatar Sep 07 '2018 07:09 Tung

Creo que para la respuesta anterior lab="Text" es inútil, el siguiente código también está bien.

ann_text <- data.frame(mpg = 15,wt = 5,
                       cyl = factor(8,levels = c("4","6","8")))
p + geom_text(data = ann_text,label = "Text" )

Sin embargo, si desea etiquetar de manera diferente en diferentes subgráficos, estará bien de esta manera:

ann_text <- data.frame(mpg = c(14,15),wt = c(4,5),lab=c("text1","text2"),
                       cyl = factor(c(6,8),levels = c("4","6","8")))
p + geom_text(data = ann_text,aes(label =lab) )
kdyhl avatar Dec 12 '2014 14:12 kdyhl

No conocía el eggpaquete, así que aquí hay una ggplot2solución de paquete simple.

library(tidyverse)
library(magrittr)
Data1=data.frame(A=runif(20, min = 0, max = 100), B=runif(20, min = 0, max = 250), C=runif(20, min = 0, max = 300))
Data2=data.frame(A=runif(20, min = -10, max = 50), B=runif(20, min = -5, max = 150), C=runif(20, min = 5, max = 200))
bind_cols(
Data1 %>% gather("Vars","Data_1"),
Data2 %>% gather("Vars","Data_2")
) %>% select(-Vars1) -> Data_combined
Data_combined %>%
  group_by(Vars) %>%
  summarise(r=cor(Data_1,Data_2),
            r2=r^2,
            p=(pt(abs(r),nrow(.)-2)-pt(-abs(r),nrow(.)-2))) %>%
  mutate(rlabel=paste("r:",format(r,digits=3)),
         plabel=paste("p:",format(p,digits=3))) ->
  label_df 
label_df %<>% mutate(x=60,y=190)
Data_combined %>%
  ggplot(aes(x=Data_1,y=Data_2,color=Vars)) +
  geom_point() + 
  geom_smooth(method="lm",se=FALSE) +
  geom_text(data=label_df,aes(x=x,y=y,label=rlabel),inherit.aes = FALSE) + 
  geom_text(data=label_df,aes(x=x,y=y-10,label=plabel),inherit.aes = FALSE) + 
    facet_wrap(~ Vars)
Erich Neuwirth avatar May 30 '2019 18:05 Erich Neuwirth