アルファの美学は単純な形ではなく矢の骨格を示しています-それを防ぐ方法は?


11

バーの端に矢印のあるバープロットを作成することを目指しています。私は定義されたと行きましgeom_segmentarrow。1つの列を透明度にマップしたいのですが、アルファの美観が矢印オブジェクトでうまく機能しないようです。コードスニペットは次のとおりです。

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))
ヴォルフガング・アーノルド

これは確かに興味深いです。これは、重複する「スケルトン」の正確な領域を計算せずに、プログラムで各領域にアルファを設定することで回避できないと思います(これはひどいハックになります)。本当に透明な矢印が本当に必要な場合は、別のアプローチとして、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_widthhead_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つのパラメータを渡すことができるようにしたい除いて、他のgeomが定義されているのと同じように。これらは、矢印レイヤーを作成するために使用される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, ...))
}

今残っている「すべて」はa GeomArrowBarが何であるかを定義することです。これは事実上ggprotoクラス定義です。その最も重要な部分はdraw_panelメンバー関数で、データフレームの各行を取り、それを矢印の形に変換します。x座標とy座標、およびさまざまな形状パラメーターから矢印の形状を計算するためのいくつかの基本的な計算grid::polygonGrobを行った後、データの各行に1つを生成してに格納し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、矢印の頭が列全体よりも長い場合、美的でない結果が生成されます(このようなプロットをこのような状況で使用したくない場合もあります)。 。ただし、負の値の場合は、左向きの矢印が表示されます。より良い実装では、空の矢印のオプションを追加することもできます。

つまり、これらの(およびその他の)バグを解決して本番環境で使用できるようにするには、多くの微調整が必​​要になりますが、それまでの間、あまり手間をかけずに優れたグラフを作成するのに十分です。

2020-03-08にreprexパッケージ(v0.3.0)によって作成されました


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
これは、私が再考したばかりのホイールに違いありません。;)
アランキャメロン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.