Mam święceń NMD, które wykreślałem za pomocą GgplOT2. Dodałem wektory środowiskowe na górze (z funkcji envfit() w vegan) przy użyciu geom_segment() i dodano odpowiednie etykiety do tych samych współrzędnych, co segmenty przy użyciu geom_text() (kod poniżej ):

ggplot() +
  geom_point(data = nmds.sites.plot, aes(x = NMDS1, y = NMDS2, col = greening), size = 2) +
  labs(title = "Study Area", 
       col = "Sites") +
  geom_polygon(data = hull.data, aes(x = NMDS1, y = NMDS2, fill = grp, group = grp), alpha = 0.2) +
  scale_fill_discrete(name = "Ellipses", 
                      labels = c("High", "Moderate", "Control")) +
  xlim(c(-1, 1)) +
  guides(shape = guide_legend(order = 1), 
         colour = guide_legend(order = 2)) +
  geom_segment(data = env.arrows, 
               aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               colour = "black", inherit.aes = FALSE) +
  geom_text(data = env.arrows, aes(x = NMDS1, y = NMDS2, label = rownames(env.arrows))) +
  coord_fixed() +
  theme_bw() +
  theme(text = element_text(size = 14))

NMDS Ordination Output

Ponieważ jednak etykiety są uzasadnione centrum, część etykiety czasami nakłada się na końcu strzałki. Chcę mieć tekst zacząć na końcu strzałki. W innych przypadkach, jeśli strzałka wskazuje, popycha do środka tekstu. Zasadniczo chcę być w stanie zobaczyć zarówno głowę strzałki, jak i tekst.

Próbowałem użyć geom_text_repel() z pakietu ggrepel, ale umieszczenie wydaje się losowe (i będzie również odpychać z innych punktów lub tekstu na działce (lub po prostu nic nie rób).

[EDYTOWAĆ] Poniżej znajdują się współrzędne wektory NMDS (to jest obiekt env.arrows z powyższego kodu przykładowego):

                NMDS1       NMDS2
Variable1 -0.46609087  0.27567532
Variable2 -0.21524887 -0.10128795
Variable3  0.59093184  0.03423775
Variable4 -0.00136418  0.46550043
Variable5 -0.30900813 -0.19659929
Variable6  0.53510347 -0.36387227
Variable7  0.66376246 -0.05220685
2
apple 20 listopad 2020, 22:02

1 odpowiedź

Najlepsza odpowiedź

W poniższym kodzie tworzymy funkcję zmiany biegów promieniowej, aby przesunąć etykiety od strzałek. Przesunięcie zawiera stałą ilość plus dodatkową przesunięcie, która zmienia się w zależności od wartości bezwzględnej cosinus kąta etykiety do osi X. Dzieje się tak, ponieważ etykiety z theta w pobliżu 0 lub 180 stopni mają większą długość nakładania się ze strzałkami, a zatem musi być przesuwany dalej, niż etykiety z theta w pobliżu 90 lub 270 stopni.

Może być konieczne przełożenie kodu trochę, aby uzyskać etykiety dokładnie tam, gdzie ich chcesz. Również prawdopodobnie będziesz musiał dodać dodatkową regulację, jeśli nazwy zmiennych mogą mieć różne szerokości.

Jedna dodatkowa uwaga: zmieniłem nazwy zmiennych w kolumnę danych. Powinieneś to zrobić ze swoimi danymi, a następnie mapować tę kolumnę danych do argumentu label o aes. Korzystanie z {{x2} geom_text (Chociaż prawdopodobnie nie spowoduje problemu w tym konkretnym przypadku).

library(tidyverse)
library(patchwork)

# data
env.arrows = read.table(text="    var            NMDS1       NMDS2
Variable1 -0.46609087  0.27567532
Variable2 -0.21524887 -0.10128795
Variable3  0.59093184  0.03423775
Variable4 -0.00136418  0.46550043
Variable5 -0.30900813 -0.19659929
Variable6  0.53510347 -0.36387227
Variable7  0.66376246 -0.05220685", header=TRUE)

# Radial shift function
rshift = function(r, theta, a=0.03, b=0.07) {
  r + a + b*abs(cos(theta))
}

# Calculate shift
env.arrows = env.arrows %>% 
  mutate(r = sqrt(NMDS1^2 + NMDS2^2),
         theta = atan2(NMDS2,NMDS1),
         rnew = rshift(r, theta),
         xnew = rnew*cos(theta),
         ynew = rnew*sin(theta))

p = ggplot() +
  geom_segment(data = env.arrows, 
               aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               colour = "black", inherit.aes = FALSE) +
  geom_text(data = env.arrows, aes(x = NMDS1, y = NMDS2, label = var)) +
  coord_fixed() +
  theme_bw() +
  theme(text = element_text(size = 14))

pnew = ggplot() +
  geom_segment(data = env.arrows, 
               aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.2, "cm")),
               colour = "grey60", inherit.aes = FALSE) +
  geom_text(data = env.arrows, aes(x = xnew, y = ynew, label = var), size=3.5) +
  coord_fixed() +
  theme_bw() +
  theme(text = element_text(size = 14)) +
  scale_x_continuous(expand=expansion(c(0.12,0.12))) +
  scale_y_continuous(expand=expansion(c(0.07,0.07))) 

p / pnew

enter image description here

2
eipi10 5 grudzień 2020, 00:47