如何在ggraph中的边中间绘制箭头

2024-01-22

是否可以使用以下方法在边缘中间绘制箭头ggraph::geom_edge_link(),如果是这样,该怎么办?

而不是像这样在边缘末端绘制箭头:

library(ggraph)
library(tidygraph)
library(dplyr)

create_notable('bull') %>%
  ggraph(layout = 'graphopt') + 
  geom_edge_link(arrow = arrow(length = unit(4, 'mm')), 
                 end_cap = circle(3, 'mm')) +  
  geom_node_point(size = 5) +
  theme_graph()

我希望能够实现这样的目标:

我已经检查过ggraph::geom_edge_link() and grid::arrow()文档,但看不到任何关于如何执行此操作的明显信息。


我自己没有使用过 ggraph 包,但是根据我对底层 grobs 的理解,你可以尝试以下操作:

Step 1。在控制台中运行以下行:

trace(ggraph:::cappedPathGrob, edit = TRUE)

Step 2。在弹出窗口中,更改最后一段代码:

if (is.null(start.cap) && is.null(end.cap)) {
  if (constant) {
    grob(x = x, y = y, id = id, id.lengths = NULL, arrow = arrow, 
         name = name, gp = gp, vp = vp, cl = "polyline")
  }
  else {
    grob(x0 = x[!end], y0 = y[!end], x1 = x[!start], 
         y1 = y[!start], id = id[!end], arrow = arrow, 
         name = name, gp = gp, vp = vp, cl = "segments")
  }
} else {
  gTree(x = x, y = y, id = id, arrow = arrow, constant = constant, 
        start = start, end = end, start.cap = start.cap, 
        start.cap2 = start.cap2, start.captype = start.captype, 
        end.cap = end.cap, end.cap2 = end.cap2, end.captype = end.captype, 
        name = name, gp = gp, vp = vp, cl = "cappedpathgrob")
}

To this:

if(is.null(arrow)) {
  # same code as before, if no arrow needs to be drawn
  if (is.null(start.cap) && is.null(end.cap)) {
    if (constant) {
      grob(x = x, y = y, id = id, id.lengths = NULL, arrow = arrow, 
           name = name, gp = gp, vp = vp, cl = "polyline")
    }
    else {
      grob(x0 = x[!end], y0 = y[!end], 
           x1 = x[!start], y1 = y[!start], 
           id = id[!end], arrow = arrow, 
           name = name, gp = gp, vp = vp, cl = "segments")
    }
  } else {
    gTree(x = x, y = y, id = id, arrow = arrow, constant = constant, 
          start = start, end = end, start.cap = start.cap, 
          start.cap2 = start.cap2, start.captype = start.captype, 
          end.cap = end.cap, end.cap2 = end.cap2, end.captype = end.captype, 
          name = name, gp = gp, vp = vp, cl = "cappedpathgrob")
  }
} else {
  # split x/y/ID values corresponding to each ID into two halves; first half to
  # end with the specified arrow aesthetics; second half (with a repetition of the
  # last value from first half, so that the two halves join up) has arrow set to NULL.
  id.split = split(id, id)
  id.split = lapply(id.split, 
                    function(i) c(rep(TRUE, ceiling(length(i)/2)), 
                                  rep(FALSE, length(i) - ceiling(length(i)/2))))
  id.split = unsplit(id.split, id)
  id.first.half = which(id.split == TRUE)
  id.second.half = which(id.split == FALSE |
                           (id.split == TRUE & c(id.split[-1], FALSE) == FALSE))

  if (is.null(start.cap) && is.null(end.cap)) {
    if (constant) {
      gList(grob(x = x[id.first.half], y = y[id.first.half], id = id[id.first.half], 
                 id.lengths = NULL, arrow = arrow, 
                 name = name, gp = gp, vp = vp, cl = "polyline"),
            grob(x = x[id.second.half], y = y[id.second.half], id = id[id.second.half], 
                 id.lengths = NULL, arrow = NULL, 
                 name = name, gp = gp, vp = vp, cl = "polyline"))

    }
    else {
      # I haven't modified this chunk as I'm not familiar with ggraph,
      # & haven't managed to trigger constant == FALSE condition yet
      # to test out code modifications here
      grob(x0 = x[!end], y0 = y[!end], 
           x1 = x[!start], y1 = y[!start], 
           id = id[!end], arrow = arrow, 
           name = name, gp = gp, vp = vp, cl = "segments")
    }
  } else {
    gList(gTree(x = x[id.first.half], y = y[id.first.half], id = id[id.first.half], 
                arrow = arrow, constant = constant, 
                start = start, end = end, start.cap = start.cap, 
                start.cap2 = start.cap2, start.captype = start.captype, 
                end.cap = end.cap, end.cap2 = end.cap2, end.captype = end.captype, 
                name = name, gp = gp, vp = vp, cl = "cappedpathgrob"),
          gTree(x = x[id.second.half], y = y[id.second.half], id = id[id.second.half],
                arrow = NULL, constant = constant, 
                start = start, end = end, start.cap = start.cap, 
                start.cap2 = start.cap2, start.captype = start.captype, 
                end.cap = end.cap, end.cap2 = end.cap2, end.captype = end.captype, 
                name = name, gp = gp, vp = vp, cl = "cappedpathgrob"))
  }
}

