You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggraph的边的指定相对位置绘制箭头?

自定义边箭头位置可视化所有权分配(基于ggraph)

我有一个图,每条边代表节点间的所有权分配情况。例如节点"A"与"B"之间的边,"A"拥有90%的所有权,"B"仅拥有10%。希望通过在边的对应相对位置放置箭头来可视化该分配,优先使用ggraph实现,也接受其他方案。

默认情况下,箭头会放置在边的末端,如下方代码生成的图所示:

library(ggraph)
library(ggplot2)

# 构建边数据
edges = data.frame(from = c("A", "B", "C"),
                   to = c("C","A", "B"),
                   relative_position = c(.6,.1, .4))

# 创建图对象
graph <- as_tbl_graph(edges)

# 使用ggraph绘图
ggraph(graph) + 
  geom_edge_link(
    arrow = arrow()
  ) + 
  geom_node_label(aes(label = name))

默认箭头位置

我想要的效果如下方图所示。之前找到过讨论将箭头移到边中间的文章,但该方法无法设置自定义相对位置。
目标箭头位置


解决方案:拆分边实现自定义箭头位置

ggraph的geom_edge_link本身不支持直接设置箭头的自定义位置,但可以通过将每条边拆分为两段的方式实现:一段从起点到箭头位置(带箭头),另一段从箭头位置到终点(无箭头)。以下是完整实现代码:

library(ggraph)
library(ggplot2)
library(tidygraph)

# 原始边数据
edges <- data.frame(
  from = c("A", "B", "C"),
  to = c("C", "A", "B"),
  relative_position = c(.6, .1, .4)
)

# 创建图对象并生成布局(这里用圆形布局匹配示例)
graph <- as_tbl_graph(edges)
layout <- create_layout(graph, layout = "circle")

# 提取节点的坐标信息
node_coords <- layout$nodes[, c("x", "y", "name")]
names(node_coords) <- c("x_from", "y_from", "name")

# 合并边数据与起点、终点的坐标
edge_coords <- edges %>%
  left_join(node_coords, by = c("from" = "name")) %>%
  left_join(node_coords, by = c("to" = "name"), suffix = c("_from", "_to"))

# 计算箭头位置的坐标(基于相对位置)
edge_coords <- edge_coords %>%
  mutate(
    x_arrow = x_from + relative_position * (x_to - x_from),
    y_arrow = y_from + relative_position * (y_to - y_from)
  )

# 拆分边为两段:起点→箭头位置,箭头位置→终点
edges_segment1 <- edge_coords %>%
  select(from = from, to = "arrow_pos", x_from, y_from, x_to = x_arrow, y_to = y_arrow) %>%
  mutate(segment = "to_arrow")

edges_segment2 <- edge_coords %>%
  select(from = "arrow_pos", to = to, x_from = x_arrow, y_from = y_arrow, x_to, y_to) %>%
  mutate(segment = "from_arrow")

# 合并两段边并添加唯一ID(避免ggraph绘图报错)
all_edges <- bind_rows(edges_segment1, edges_segment2) %>%
  mutate(id = row_number())

# 创建包含拆分边的图对象
graph_custom <- tbl_graph(
  nodes = bind_rows(node_coords, data.frame(name = "arrow_pos", x = NA, y = NA)), # 临时节点,不显示
  edges = all_edges,
  directed = FALSE
)

# 绘制最终图形
ggraph(graph_custom, layout = "manual", x = x, y = y) +
  # 绘制箭头到终点的线段(无箭头)
  geom_edge_link(
    data = function(x) filter(x, segment == "from_arrow"),
    color = "black"
  ) +
  # 绘制起点到箭头位置的线段(带箭头)
  geom_edge_link(
    data = function(x) filter(x, segment == "to_arrow"),
    arrow = arrow(length = unit(4, "mm")),
    color = "black"
  ) +
  # 绘制原始节点标签,隐藏临时节点
  geom_node_label(
    data = function(x) filter(x, name != "arrow_pos"),
    aes(label = name),
    size = 5
  ) +
  theme_void()

说明

  • 代码中通过relative_position参数(0对应起点,1对应终点)精准控制箭头的位置,完全匹配你的需求
  • 示例用了圆形布局,你可以根据需要替换为其他布局(比如layout = "kk")
  • 拆分边的方式兼容性强,适用于大多数ggraph支持的布局类型

内容的提问来源于stack exchange,提问作者jhfodr76

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 01:01:06