如何在ggplot2中制作以不同宽高比保留角度的片段?

时间:2017-12-14 13:51:50

标签: r ggplot2

我想将风的大小和方向绘制为矢量。问题是,如果轴具有不同的比率或具有不同的类型(例如,x =日期,y =高度),则推荐用于向量(geom_segment()geom_spoke())的常用geom会改变角度。我目前的解决方法是每this answer使用geom_text(label = "→", ...)

问题是这个解决方案很慢,并且基于文本的箭头的大小没有很好地映射到风的大小。此外,重要的是,由于某种原因,导出为PDF时失败。我想要一个基于适当细分的解决方案。在geom调用中工作,我知道即使一个轴的类别与另一个轴不同,我也可以使用绘图的原始坐标绘制正确的段。我目前的尝试是:


library(ggplot2)

geom_arrow2 <- function(mapping = NULL, data = NULL, stat = "identity",
                              position = "identity", na.rm = FALSE, show.legend = NA,
                              inherit.aes = TRUE, scale = 1,...) {
    layer(geom = GeomArrow2,
          mapping = mapping,
          data = data,
          stat = stat,
          position = position,
          show.legend = show.legend,
          inherit.aes = inherit.aes,
          params = list(na.rm = na.rm, scale = scale, ...)
    )
}
GeomArrow2 <- ggplot2::ggproto("GeomArrow2", Geom,
   required_aes = c("x", "y", "mag", "angle"),
   default_aes = ggplot2::aes(color = "black", scale = 1),
   draw_key = draw_key_polygon,
   draw_panel = function(data, panel_scales, coord, scale = 1) {
       coords <- coord$transform(data, panel_scales)

       Mmag <- max(coords$mag)
       coords$mag <- with(coords, mag/Mmag*coords$scale)

       coords$dx <- with(coords, cos(angle)*mag)*scale
       coords$dy <- with(coords, sin(angle)*mag)*scale

       pol <- grid::polylineGrob(x = c(coords$x,
                                        coords$x + coords$dx),
                                  y = c(coords$y,
                                        coords$y + coords$dy),
                                  default.units = "npc",
                                  arrow = grid::arrow(angle = 15, length = unit(0.5, "lines")),
                                  gp = grid::gpar(col = coords$colour),
                                  id = rep(seq(nrow(coords)), 2))
       pol

   })


field <- expand.grid(x = seq.Date(as.Date("2017-01-01"), as.Date("2017-01-31"), "2 days"),
                     y = 1:10)
field$u <- rnorm(nrow(field))
field$v <- rnorm(nrow(field))
field$V <- with(field, sqrt(u^2 + v^2))
field$dir <- with(field, atan2(v, u))*180/pi

ggplot(field, aes(x, y)) +
    geom_point() +
    geom_arrow2(aes(mag = V, angle = dir), scale = 0.5)

但现在问题又回来了,不同的宽高比扭曲了箭头的实际角度。我一直在尝试不同的事情,并发现使用"snpc"单位而不是"npc"来保留角度,但是位置会发生偏移,所以这并不好。

如果我能获得geom调用内的情节宽高比的信息,那就太棒了。

任何帮助将非常感谢。

1 个答案:

答案 0 :(得分:2)

你可以混合单位,

xx <- unit.c(unit(coords$x, "npc"), 
             unit(coords$x, "npc") + unit(coords$dx, "snpc"))
yy <- unit.c(unit(coords$y, "npc"), 
             unit(coords$y, "npc") + unit(coords$dy, "snpc"))
pol <- grid::polylineGrob(x = xx, y = yy,
                          default.units = "npc",
                          arrow = grid::arrow(angle = 15, length = unit(0.5, "lines")),
                          gp = grid::gpar(col = coords$colour),
                          id = rep(seq(nrow(coords)), 2))