Step 3。正常运行 ggraph 代码:

set.seed(777) # set seed for reproducibility

create_notable('bull') %>%
  ggraph(layout = 'graphopt') + 
  geom_edge_link(arrow = arrow(length = unit(4, 'mm')), 
                 end_cap = circle(0, 'mm')) +
  geom_node_point(size = 5) +
  theme_graph()

# end_cap parameter has been set to 0 so that the segments join up;
# you can also refrain from specifying this parameter completely.

此效果将在当前 R 会话的其余部分中保持不变(即由ggraph将箭头放在中间而不是末尾),直到运行以下行:

untrace(ggraph:::cappedPathGrob)

此后,将恢复正常行为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在ggraph中的边中间绘制箭头 的相关文章

  • R 中的快速 QR 分解

    我有大量矩阵 需要对其执行 QR 分解并存储生成的 Q 矩阵 进行归一化 以便 R 矩阵在其对角线上具有正数 除了使用之外还有其他方法吗qr 功能 这是工作示例 system time Parameters for the matrix t
  • 在 R 中绘制 Likert 变量的堆积条形图

    假设我有一个如下所示的数据框 P Q1 Q2 1 1 4 1 2 2 3 4 3 1 1 4 其中的列告诉我哪个人相应地回答了问题 q1 q2 中的哪一个 这些问题需要按照 4 分李克特量表进行回答 例如 批准 表示 1 稍微批准 表示 2
  • API 请求和curl::curl_fetch_memory(url, handle = handle) 中的错误:SSL 证书问题:证书已过期

    几天前 我运行了代码几个月 没有任何问题 GET url myurl query 今天我遇到一个错误 Error in curl curl fetch memory url handle handle SSL certificate pro
  • 以引用透明的方式从函数的省略号参数中提取符号

    事情又发生了 我正要按下发布答案按钮的问题被删除了 我正在寻找一种方法来从函数的省略号参数中提取绑定到符号的对象的值以及符号 也就是说 我试图以引用透明的方式从省略号中提取符号 我尝试过使用替代品和lazy dots 但没有成功 funct
  • 使用 R 选择第一个非 NA 值

    df lt data frame ID c 1 1 1 2 3 3 3 test c NA 5 5 6 4 NA 7 3 NA 10 9 我想创建一个名为 value 的变量 它是每个单独 ID 测试的第一个非 NA 值 对于只有NA的个体
  • R 中的列乘以子字符串

    假设我有一个数据框 其中包含多个组件及其在多个列中列出的属性 并且我想对这些列运行多个函数 我的方法是尝试将其基于每个列标题中的子字符串 但我无法弄清楚如何做到这一点 下面是数据框的示例 Basket F Type 1 F Qty 1 F
  • 在 R 中使用 lapply 绘制多个数据帧

    我正在尝试使用 lapply 函数绘制多个数据帧 每个数据帧一个图 但是尽管有关此主题的所有帖子我都找不到答案 因为我不断收到错误 图的输出列表为空 我的数据结构如下 df1 lt mtcars gt group by cyl gt tal
  • 朴素贝叶斯分类器仅基于先验概率做出决策

    我试图根据推文的情绪将推文分为三类 买入 持有 卖出 我正在使用 R 和包 e1071 我有两个数据框 一个训练集和一组需要预测情绪的新推文 训练集数据框 text sentiment this stock is a good buy Bu
  • 将数据框中重叠的范围合并到唯一的组中

    我有一个 n 行 3 的数据框 df lt data frame start c 178 400 983 1932 33653 end c 5025 5025 5535 6918 38197 group c 1 1 2 2 3 df sta
  • 基于时间窗口的不规则时间序列的优化滚动函数

    有没有办法使用 rollapply 来自zoo包或类似的东西 优化功能 rollmean rollmedian等 使用基于时间的窗口计算滚动函数 而不是基于大量观察的函数 我想要的很简单 对于不规则时间序列中的每个元素 我想计算一个具有 N
  • 如何仅删除单括号并保留配对的括号

    你好 我亲爱的老师 R 用户朋友们 我最近开始认真学习正则表达式 最近我遇到了一种情况 我们只想保留配对括号 并省略未配对的 这是我的样本数据 structure list t1 c Book Pg 1 Website Online Jou
  • 如何在 R 或 Python 中制作旭日图?

    到目前为止 我一直无法找到一个可以创建旭日图的 R 库约翰 斯塔斯科 http www cc gatech edu gvu ii sunburst 有人知道如何在 R 或 Python 中实现这一点吗 在极坐标投影中使用 matplotli
  • R 的 ggplot2 有 Python API 吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我的问题就像标题一样简单 我想使用R s ggplot2但我所有的数据处理都是在Python 有没有Py
  • 使用 ggmap 截断密度多边形

    我在使用 R ggmap 绘制密度图时遇到问题 我的数据如下所示 gt head W date lat lon dist 1 2010 01 01 31 942 86 659 292 415 2 2010 01 10 32 970 84 1
  • ggplot2:如何标记事件发生的日期

    我想从第二个情节中获取第一个情节的信息 第二张图表示事件发生的天数 它看起来更宽 因为它没有图例 但它是相同的时间尺度 我选择在第一个图中手动分配颜色 I would like to overlay the second plot dots
  • 将不均匀的层次列表转换为数据框

    我认为还没有有人问过这个问题 但是有没有一种方法可以将具有多个级别和不均匀结构的列表的信息组合成 长 格式的数据帧 具体来说 library XML library plyr xml inning lt http gd2 mlb com c
  • 投资决策:R中的NPV、IRR、PB计算

    我正在尝试计算不同数量项目的净现值 NPV 内部收益率 IRR 和投资回收期 PB 时间 以评估哪个投资项目提供最佳回报 到目前为止 我可以为每个项目单独计算几行代码 但我想做的是 编写一个函数 它接受一个包含许多不同项目及其现金流的矩阵
  • 如何在将两根柱子保持在一起的同时熔化柱子?

    我有这种宽格式的数据 我想将其转换为长格式 Cond Construct Line Plant Tube shoot weight shoot Tube root weight root 1 Standard NA NA 2 199 95
  • 如何修复 R 中 Kaplan Meier 图的风险表计算错误

    以下是一个数据帧 其中 6 个参与者中的每一个都有唯一的 record ID 我想绘制一个生存分析图 其中包含感兴趣事件的复发以及在时间间隔 tstart 到 tstop 内 暴露 药物剂量 数值变量 的时间依赖性协变量 每个参与者的最大
  • 在 Shiny 中的用户会话之间共享反应数据集

    我有一个相当大的反应数据集 该数据集是通过轮询文件然后按预定义的时间间隔读取该文件而派生的 数据更新频繁 需要不断重新加载 诚然 重新加载可以增量完成并附加到 R 中的现有对象 但事实并非如此 然而目前 尽管会话中的数据相同 但此操作是针对

随机推荐