알파 미학은 평범한 모양 대신 화살표의 골격을 보여줍니다.


11

나는 막대 끝에 화살표가있는 막대 그림을 만드는 것을 목표로하고 있습니다. 나는 갔다 geom_segment으로 arrow정의했다. 하나의 열을 투명도에 매핑하고 싶지만 화살표 미학에서는 알파 미학이 제대로 작동하지 않는 것 같습니다. 다음은 코드 스 니펫입니다.

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

여기에 이미지 설명을 입력하십시오

쉽게 관찰 할 수있는 arrow오브젝트가 낮은 값으로 잘 보이지 않는 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-10, y = y, yend = y, alpha = transparency), colour = 'red', size = 10) + geom_segment(aes(x = n-0.1, xend = n, y = y, yend = y, alpha = transparency), colour = 'red', size = 1, arrow = arrow(length = unit(1.5, 'cm'), type = 'closed')) + scale_y_continuous(limits = c(5, 35))
Wolfgang Arnold

이것은 실제로 흥미 롭습니다. 겹치는 "골격"의 정확한 영역을 계산하지 않고 각 영역에 대해 프로그래밍 방식으로 알파를 설정하지 않으면 피할 수 없다고 생각합니다 (끔찍한 핵이 될 것입니다). 정말로 투명한 화살표를 원한다면 다른 접근법은 1) 세그먼트와 2) 인접한 삼각형을 그리는 것입니다. (이것은 나에게 꽤 해킹처럼 보인다).
Tjebo

2
화살표의 평평한 투명도를 갖는 것이 좋을 것입니다. 나는 이것이 ggplot의 끝에서 어떤 행동으로 인한 것이 아니라고 생각하지만 'grid'패키지가 화살표를 그리는 방법 (ggplot2가 의존하는)과 관련이있는 것 같습니다.
teunbrand

답변:


13

우리는 geom_arrowbar다른 geom처럼 사용할 수 있는 새로운 geom을 만들 수 있습니다. 따라서 귀하의 경우 다음을 수행하여 원하는 플롯을 제공합니다.

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

여기에 이미지 설명을 입력하십시오

그리고 3 개 개의 매개 변수를 포함 column_width, head_width그리고 head_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))

여기에 이미지 설명을 입력하십시오

우리가 그것을 먼저 써야하는 유일한 걸림돌!

의 실시 예에 따라 연장 ggplot2 비네팅 , 우리는를 정의 할 수 geom_arrowbar우리는 화살표의 모양을 제어하는 우리의 3 개 파라미터를 전달할 수 있도록하려는 제외한 다른 기하 구조가 정의되는 것과 동일한 방식이다. 이것들은 params결과 layer객체 목록에 추가되며 화살표 레이어를 만드는 데 사용됩니다.

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입니다. 이것은 사실상 ggproto클래스 정의입니다. 가장 중요한 부분은 draw_panel멤버 함수로, 데이터 프레임의 각 줄을 가져 와서 화살표 모양으로 변환합니다. x 및 y 좌표와 화살표의 모양에 대한 다양한 모양 매개 변수에서 해결되는 몇 가지 기본 수학 후에 grid::polygonGrob데이터의 각 줄에 대해 하나 를 생성 하여에 저장합니다 gTree. 이것은 레이어의 그래픽 구성 요소를 형성합니다.

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
    zero <- coord$transform(data2, panel_params)$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}
)

이 구현은 완벽하지 않습니다. 합리적인 기본 축 제한 및 기능과 같은 중요한 기능이 누락되어 coord_flip있으며 화살촉이 전체 열보다 길면 미학적 인 결과가 나옵니다 (어쨌든 그러한 상황에서 그러한 음모를 사용하고 싶지 않을 수도 있음) . 그러나 음수 값이 있으면 화살표가 왼쪽을 가리키는 것이 현명합니다. 더 나은 구현은 빈 화살표 머리에 대한 옵션을 추가 할 수도 있습니다.

요컨대, 이러한 (및 기타) 버그를 해결하고 생산 준비가 되려면 많은 조정이 필요하지만 그 동안 너무 많은 노력을 기울이지 않고도 멋진 차트를 만드는 것이 좋습니다.

reprex 패키지 (v0.3.0)로 2020-03-08에 작성


4

geom_gene_arrow에서 사용할 수 있습니다library(gggenes)

data.frame(y=c(10, 20, 30), n=c(300, 100, 200), transparency=c(10, 2, 4)) %>% 
  ggplot() + 
  geom_gene_arrow(aes(xmin = 0, xmax = n, y = y, alpha = transparency), 
                  arrowhead_height = unit(6, "mm"), fill='red') +
  scale_y_continuous(limits = c(5, 35))

여기에 이미지 설명을 입력하십시오


2
이것은 내가 방금 재발 명 한 바퀴 일 것입니다! ;)
Allan Cameron
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.