Alpha美学显示的是箭头的骨架,而不是普通的形状-如何预防?

问题描述 投票:4回答:1

我的目标是在条形图的末端建立带有箭头的条形图。我选择了geom_segmentarrow。我想将一列映射到透明度上,但是Alpha美学在使用箭头对象时似乎无法正常工作。这是代码段:

tibble(y = c(10, 20, 30), n = c(300, 100, 200), transparency = c(10, 2, 4)) %>% 
  ggplot() + geom_segment(aes(x = 0, xend = n, y = y, yend = y, alpha = transparency), 
                          colour = 'red', size = 10, arrow = arrow(length = unit(1.5, 'cm'), type = 'closed')) +
  scale_y_continuous(limits = c(5, 35))

enter image description here

可以很容易地观察到,arrow对象在alpha值较低的情况下看起来并不好,显示出其骨架而不是普通的透明形状。有没有办法防止它?

r ggplot2 geom-bar
1个回答
1
投票

我们可以创建一个新的几何图形geom_arrowbar,我们可以像使用其他任何几何图形一样使用它,因此在您的情况下,只需执行以下操作即可提供所需的图形:

tibble(y = c(10, 20, 30), n = c(300, 100, 200), transparency = c(10, 2, 4)) %>%
  ggplot() +
  geom_arrowbar(aes(x = n, y = y, alpha = transparency), fill = "red") +
  scale_y_continuous(limits = c(5, 35)) +
  scale_x_continuous(limits = c(0, 350))

enter image description here

并且它包含3个参数,column_widthhead_widthhead_length,如果您不喜欢默认值,可以更改箭头的形状。我们还可以根据需要指定填充颜色和其他美观性:

tibble(y = c(10, 20, 30), n = c(300, 100, 200), transparency = c(10, 2, 4)) %>%
  ggplot() +
  geom_arrowbar(aes(x = n, y = y, alpha = transparency, fill = as.factor(n)),
                column_width = 1.8, head_width = 1.8, colour = "black") +
  scale_y_continuous(limits = c(5, 35)) +
  scale_x_continuous(limits = c(0, 350))

enter image description here

唯一的麻烦是我们必须先写它!

library(tidyverse)

geom_arrowbar <- function(mapping = NULL, data = NULL, stat = "identity",
                          position = "identity", na.rm = FALSE, show.legend = NA,
                          inherit.aes = TRUE, head_width = 1, column_width = 1,
                          head_length = 1, ...) 
{
  layer(geom = GeomArrowBar, mapping = mapping, data = data, stat = stat,
        position = position, show.legend = show.legend, inherit.aes = inherit.aes,
        params = list(na.rm = na.rm, head_width = head_width,
                      column_width = column_width, head_length = head_length, ...))
}

并且它需要一个GeomArrowBar定义:

GeomArrowBar <- ggproto("GeomArrowBar", Geom,
  required_aes = c("x", "y"),
  default_aes = aes(colour = NA, fill = "grey20", size = 0.5, linetype = 1, alpha = 1),
  extra_params = c("na.rm", "head_width", "column_width", "head_length"),
  draw_key = draw_key_polygon,
  draw_panel = function(data, panel_params, coord, head_width = 1,
                        column_width = 1, head_length = 1) {
    hwidth <- head_width / 5
    wid <- column_width / 10
    len <- head_length / 10
    data2 <- data
    data2$x[1] <- data2$y[1] <- 0
    coords2 <- coord$transform(data2, panel_params)
    zero <- coords2$x[1]
    coords <- coord$transform(data, panel_params)
    make_arrow_y <- function(y, wid, hwidth) {
      c(y - wid/2, y - wid/2, y - hwidth/2, y, y + hwidth/2, y + wid/2, y + wid/2)
    }
    make_arrow_x <- function(x, len){
      if(x < zero) len <- -len
      return(c(zero, x - len, x - len , x, x - len, x - len, zero))
    }
    my_tree <- grid::gTree()
    for(i in seq(nrow(coords)))
    {
      my_tree <- grid::addGrob(my_tree, grid::polygonGrob(
        make_arrow_x(coords$x[i], len),
        make_arrow_y(coords$y[i], wid, hwidth),
        default.units = "native",
        gp = grid::gpar(
          col = coords$colour[i],
          fill = scales::alpha(coords$fill[i], coords$alpha[i]),
          lwd = coords$size[i] * .pt,
          lty = coords$linetype[i])))
    }
    my_tree
  }
)

此实现远非完美。它需要大量调整才能消除错误并使其可以投入生产,但是它应该足够好以产生一些不错的图表而无需付出太多的努力]

reprex package(v0.3.0)在2020-03-08创建

© www.soinside.com 2019 - 2024. All rights reserved.