简体   繁体   English

如何在ggplot2中绘制一个漂亮的箭头

[英]How to draw a nice arrow in ggplot2

I am creating a ggplot chart where I want to have some arrows between two points.我正在创建一个ggplot图表,我想在两点之间有一些箭头。 The main task is easily done with geom_line(arrow = arrow()) .使用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.通过size=调整箭头size=无济于事,因为它完全弄乱了箭头的头部。 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:结果图如下所示:

情节1

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:这是这里显示的结果:

情节2

My question: Is there any way to plot some "beautiful" thick arrows?我的问题:有没有办法绘制一些“漂亮”的粗箭头?

Here are some reproducible examples (try running them)以下是一些可重现的示例(尝试运行它们)

A Simple arrow (ie line segment): 一个简单的箭头(即线段):

library(dplyr)
library(ggplot2)

# Create a scatter plot
i <- ggplot(mtcars, aes(wt, mpg)) + geom_point()

# Add arrow
i + geom_segment(aes(x = 5, y = 30, xend = 3.5, yend = 25),
                  arrow = arrow(length = unit(0.5, "cm")))

在此处输入图片说明

A Simple curved arrow一个简单的弯曲箭头

b <- ggplot(mtcars, aes(wt, mpg)) +
  geom_point()

df <- data.frame(x1 = 2.62, x2 = 3.57, y1 = 21.0, y2 = 15.0)

b + geom_curve(
  aes(x = x1, y = y1, xend = x2, yend = y2),
  data = df,
  arrow = arrow(length = unit(0.03, "npc"))
)

在此处输入图片说明

Available Arrow Types可用的箭头类型

You don't have to understand this code, but simply note the lineend , and linejoin options available to you您不必理解此代码,只需注意可用的lineendlinejoin选项

df2 <- expand.grid(
  lineend = c('round', 'butt', 'square'),
  linejoin = c('round', 'mitre', 'bevel'),
  stringsAsFactors = FALSE
)
df2 <- data.frame(df2, y = 1:9)

ggplot(df2, aes(x = 1, y = y, xend = 2, yend = y, label = paste(lineend, linejoin))) +
  geom_segment(
    lineend = df2$lineend, linejoin = df2$linejoin,
    size = 3, arrow = arrow(length = unit(0.3, "inches"))
  ) +
  geom_text(hjust = 'outside', nudge_x = -0.2) +
  xlim(0.5, 2)

在此处输入图片说明

A Straight Arrow to Toggle for Yourself为自己切换的直箭头

Here is a very simple arrow to adjust each parameter and see what it does这是一个非常简单的箭头来调整每个参数并查看它的作用

ggplot(iris) +
  geom_segment(
    x = 1, y = 1,
    xend = 4, yend = 7,
    lineend = "round", # See available arrow types in example above
    linejoin = "round",
    size = 2, 
    arrow = arrow(length = unit(0.3, "inches")),
    colour = "#EC7014" # Also accepts "red", "blue' etc
  ) + 
  scale_x_continuous(limits = c(0, 10)) +
  scale_y_continuous(limits = c(0, 10))

在此处输入图片说明

A Curved Arrow to Toggle for Yourself为自己切换的弯曲箭头

# Nicer curve
b <- ggplot(mtcars, aes(wt, mpg)) +
  geom_point()

b + geom_curve(
  aes(x = 3, y = 22, xend = 3.5, yend = 15),
  arrow = arrow(
    length = unit(0.03, "npc"), 
                type="closed" # Describes arrow head (open or closed)
    ),
  colour = "#EC7014",
  size = 1.2,
  angle = 90 # Anything other than 90 or 0 can look unusual
)

在此处输入图片说明

I usually use geom_segment to create arrow.我通常使用geom_segment来创建箭头。 But to do that we need to modify the data from "long" to "wide" format (usually using dcast from reshape2 or data.table package).但要做到这一点,我们需要从“长”数据修改为“宽”的格式(通常使用dcastreshape2data.table包)。 But this time I tried using base 's reshape function.但是这次我尝试使用basereshape函数。

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

箭头.segment

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).现在,尝试将绘图保存为矢量图(pdf 或 svg,使用 Plots 选项卡中的ggsave或 Export 菜单)。 The result is not "messy".结果并不“乱”。

svg

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 .在最新的(我的意思是devtools::install_github("tidyverse/ggplot2")最新的,因为写这个答案-我敢肯定,他们会主线它很快)的版本ggplot2 ,有linejoin参数geom_segment Using linejoin='mitre' will provide crisp edges.使用linejoin='mitre'将提供清晰的边缘。 See the following for details .有关详细信息,请参阅以下内容

There is a very simple, but somewhat "hacky" solution to this.对此有一个非常简单但有点“hacky”的解决方案。

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.生成的叠加层将看起来像您想要的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM