Etichetta i punti in geom_point


178

I dati con cui sto giocando provengono dalla fonte Internet elencata di seguito

nba <- read.csv("http://datasets.flowingdata.com/ppg2008.csv", sep=",")

Quello che voglio fare è creare un grafico a punti 2D confrontando due metriche da questa tabella, con ogni giocatore che rappresenta un punto sul grafico. Ho il codice seguente:

nbaplot <- ggplot(nba, aes(x= MIN, y= PTS, colour="green", label=Name)) + 
                  geom_point() 

Questo mi dà quanto segue:

Grafico NBA

Quello che voglio è un'etichetta del nome del giocatore proprio accanto ai punti. Ho pensato che la funzione dell'etichetta nell'estetica di ggplot avrebbe fatto questo per me, ma non è stato così.

Ho anche provato la text()funzione e la textxy()funzione da library(calibrate), nessuna delle quali sembra funzionare con ggplot.

Come posso aggiungere etichette nome a questi punti?

Risposte:


280

Utilizzare geom_text, con aesetichetta. Puoi giocare con hjust, vjustper regolare la posizione del testo.

ggplot(nba, aes(x= MIN, y= PTS, colour="green", label=Name))+
  geom_point() +geom_text(aes(label=Name),hjust=0, vjust=0)

inserisci qui la descrizione dell'immagine

EDIT: etichetta solo i valori al di sopra di una certa soglia:

  ggplot(nba, aes(x= MIN, y= PTS, colour="green", label=Name))+
  geom_point() +
  geom_text(aes(label=ifelse(PTS>24,as.character(Name),'')),hjust=0,vjust=0)

grafico con etichette condizionali


4
C'è un modo per spostare le etichette (schivandole leggermente), in modo che non si sovrappongano?
Thomas Browne,

2
Non penso che ci sia una soluzione semplice all'interno ggplot2. Forse questo può aiutarti.
agstudy,

1
C'è un modo per etichettare solo i punti sopra un certo valore, ad esempio PTS maggiore di 24 sul grafico sopra?
ONeillMB1

a meno di "schivare" correttamente, considera questo hjust = -0.1per allontanare le etichette stampate così leggermente dal punto dati.
Patrick

Per spostare le etichette, considerare ggrepel .
Homer White,

92

Il ggrepelpacchetto funziona perfettamente per respingere le etichette di testo sovrapposte l'una dall'altra. Puoi usare geom_label_repel()(disegna rettangoli attorno al testo) o geom_text_repel()funzioni.

library(ggplot2)
library(ggrepel)

nba <- read.csv("http://datasets.flowingdata.com/ppg2008.csv", sep = ",")

nbaplot <- ggplot(nba, aes(x= MIN, y = PTS)) + 
  geom_point(color = "blue", size = 3)

### geom_label_repel
nbaplot + 
  geom_label_repel(aes(label = Name),
                  box.padding   = 0.35, 
                  point.padding = 0.5,
                  segment.color = 'grey50') +
  theme_classic()

inserisci qui la descrizione dell'immagine

### geom_text_repel
# only label players with PTS > 25 or < 18
# align text vertically with nudge_y and allow the labels to 
# move horizontally with direction = "x"
ggplot(nba, aes(x= MIN, y = PTS, label = Name)) + 
  geom_point(color = dplyr::case_when(nba$PTS > 25 ~ "#1b9e77", 
                                      nba$PTS < 18 ~ "#d95f02",
                                      TRUE ~ "#7570b3"), 
             size = 3, alpha = 0.8) +
  geom_text_repel(data          = subset(nba, PTS > 25),
                  nudge_y       = 32 - subset(nba, PTS > 25)$PTS,
                  size          = 4,
                  box.padding   = 1.5,
                  point.padding = 0.5,
                  force         = 100,
                  segment.size  = 0.2,
                  segment.color = "grey50",
                  direction     = "x") +
  geom_label_repel(data         = subset(nba, PTS < 18),
                  nudge_y       = 16 - subset(nba, PTS < 18)$PTS,
                  size          = 4,
                  box.padding   = 0.5,
                  point.padding = 0.5,
                  force         = 100,
                  segment.size  = 0.2,
                  segment.color = "grey50",
                  direction     = "x") +
  scale_x_continuous(expand = expand_scale(mult = c(0.2, .2))) +
  scale_y_continuous(expand = expand_scale(mult = c(0.1, .1))) +
  theme_classic(base_size = 16)

Modifica: per usare ggrepelcon le linee, vedi questo e questo .

Creato il 01/05/2019 dal pacchetto reprex (v0.2.0).


1
! Neat Mi piace molto la prima trama. Ho provato questo con i miei dati e sono contento del risultato tranne per il fatto che la legenda mostra "a" s invece delle forme mostrate nella trama. (Uso una forma estetica per distinguere i punti in base a un fattore)
ragazzo delle api

2
Ho risolto questo problema ormai da (a) estraendo la leggenda di una trama senza la geom_label_repel stackoverflow.com/questions/12041042/... e (b) aggiungendolo poi con gridExtra :: grid.arrange ad una trama con le etichette. Se conosci una soluzione più semplice, lo apprezzerei comunque!
ragazzo delle api

1
@beeguy: non sono sicuro di ottenere quello che mi stai chiedendo, ma di recente ho visto un impegno su ggplot2Dev che ha menzionato cose simili github.com/tidyverse/ggplot2/commit/… . Puoi provare a installare sia la versione dev di ggplot2& ggrepelper vedere se il tuo problema è stato risolto
Tung

1
@beeguy: a proposito c'è anche un lemonpacchetto che è molto buono nel manipolare la leggenda della trama.
Tung,

1
Grazie per la punta
ape ragazzo

10

Invece di usare ifelse come nell'esempio sopra, si possono anche prefiltrare i dati prima dell'etichettatura in base ad alcuni valori di soglia, risparmiando molto lavoro per il dispositivo di stampa:

xlimit <- 36
ylimit <- 24
ggplot(myData)+geom_point(aes(myX,myY))+
    geom_label(data=myData[myData$myX > xlimit & myData$myY> ylimit,], aes(myX,myY,myLabel))
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.