Как повернуть пользовательскую аннотацию в ggplot?

Я хотел бы повернуть изображение, включенное в annotation_custom в ggplot2.

Для анимации с gganimate Я хотел бы добавить изображения с определенными углами к линейному графику. К сожалению, нет angle параметр в annotation_custom,

library(tidyverse)

gundf <- tibble(year = c(1999:2017),
                deaths = c(28874, 28663, 29573, 30242, 30136, 29569, 30694, 30896, 
                           31224, 31593, 31347, 31672, 32351, 33563, 33636, 33594, 
                           36252, 38658, 39773))

# Download png from cl.ly/47216db435d3
bullet <- rasterGrob(readPNG("bullet.png"))

gundf %>% 
  ggplot(aes(x=year, y=deaths)) + 
  geom_line(size=1.2) +
  mapply(function(x, y) {
    annotation_custom(bullet, xmin = x-0.5, 
                              xmax = x+0.5, 
                              ymin = y-500, 
                              ymax = y+500)
                         },
    gundf$year, gundf$deaths) + 
  theme_minimal()

Результат:

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

Заранее спасибо за ваши предложения!

0 ответов

Вы можете использовать пакет magick для вращения файла png:

library(magick)

bullet <- magick::image_read("bullet.png")

## To remove white borders from the example png
bullet <- magick::image_background(bullet, "#FF000000")

## Create angle column
gundf$angle <- seq(0,360, length.out = nrow(gundf))

## Plot
gundf %>% 
  ggplot(aes(x=year, y=deaths)) + 
  geom_line(size=1.2) +
  mapply(function(x, y, angle) {
    annotation_custom(rasterGrob(magick::image_rotate(bullet, angle)),
                              xmin = x-0.5, 
                              xmax = x+0.5, 
                              ymin = y-500, 
                              ymax = y+500)
                         },
    gundf$year, gundf$deaths, gundf$angle) + 
  theme_minimal()

Что касается вашего вопроса о том, как сделать так, чтобы пуля следовала за линией, см. Комментарии к этому ответу. Сделать объекты с таким же наклоном, что и у линии в ggplot2, довольно сложно, потому что вам нужно знать соотношение сторон области черчения (насколько мне известно, информацию, которая нигде не печатается в данный момент). Вы можете решить эту проблему, превратив свой график в файл (pdf или png), используя определенное соотношение сторон. Затем вы можете использовать уравнение из @Andrie (180/pi * atan(slope * aspect ratio)) вместо того, который я использовал в примере. Там может быть небольшое несоответствие, которое вы можете попытаться скорректировать с помощью константы. Кроме того, было бы неплохо линейно интерполировать одну точку между каждой точкой в ​​вашем наборе данных, потому что теперь вы строите график с изменением наклона. Делать это в анимации будет плохо. Вероятно, было бы легче построить пулю там, где наклон постоянный.

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