为什么 igraph plot 警告说 "number of items to replace is not a multiple of replacement length"?

Why igraph plot warns that "number of items to replace is not a multiple of replacement length"?

我有一个图,两个节点之间有很多边。当我绘制它时,我收到一条我在这种情况下不理解的警告。

这很好用:

library(igraph)
gg <- graph.empty(n=0, directed=TRUE)
gg <- gg + vertex("10501")
gg <- gg + edge("10501", "10501")
gg <- gg + edge("10501", "10501")
plot(gg)

但是多一条边的同一张图给出警告:

gg <- graph.empty(n=0, directed=TRUE)
gg <- gg + vertex("10501")
gg <- gg + edge("10501", "10501")
gg <- gg + edge("10501", "10501")
gg <- gg + edge("10501", "10501")
plot(gg)

我看不出原因。为什么出现此警告?

igraph 包源中搜索发出警告的行,罪魁祸首似乎是 plot.common.R 中的 autocurve.edges:

autocurve.edges <- function(graph, start=0.5) {
  cm <- count.multiple(graph)
  el <- apply(get.edgelist(graph, names=FALSE), 1, paste, collapse=":")
  ord <- order(el)
  res <- numeric(length(ord))

  p <- 1
  while (p <= length(res)) {
    m <- cm[ord[p]]
    idx <- p:(p+m-1)
    if (m==1) {
      r <- 0
    } else {
      r <- seq(-start, start, length=m)
    }
    res[ord[idx]] <- r
    p <- p + m
  }
  res
}

根据 ?igraph.plotting(和包源),默认调用 autocurve.edges 函数来确定如何弯曲边缘:

By default the vector specifying the curvatire is calculated via a call to the autocurve.edges function. This function makes sure that multiple edges are curved and are all visible. This parameter is ignored for loop edges.

igraph.plot 的早期开始,我们可以看到调用了这个函数,并传递了整个图形:

curved             <- params("edge", "curved")
if (is.function(curved)) { curved <- curved(graph) }

这是有问题的图表上警告的来源:

autocurve.edges(gg)
# [1] -0.5 -0.5  0.0
# Warning messages:
# 1: In res[ord[idx]] <- r :
#   number of items to replace is not a multiple of replacement length
# 2: In res[ord[idx]] <- r :
#   number of items to replace is not a multiple of replacement length

为了深入研究为什么会出现这些问题,此函数所做的第一件事是调用 count.multiple,其中 returns 每条边的重复次数。在有问题的图表中:

count.multiple(gg)
# [1] 1.5 1.5 1.5

它没有返回 c(3, 3, 3)(因为循环边重复了 3 次),而是返回了 c(1.5, 1.5, 1.5)。虽然我在 ?count.multiple 中没有看到任何提及,但这是因为如果它是一个循环(也就是从节点到自身的边),则边的计数除以 2,原因如下igraph 包源中 structural_properties.c 文件中的 igraph_count_multiple 行:

/* for loop edges, divide the result by two */
if (to == from) VECTOR(*res)[i] /= 2;

生成警告的事实是由于一个错误——autocurve.edges 期望得到 c(3, 3, 3) 但由于 count.multiple 而得到 c(1.5, 1.5, 1.5)循环边缘。我认为 autocurve.edges 实际上可以使用类似的东西在纯 R 中重新实现:

autocurve.edges <- function(graph, start=0.5) {
  el <- apply(get.edgelist(graph, names=FALSE), 1, paste, collapse=":")
  ave(rep(NA, length(el)), el, FUN=function(x) {
    if (length(x) == 1) {
      return(0)
    } else {
      return(seq(-start, start, length=length(x)))
    }
  })
}

此外,我认为 count.multiple 的文档应该更新以提及其对循环边缘的特殊处理。

与此同时,我认为您的解决方案是手动指定曲率参数以避免出现警告:

plot(gg, edge.curved=FALSE)

更新: 作为 pull request 提交给 rigraph 项目,现在合并到 R igraph 项目的 dev 分支:https://github.com/igraph/rigraph/pull/80