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?
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".
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.
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