Étiqueter les points dans geom_point

185

Les données avec lesquelles je joue proviennent de la source Internet répertoriée ci-dessous

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

Ce que je veux faire, c'est créer un graphique de points 2D comparant deux métriques de ce tableau, chaque joueur représentant un point sur le graphique. J'ai le code suivant:

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

Cela me donne ce qui suit:

Terrain NBA

Ce que je veux, c'est une étiquette du nom du joueur juste à côté des points. Je pensais que la fonction d'étiquette dans l'esthétique de ggplot ferait cela pour moi, mais ce n'est pas le cas.

J'ai également essayé la text()fonction et la textxy()fonction from library(calibrate), dont aucune ne semble fonctionner avec ggplot.

Comment puis-je ajouter des étiquettes de nom à ces points?

Démon vert
la source

Réponses:

293

Utilisation geom_text, avec aesétiquette. Vous pouvez jouer avec hjust, vjustpour ajuster la position du texte.

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

entrez la description de l'image ici

EDIT: Nommez uniquement les valeurs au-dessus d'un certain seuil:

  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)

graphique avec des étiquettes conditionnelles

étude
la source
4
Existe-t-il un moyen de déplacer les étiquettes (les esquiver légèrement), de sorte qu'elles ne se chevauchent pas?
Thomas Browne
2
Je ne pense pas qu'il y ait de solution facile à l'intérieur ggplot2. Peut - être que cela peut vous aider.
étude
1
Est-il possible d'étiqueter uniquement les points au-dessus d'une certaine valeur, par exemple PTS supérieur à 24 sur le graphique ci-dessus?
ONeillMB1
À moins d '«esquiver» correctement, considérez ceci hjust = -0.1pour éloigner légèrement les étiquettes imprimées du point de données.
PatrickT
1
Pour déplacer les étiquettes, pensez à ggrepel .
Homer White
100

Le ggrepelpackage fonctionne très bien pour repousser les étiquettes de texte qui se chevauchent les unes des autres. Vous pouvez utiliser geom_label_repel()(dessine des rectangles autour du texte) ou des geom_text_repel()fonctions.

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

entrez la description de l'image ici

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

Edit: à utiliser ggrepelavec des lignes, voyez ceci et cela .

Créé le 01/05/2019 par le package reprex (v0.2.0).

Tung
la source
1
Soigné! J'aime vraiment la première intrigue. J'ai essayé cela avec mes données et je suis satisfait du résultat, sauf que la légende montre "a" au lieu des formes montrées dans le tracé. (J'utilise une forme esthétique pour distinguer les points en fonction d'un facteur)
bee guy
2
J'ai résolu ce problème maintenant en (a) extrayant la légende d'un tracé sans le geom_label_repel stackoverflow.com/questions/12041042/… et (b) en l'ajoutant ensuite avec gridExtra :: grid.arrange à un tracé avec les étiquettes. Si vous connaissez une solution plus simple, je l'apprécierais toujours!
bee guy
1
@beeguy: je ne suis pas sûr de comprendre ce que vous demandez, mais j'ai récemment vu un commit sur le développement ggplot2qui mentionnait une chose similaire github.com/tidyverse/ggplot2/commit/… . Vous pouvez essayer d'installer les deux versions de développement de ggplot2& ggrepelpour voir si votre problème est résolu
Tung
1
@beeguy: pour info, il y a aussi un lemonpackage qui est très bon pour manipuler la légende de l'intrigue.
Tung
1
Mais où est le monstre grec?
Abel Callejo
10

Au lieu d'utiliser l'ifelse comme dans l'exemple ci-dessus, on peut également pré-filtrer les données avant l'étiquetage en fonction de certaines valeurs de seuil, cela économise beaucoup de travail pour le dispositif de traçage:

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
la source