Etiquetar puntos en geom_point

178

Los datos con los que estoy jugando provienen de la fuente de Internet que se detalla a continuación.

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

Lo que quiero hacer es crear un gráfico de puntos 2D comparando dos métricas de esta tabla, con cada jugador representando un punto en el gráfico. Tengo el siguiente código:

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

Esto me da lo siguiente:

Trama de la NBA

Lo que quiero es una etiqueta del nombre del jugador justo al lado de los puntos. Pensé que la función de etiqueta en la estética de ggplot haría esto por mí, pero no fue así.

También probé la text()función y la textxy()función desde library(calibrate), ninguna de las cuales parece funcionar con ggplot.

¿Cómo puedo agregar etiquetas de nombre a estos puntos?

Demonio verde
fuente

Respuestas:

280

Uso geom_text, con aesetiqueta. Puedes jugar hjust, vjustpara ajustar la posición del texto.

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

ingrese la descripción de la imagen aquí

EDITAR: Etiqueta solo valores por encima de un cierto umbral:

  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)

gráfico con etiquetas condicionales

estudio
fuente
44
¿Hay alguna forma de cambiar las etiquetas (esquivarlas muy ligeramente), para que no se superpongan?
Thomas Browne
2
No creo que haya ninguna solución fácil dentro ggplot2. Quizás esto te pueda ayudar.
Agstudy
1
¿Hay alguna manera de etiquetar solo los puntos por encima de un cierto valor, por ejemplo PTS mayor que 24 en el gráfico anterior?
ONeillMB1
antes de "esquivar" adecuadamente, considere esto hjust = -0.1para obtener las etiquetas impresas muy ligeramente alejadas del punto de datos.
PatrickT
Para cambiar las etiquetas, considere ggrepel .
Homer White
92

El ggrepelpaquete funciona muy bien para repeler las etiquetas de texto superpuestas lejos una de la otra. Puede usar geom_label_repel()(dibuja rectángulos alrededor del texto) o geom_text_repel()funciones.

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

ingrese la descripción de la imagen aquí

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

Editar: Para usar ggrepelcon líneas, vea esto y esto .

Creado el 01/05/2019 por el paquete reprex (v0.2.0).

Tung
fuente
1
¡Ordenado! Me gusta mucho la primera trama. Intenté esto con mis datos y estoy contento con el resultado, excepto que la leyenda muestra "a" s en lugar de las formas que se muestran en la trama. (Utilizo una forma estética para distinguir puntos de acuerdo a un factor)
abeja
2
Resolví este problema ahora (a) extrayendo la leyenda de un gráfico sin geom_label_repel stackoverflow.com/questions/12041042/… y (b) agregándolo luego con gridExtra :: grid.arrange a un gráfico con las etiquetas. Si conoces una solución más simple, ¡aún te lo agradecería!
abeja
1
@beeguy: no estoy seguro de obtener lo que estás preguntando, pero recientemente vi un commit en ggplot2dev que menciona algo similar github.com/tidyverse/ggplot2/commit/… . Puede intentar instalar tanto la versión de desarrollo de ggplot2& ggrepelpara ver si su problema está solucionado
Tung
1
@beeguy: para tu información, también hay un lemonpaquete que es muy bueno para manipular la leyenda de la trama.
Tung
1
Gracias por el consejo
bee guy
10

En lugar de usar el ifelse como en el ejemplo anterior, también se puede filtrar previamente los datos antes del etiquetado en función de algunos valores de umbral, esto ahorra mucho trabajo para el dispositivo de trazado:

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))
Patrick Dolan
fuente