Ми можемо створити нового геома, 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))
І вона містить 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
, і це дасть неестетичні результати, якщо головки стрілок будуть довші, ніж цілий стовпець (хоча ви, можливо, не хочете використовувати такий сюжет у цій ситуації) . Однак стрілка ліворуч буде вказувати ліворуч, якщо у вас є негативне значення. Краща реалізація може також додати варіант для порожніх головок стрілок.
Коротше кажучи, знадобиться багато налаштувань, щоб виправити ці (та інші) помилки та зробити їх готовими до виробництва, але це досить добре, щоб тим часом створити кілька приємних діаграм, не заважаючи занадто багато зусиль.
Створено 2020-03-08 пакетом reprex (v0.3.0)
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))