Oznacz punkty w geom_point

178

Dane, którymi się bawię, pochodzą z poniższego źródła internetowego

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

Chcę utworzyć wykres punktowy 2D porównujący dwie metryki z tej tabeli, gdzie każdy gracz reprezentuje kropkę na wykresie. Mam następujący kod:

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

To daje mi następujące informacje:

Fabuła NBA

To, czego chcę, to etykieta z nazwą gracza tuż obok kropek. Myślałem, że funkcja etykiety w estetyce ggplot zrobi to za mnie, ale tak się nie stało.

Próbowałem także text()funkcji i textxy()funkcji z library(calibrate), z których żadna nie wydaje się działać z ggplot.

Jak mogę dodać etykiety imienne do tych punktów?

Green Demon
źródło

Odpowiedzi:

280

Użyj geom_text, z aesetykietą. Możesz bawić się, hjust, vjustaby dostosować położenie tekstu.

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

wprowadź opis obrazu tutaj

EDYCJA: Etykietuj tylko wartości powyżej określonego progu:

  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)

wykres z etykietami warunkowymi

agstudy
źródło
4
Czy jest jakiś sposób na przesunięcie etykiet (nieznaczne ich unikanie), aby się nie nakładały?
Thomas Browne
2
Myślę, że nie ma w nim łatwego rozwiązania ggplot2. Może to ci pomoże.
agstudy
1
Czy istnieje sposób na oznaczanie punktów tylko powyżej określonej wartości, na przykład PTS większy niż 24 na powyższym wykresie?
ONeillMB1
pomijając prawidłowe „unikanie”, należy to rozważyć, hjust = -0.1aby wydrukowane etykiety były jak najbardziej oddalone od punktu danych.
PatrickT
Aby przesunąć etykiety, rozważ polecenie ggrepel .
Homer White
92

ggrepelPakiet działa świetnie do odstraszania nakładających etykiety tekstowe z dala od siebie. Możesz użyć funkcji geom_label_repel()(rysuje prostokąty wokół tekstu) lub geom_text_repel()funkcji.

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

wprowadź opis obrazu tutaj

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

Edycja: Aby używać ggrepelz liniami, zobacz to i to .

Utworzona 01.05.2019 przez pakiet reprex (v0.2.0).

Tung
źródło
1
Schludny! Bardzo podoba mi się pierwsza fabuła. Wypróbowałem to z moimi danymi i jestem zadowolony z wyniku, poza tym, że legenda pokazuje „a” zamiast kształtów pokazanych na wykresie. (Używam estetycznego kształtu, aby rozróżniać punkty według współczynnika)
pszczółka
2
Rozwiązałem ten problem teraz (a) wyodrębniając legendę działki bez pliku geom_label_repel stackoverflow.com/questions/12041042/ ... i (b) dodając ją następnie za pomocą gridExtra :: grid.arrange do działki z etykietami. Jeśli znasz prostsze rozwiązanie, nadal bym to docenił!
Pszczółka
1
@beeguy: nie jestem pewien, czy rozumiem to, o co pytasz, ale ostatnio widziałem zmianę w programie deweloperskim,ggplot2 która wspomniała o podobnej rzeczy github.com/tidyverse/ggplot2/commit/… . Możesz spróbować zainstalować obie wersje deweloperskie ggplot2&, ggrepelaby sprawdzić, czy problem został rozwiązany
Tung
1
@beeguy: fyi jest też lemonpakiet, który jest bardzo dobry w manipulowaniu legendą fabuły.
Tung
1
Dziękuję za podpowiedź
pszczelarz
10

Zamiast używać ifelse, jak w powyższym przykładzie, można również wstępnie przefiltrować dane przed etykietowaniem w oparciu o pewne wartości progowe, oszczędza to wiele pracy dla urządzenia rysującego:

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
źródło