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

69

我正在创建一个ggplot图表,希望在两个点之间添加一些箭头。主要任务可以通过 geom_line(arrow = arrow()) 来轻松完成。然而,我想要一些“美丽”的粗箭头。通过size=调整箭头大小并不能帮助我达到预期的效果,因为这样会完全破坏箭头的头部。我将我的问题举例说明:

创建一些示例数据和图表:

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

最终的图表如下所示:

plot1

现在我尝试“加粗”箭头...

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)

这是此处显示的结果:

plot2

我的问题是:有没有办法绘制一些“漂亮”的粗箭头?


改变箭头的角度并增加长度? - Adam Quek
尝试使用不同的参数进行实验:linetype(可以使线条成为点状或虚线等),arrow length等。 - rar
相关链接:https://dev59.com/4XrZa4cB1Zd3GeqP12Wb - 不幸的是,答案有点像寻宝游戏(我不知道为什么他没有发布完整的修改函数)。此外,我不知道它是否也适用于更新的ggplot版本。 - lukeA
4个回答

78

这里有一些可重现的示例(请尝试运行它们)

一个简单的箭头(即线段):

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

在此输入图片描述

一个简单的曲线箭头

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

在此输入图片描述

可用的箭头类型

您不必理解此代码,只需注意您可以使用的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)

enter image description here

一个直接的箭头,供您切换

这里有一个非常简单的箭头,调整每个参数并查看其作用。

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

输入图像描述

一条弯曲的箭头,供您自行切换

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

输入图片说明


13

我通常使用geom_segment来创建箭头。但为了这样做,我们需要将数据从“长”格式修改为“宽”格式(通常使用reshape2data.table包的dcast)。但这次我尝试使用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")))

arrow.segment

编辑:我刚刚发现同样的问题也适用于“closed”类型的箭头。目前,尝试将图形保存为矢量图(pdf或svg,使用ggsave或在Plots选项卡中使用导出菜单)。结果不会“混乱”。

svg


8
在最新版本的ggplot2中(我的意思是devtools::install_github("tidyverse/ggplot2"),在撰写本答案时为最新版本 - 我相信他们很快就会将其纳入主线),geom_segment有一个linejoin参数。使用linejoin='mitre'可以提供清晰的边缘。有关详细信息,请参见以下内容

1

有一个非常简单但有点“hacky”的解决方法。

这个想法是先画线(以所需的粗细,但没有箭头),但稍微短一点(在某些情况下可以计算)。然后只需画第二条线,不改变大小,带上箭头。最终的重叠部分将会看起来您想要的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接