Как мне сдвинуть метки geom_text на ПОСЛЕ стрелки geom_segment в ggplot2?

#r #ggplot2

#r #ggplot2

Вопрос:

У меня есть порядок NMDS, который я построил с помощью ggplot2. Я добавил векторы среды сверху (из envfit() функции в vegan ), используя geom_segment() и добавил соответствующие метки к тем же координатам, что и используемые сегменты geom_text() (код ниже):

 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

Однако, поскольку метки выровнены по центру, часть метки иногда перекрывается с концом стрелки. Я хочу, чтобы текст НАЧИНАЛСЯ с конца стрелки. В некоторых других случаях, если стрелка направлена вверх, она перемещается в середину текста. По сути, я хочу иметь возможность видеть как заголовок стрелки, так И текст.

Я пытался использовать geom_text_repel() из ggrepel пакета, но размещение кажется случайным (и также будет отталкиваться от других точек или текста на графике (или просто вообще ничего не делать).

[РЕДАКТИРОВАТЬ] Ниже приведены координаты векторов NMDS (это env.arrows объект из примера кода выше):

                 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
 

Комментарии:

1. Поскольку направление подталкивания является радиальным (и, следовательно, зависит от угла относительно оси x), вам может потребоваться вычислить пользовательский радиальный сдвиг для каждой метки. Вы можете сделать это, преобразовав в полярные координаты, добавив радиальный сдвиг, а затем преобразовав обратно в декартовы. Можете ли вы предоставить воспроизводимый пример для работы?

2. Это звучит как разумное решение! Я добавил координаты для векторов в сообщение.

Ответ №1:

В приведенном ниже коде мы создаем функцию радиального сдвига, чтобы отодвинуть метки от стрелок. Сдвиг включает в себя постоянную величину плюс дополнительный сдвиг, который изменяется в зависимости от абсолютного значения косинуса угла наклона метки к оси x. Это связано с тем, что метки с theta углом около 0 или 180 градусов имеют большую длину перекрытия со стрелками, и поэтому их необходимо перемещать дальше, чем метки с theta углом около 90 или 270 градусов.

Возможно, вам придется немного подправить код, чтобы метки располагались именно там, где вы хотите. Кроме того, вам, вероятно, потребуется добавить дополнительную настройку, если имена переменных могут иметь разную ширину.

Еще одно замечание: я превратил имена переменных в столбец данных. Вы также должны сделать это со своими данными , а затем сопоставить этот столбец данных с label аргументом of aes . Использование rownames(env.arrows) для меток выходит за пределы ggplot среды функций к внешнему фрейму данных env.arrows и нарушает сопоставление с фреймом данных, который вы указали в data аргументе geom_text (хотя это, вероятно, не вызовет проблем в данном конкретном случае).

 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
 

введите описание изображения здесь