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

╄→尐↘猪︶ㄣ 提交于 2019-12-24 17:04:19

问题


I have a graph with many edges between two nodes. When I plot it, I get a warning I don't understand in this context.

This works fine:

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)

But the same graph with one more edge gives a warning:

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)

I fail to see the reason. Why this warning?


回答1:


Searching the igraph package source for the line giving the warning, it seems that the culprit function is autocurve.edges in plot.common.R:

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
}

According to ?igraph.plotting (and the package source) the autocurve.edges function is the called by default to determine how to curve 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.

From early in igraph.plot, we can see that this function is called, being passed the whole graph:

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

This is the source of the warnings on the problematic 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

To delve into why we're seeing these issues, the very first thing this function does is call count.multiple, which returns the number of times each edge is repeated. In the offending graph:

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

Instead of returning c(3, 3, 3) (since the looping edge is repeated 3 times), it's returning c(1.5, 1.5, 1.5). Though I don't see any mention of this in ?count.multiple, this is happening because the count of an edge is divided by 2 if it is a loop (aka an edge from a node to itself), due to the following line in igraph_count_multiple from the structural_properties.c file in the igraph package source:

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

The fact that the warnings are generated is due to a bug -- autocurve.edges was expecting to get c(3, 3, 3) but instead got c(1.5, 1.5, 1.5) from count.multiple due to the loop edges. I think autocurve.edges could actually be reimplemented in pure R using something like:

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

Further, I think the documentation of count.multiple should be updated to mention its special handling of loop edges.

In the meantime, I think the solution in your case would be to manually specify your curvature parameter to avoid the warnings:

plot(gg, edge.curved=FALSE)

Update: Submitted as a pull request to the rigraph project and now merged into the dev branch of the R igraph project: https://github.com/igraph/rigraph/pull/80



来源:https://stackoverflow.com/questions/30556493/why-igraph-plot-warns-that-number-of-items-to-replace-is-not-a-multiple-of-repl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!