如何在 ggplot 中旋转自定义注释?
How to rotate a custom annotation in ggplot?
我想在 ggplot2 中旋转 annotation_custom
中包含的图像。
对于 gganimate
的动画,我想将具有特定角度的图像添加到线图中。不幸的是,annotation_custom
.
中没有 angle
参数
library(tidyverse)
library(grid)
library(png)
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()
结果:
从图中可以看出,所有子弹都是水平对齐的。我想旋转子弹以对应线的斜率。在动画中,线条应该像发射子弹一样出现(这将是另一个问题,因为 annotate_custom
中没有 aes
参数)。
提前感谢您的建议!
您可以使用 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()
关于让子弹跟随直线的问题,见this answer的评论。使对象具有与 ggplot2 中的线相同的斜率是棘手的,因为您需要知道绘图区域的纵横比(据我所知,目前没有在任何地方打印的信息)。您可以通过使用定义的纵横比将绘图制作为文件(pdf 或 png)来解决此问题。然后,您可以使用@Andrie (180/pi * atan(slope * aspect ratio)
) 中的方程式代替我在示例中使用的方程式。可能存在轻微的不匹配,您可以尝试使用常量进行调整。此外,在数据集中的每个点之间线性插值一个点可能是个好主意,因为现在您正在绘制斜率变化的子弹。在动画中这样做效果不佳。相反,在斜率恒定的地方绘制子弹可能会更容易。
我想在 ggplot2 中旋转 annotation_custom
中包含的图像。
对于 gganimate
的动画,我想将具有特定角度的图像添加到线图中。不幸的是,annotation_custom
.
angle
参数
library(tidyverse)
library(grid)
library(png)
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()
结果:
从图中可以看出,所有子弹都是水平对齐的。我想旋转子弹以对应线的斜率。在动画中,线条应该像发射子弹一样出现(这将是另一个问题,因为 annotate_custom
中没有 aes
参数)。
提前感谢您的建议!
您可以使用 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()
关于让子弹跟随直线的问题,见this answer的评论。使对象具有与 ggplot2 中的线相同的斜率是棘手的,因为您需要知道绘图区域的纵横比(据我所知,目前没有在任何地方打印的信息)。您可以通过使用定义的纵横比将绘图制作为文件(pdf 或 png)来解决此问题。然后,您可以使用@Andrie (180/pi * atan(slope * aspect ratio)
) 中的方程式代替我在示例中使用的方程式。可能存在轻微的不匹配,您可以尝试使用常量进行调整。此外,在数据集中的每个点之间线性插值一个点可能是个好主意,因为现在您正在绘制斜率变化的子弹。在动画中这样做效果不佳。相反,在斜率恒定的地方绘制子弹可能会更容易。