如何在ggplot2中制作以不同纵横比保留角度的段

如何在ggplot2中制作以不同纵横比保留角度的段

本文介绍了如何在ggplot2中制作以不同纵横比保留角度的段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将风的大小和方向绘制为矢量.问题是,如果轴的比率不同或类型不同(例如,x =日期,y =高度),则推荐用于矢量(geom_segment()geom_spoke())的常用几何形状会改变角度.我当前的解决方法是根据每个此答案使用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调用中绘图的长宽比的信息,那将是很好的.

任何帮助将不胜感激.

解决方案

您可以混合使用单位,

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))

I want to plot wind magnitude and direction as vectors. The problem is that the usual geoms recommended for vectors (geom_segment() or geom_spoke()) change angle if the axes have different ratios or are of different type (for example, x = date, y = height). My current workaround is using geom_text(label = "→", ...) per this answer.

The problem is that this solution is slow and the size of the text based arrow is not well mapped to the magnitude of the wind. Also, importantly, for some reason it fails when exporting to PDF. I want a solution based on proper segments. Working within the geom call, I know I can work with the native coordinates of the plot to draw proper segments even if one axis is of different class than the other. My current attempt is this:


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)

But now the problem is back and different aspect ratios distort the actual angle of the arrows. I've been trying different things and found out that using "snpc" units instead of "npc" preserves angles, but the position is shifted, so that's no good.

If I could get information of the aspect ratio of the plot inside the geom call that would be great.

Any help will be very appreciated.

解决方案

you can mix units,

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))

这篇关于如何在ggplot2中制作以不同纵横比保留角度的段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 00:13