How to draw a nice arrow in ggplot2

爱⌒轻易说出口 提交于 2019-11-29 05:30:11

问题


I am creating a ggplot chart where I want to have some arrows between two points. The main task is easily done with geom_line(arrow = arrow()). However, I want to have some "beautiful" thick arrows. Resizing the arrow via size= doesn't help since it messes up the head of the arrow completely. I illustrate my Problems:

Create some sample data and a plot:

 NAME <- c("A", "A", "B", "B", "C", "C")
 YEAR <- c(2016, 2011, 2016, 2011, 2016, 2011)
 YEAR <- as.factor(YEAR)
 VALUE <- c(1, 4, 1, 5, 2, 8)
 DATA <- data.frame(NAME, YEAR, VALUE)

ggplot(DATA, aes(x=VALUE, y=NAME)) + 
  geom_point(size=5, aes(colour=YEAR)) +
  geom_line(arrow = arrow(length=unit(0.30,"cm"), ends="first", type = "closed"))

The resulting plot looks like that:

Now I've tried to "thicken" the arrows...

ggplot(DATA, aes(x=VALUE, y=NAME)) + 
  geom_point(size=5, aes(colour=YEAR)) +
  geom_line(arrow = arrow(length=unit(0.30,"cm"), ends="first", type = "closed"), size = 3)

That's the result shown here:

My question: Is there any way to plot some "beautiful" thick arrows?


回答1:


I usually use geom_segment to create arrow. But to do that we need to modify the data from "long" to "wide" format (usually using dcast from reshape2 or data.table package). But this time I tried using base's reshape function.

ggplot(DATA, aes(x=VALUE, y=NAME)) + 
  geom_point(size=5, aes(colour=YEAR)) +
  geom_segment(data = reshape(DATA, v.names="VALUE", idvar = "NAME", timevar = "YEAR", direction = "wide"),
               aes(x=VALUE.2011, xend=VALUE.2016, y=NAME, yend=NAME), size = 2,
               arrow = arrow(length = unit(0.5, "cm")))

EDIT: I just found that same issue pertains for "closed" type arrows. For now, try to save the plot as a vector graph (pdf or svg, using ggsave or Export menu in Plots tab). The result is not "messy".




回答2:


In the latest (and I mean devtools::install_github("tidyverse/ggplot2") latest, as of writing this answer - I'm sure they'll mainline it soon enough) version of ggplot2, there is a linejoin argument to geom_segment. Using linejoin='mitre' will provide crisp edges. See the following for details.




回答3:


There is a very simple, but somewhat "hacky" solution to this.

The idea is to draw the lines first (at the desired thickness, but no arrowheads), but a little bit shorter (can be calculated in some cases). Then just draw a second line, without changing the size with arrowheads. The resulting overlay will look the way you want.



来源:https://stackoverflow.com/questions/38008863/how-to-draw-a-nice-arrow-in-ggplot2

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!