ggplot2 определяет позицию geom_text с помощью обычных "top", "bottom", "left", "right", "center"

Я делаю некоторые графики в ggplot и не могу понять, как изобразить в графике текст без указания x и y позиций.

Допустим, я делаю график, как это.

sp <- ggplot(mpg, aes(hwy, cty, label = "sometext"))+
    geom_point()

Я хочу добавить ярлык, который будет напечатан одинаково на каждом графике. Вызов следующего просто печатает текст при каждом значении x, y aes,

sp + geom_text()

Я мог бы манипулировать данными XY, предоставленными geom_text() чтобы текст оставался в одном и том же относительном положении между графиками, но разве не существует простого способа вызвать положение по умолчанию в таких позициях, как "верх", "низ" и т. д.? Т.е. sp + geom_text(position="top"),

4 ответа

Решение

geom_text хочет построить метки на основе вашего набора данных. Похоже, вы хотите добавить один фрагмент текста на ваш сюжет, в этом случае, annotate это лучший вариант. Чтобы заставить метку появляться в одной и той же позиции независимо от единиц на графике, вы можете воспользоваться Inf ценности:

sp <- ggplot(mpg, aes(hwy, cty, label = "sometext"))+
  geom_point() +
  annotate(geom = 'text', label = 'sometext', x = -Inf, y = Inf, hjust = 0, vjust = 1)
print(sp)

Я избегаю annotate как чума и просто использовать пустой фрейм данных data аргумент в пользу geom_text:

ggplot(mpg, aes(hwy, cty, label = "sometext"))+
  geom_point() +
  geom_text(data=data.frame(), aes(label = 'sometext', x = -Inf, y = Inf),
            hjust = 0, vjust = 1)

В ggpmisc::geom_text_npc то x а также yпозиции даны в единицах npc (0-1). Однако позиции также могут быть указаны как "слова":

d = data.frame(x = rep(c("left", "center", "right"), each = 3),
               y = rep(c("bottom", "middle", "top"), 3))
d$lab = with(d, paste0(x, "-", y))
d
#        x      y           lab
# 1   left bottom   left-bottom
# 2   left middle   left-middle
# 3   left    top      left-top
# 4 center bottom center-bottom
# 5 center middle center-middle
# 6 center    top    center-top
# 7  right bottom  right-bottom
# 8  right middle  right-middle
# 9  right    top     right-top

ggplot(d) +
  geom_text_npc(aes(npcx = x.chr, npcy = y.chr, label = lab))

Конечно, можно написать обертку, но способ определения единиц и обоснования делает его довольно многословным,

library(ggplot2)

qplot(1,1) + 
  annotation_compass('testN') + 
  annotation_compass('testE','E') + 
  annotation_compass('testSW','SW') + 
  annotation_compass('testW','W')

annotation_compass <- function(label,
                               position = c('N','NE','E','SE','S','SW','W','NW'),
                               padding = grid::unit(c(0.5,0.5),"line"), ...){
  position <- match.arg(position)
  x <- switch (position,
    N = 0.5,
    NE = 1,
    E = 1,
    SE = 1,
    S = 0.5, 
    SW = 0,
    W = 0, 
    NW = 0
  )
  y <- switch (position,
               N = 1,
               NE = 1,
               E = 0.5,
               SE = 0,
               S = 0, 
               SW = 0,
               W = 0.5, 
               NW = 1
  )
  hjust <- switch (position,
               N = 0.5,
               NE = 1,
               E = 1,
               SE = 1,
               S = 0.5, 
               SW = 0,
               W = 0, 
               NW = 0
  )
  vjust <- switch (position,
               N = 1,
               NE = 1,
               E = 0.5,
               SE = 0,
               S = 0, 
               SW = 0,
               W = 0.5, 
               NW = 1
  )
  f1 <- switch (position,
                   N = 0,
                   NE = -1,
                   E = -1,
                   SE = -1,
                   S = 0, 
                   SW = 1,
                   W = 1, 
                   NW = 1
  )
  f2 <- switch (position,
                   N = -1,
                   NE = -1,
                   E = 0,
                   SE = 1,
                   S = 1, 
                   SW = 1,
                   W = 0, 
                   NW = -1
  )
  annotation_custom(grid::textGrob(label, 
                                   x=grid::unit(x,"npc") + f1*padding[1] , 
                                   y=grid::unit(y,"npc") + f2*padding[2],
                                   hjust=hjust,vjust=vjust, ...))
}

Решение с использованием бесконечности хорошо и, безусловно, самый простой вариант.

Однако, если вам нужен больший контроль над положением ваших надписей (например, если вы хотите, чтобы они были отцентрированы, или если вы хотите больше места между линией оси и аннотацией), вы можете использовать некоторую математику с min() а также max() заголовков вашего сюжета для создания заголовков по центру сверху, снизу, справа или слева. Приведенный ниже код немного длинен, но все равно будет правильно размещать метки, если значения в вашем графике изменятся. Кроме того, для копирования на другие графики вам не нужно вручную вычислять значения, просто измените имена переменных x и y.

sp <- ggplot(mpg, aes(hwy, cty)) +
  geom_point() +
  theme_classic() +
  annotate("text", label = "top", 
           x = 0.5*(min(mpg$hwy) + max(mpg$hwy)), y = max(mpg$cty), vjust = 1) +
  annotate("text", label = "bottom", 
           x = 0.5*(min(mpg$hwy) + max(mpg$hwy)), y = min(mpg$cty), vjust = 0) +
  annotate("text", label = "right", 
           x =  max(mpg$hwy), y = 0.5*(min(mpg$cty) + max(mpg$cty)), hjust = 1) +
  annotate("text", label = "left", 
            x =  min(mpg$hwy), y = 0.5*(min(mpg$cty) + max(mpg$cty)), hjust = 0)

sp   

Другие вопросы по тегам