Annotazione di testo sul singolo aspetto in ggplot2


150

Voglio annotare un po 'di testo sull'ultima sfaccettatura della trama con il seguente codice:

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)

inserisci qui la descrizione dell'immagine

Ma questo codice annota il testo su ogni aspetto. Ti sarei molto grato se mi guidassi su come ottenere il testo annotato su un solo aspetto.


1
Credo che questo non sia ancora implementato , quindi sospetto che dovrete ricorrere al metodo provato e vero per costruire un frame di dati con il testo e una colonna per la variabile di sfaccettatura.
joran,

Risposte:


144

In genere dovresti fare qualcosa del genere:

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

Dovrebbe funzionare senza specificare completamente la variabile fattore, ma probabilmente genererà alcuni avvisi:

inserisci qui la descrizione dell'immagine


2
Mi sembra di imbattermi in alcune etichette sfocate quando provo a usare geom_text () sulla mia trama sfaccettata. È lo stesso problema discusso qui ( groups.google.com/forum/?fromgroups=#!topic/ggplot2/evsbeBT48M4 ) ed è stato risolto utilizzando annotate ("testo", ...). Qualcun altro ottiene etichette sfocate con geom_text ()?
Margaret,

6
@Margaret Di solito, è perché hai erroneamente detto a ggplot di tracciare una copia di ogni etichetta per ogni riga nel tuo frame di dati originale (quello con i punti, le linee, ecc.). Si noti che passo un frame di dati separato geom_textcon solo una riga.
joran,

3
Ok ho capito. Grazie. E se volessi mettere 3 etichette diverse sulla tua trama sfaccettata? Ho provato un frame di dati con tutte le righe che avevo sfaccettature e etichette univoche in ogni riga. Forse dovrei iniziare questo come una domanda separata.
Margaret,

8
Grazie per la tua soluzione Mi chiedo se posso farlo anche usando annotate()...?
Polarizza il

2
@ user3420448 Lo stesso, devi solo specificare i valori per ogni variabile di sfaccettatura.
joran,

106

Ecco la trama senza annotazioni di testo:

library(ggplot2)

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

trama senza annotazioni di testo

Creiamo un frame di dati aggiuntivo per contenere le annotazioni di testo:

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
)

trama con annotazioni di testo ai bordi

In alternativa, possiamo specificare manualmente la posizione di ciascuna etichetta:

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

trama con etichette di testo posizionate manualmente

Possiamo anche etichettare i grafici su due aspetti:

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
  )

sfaccettatura di due variabili

Appunti:

  • È possibile utilizzare -Infe Infper posizionare il testo ai bordi di un pannello.
  • È possibile utilizzare hjuste vjustper regolare la giustificazione del testo.
  • La cornice dati dell'etichetta di testo dat_textdovrebbe avere una colonna che funziona con il tuo facet_grid()o facet_wrap().

6
Questa risposta è superiore alla risposta accettata (ovviamente una differenza di 5 anni tra i due) per quanto chiaramente passi attraverso ogni passaggio. Anche maggiore chiarezza e spiegazioni.
Brandon,

1
Se vuoi aggiungere del testo a più righe, assicurati che il tuo colnames()testo data.framecorrisponda a quello dei dati che stai per tracciare.
Kots

Quando provo a farlo per una sola delle mie sfaccettature, viene visualizzata l'annotazione ma i punti effettivi scompaiono (o sono oscurati?).
Ben G,

Ben G, potresti prendere in considerazione l'idea di creare un nuovo post per condividere codice e figura.
Kamil Slowikowski,

36

Se qualcuno è alla ricerca di un modo semplice per etichettare le sfaccettature di report o pubblicazioni, il pacchetto egg( CRAN ) ha funzioni tag_facet()e tag_facet_outside()funzioni piuttosto eleganti .

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)

Tag all'interno

Predefinito

tag_facet(p)

Nota: se si desidera mantenere il testo e lo sfondo della striscia, provare ad aggiungere strip.textestrip.background ricollegare themeo rimuovere theme(strip.text = element_blank(), strip.background = element_blank())dalla tag_facet()funzione originale .

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

Allinea in alto a destra e usa numeri romani

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

Allinea in basso a sinistra e usa le lettere maiuscole

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

Definisci i tuoi tag

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)

Tag all'esterno

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)

Modifica : aggiunta di un'altra alternativa usando il pacchetto 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)

Creato dal pacchetto reprex (v0.2.1)


2
Fonte dice "Aggiunge un livello di testo fittizio per un ggplot a sfaccettature di etichette e set sfaccettatura strisce a vuoto". Ergo, se si dispone di un'etichetta aspetto personalizzato strisce non si vuole perdere, modificare lo script per tag_facetda nixingstrip.text = element_blank()
CrunchyTopping

@CrunchyTopping Questo era in realtà il cappello che stavo cercando, ma non sembra funzionare per me:Warning: Ignoring unknown parameters: strip.text
efrem,

1
Per rispondere ai miei problemi sopra ... questo post spiega bene come mantenere le strisce: stackoverflow.com/a/56064130/3609450
efrem

22

Penso che per la risposta sopra lab = "Testo" sia inutile, anche il codice qui sotto è ok.

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

Tuttavia, se vuoi etichettare diversamente in diversi sotto-grafici, andrà bene in questo modo:

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

7
Dovresti spiegare in dettaglio cosa offre la tua soluzione rispetto alla risposta già fornita e accettata.
Sascha Wolf,

3
Grazie, è stato utile per etichettare diversi sotto-grafici.
Deathkill14

Per qualche ragione, quando lo faccio, aggiunge sfaccettature (vuote) per i fattori cil = 2 e cil = 3.
emudrak,

6

Espandendo leggermente la risposta eccellente di joran, per chiarire come funziona il dataframe dell'etichetta.

Puoi pensare a "mpg" e "wt" come rispettivamente le coordinate xey (trovo più facile tenere traccia dei nomi delle variabili originali piuttosto che rinominarli, come nella risposta eccellente anche di Kamil). È necessaria una riga per etichetta e la colonna "cil" mostra a quale aspetto è associata ciascuna riga.

ann_text<-data.frame(mpg=c(25,15),wt=c(3,5),cyl=c(6,8),label=c("Label 1","Label 2"))

ann_text
>  mpg wt cyl  label
>  25  3   6   Label 1
>  15  5   8   Label 2

p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p <- p + facet_grid(. ~ factor(cyl))
p + geom_text(data = ann_text,label=ann_text$label)

trama con etichette


2

Non sapevo del eggpacchetto, quindi ecco una ggplot2soluzione pacchetto semplice

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.