使用 R 的 igraph 中的迭代器 V 和 E 如何工作?

发布于 2024-12-01 14:37:20 字数 595 浏览 0 评论 0原文

我已经浏览了 V 和 E 的源代码,但我不太确定它们是如何工作的。 下面是 V 的代码:

> V
function (graph)
{
    if (!is.igraph(graph)) {
        stop("Not a graph object")
    }
    vc <- vcount(graph)
    if (vc == 0) {
        res <- numeric()
    }
    else {
        res <- 0:(vc - 1)
    }
    class(res) <- "igraph.vs"
    ne <- new.env()
    assign("graph", graph, envir = ne)
    attr(res, "env") <- ne
    res
}

我不太确定调用 allocate 和 attr 的目的是什么。 分配图形是否会创建图形的新副本?这有多高效/低效?也就是说,这会生成多少个图表副本,代码如下:

V(g)$someattr <- somevector

感谢您的帮助。

I've looked through the source for V and E and I'm not really sure how they work.
Here's the code for V:

> V
function (graph)
{
    if (!is.igraph(graph)) {
        stop("Not a graph object")
    }
    vc <- vcount(graph)
    if (vc == 0) {
        res <- numeric()
    }
    else {
        res <- 0:(vc - 1)
    }
    class(res) <- "igraph.vs"
    ne <- new.env()
    assign("graph", graph, envir = ne)
    attr(res, "env") <- ne
    res
}

I'm not really sure what purpose the calls to assign and attr serve here.
Does assigning graph create a new copy of graph? How efficient/inefficient is this? That is, how many copies of graph does this generate say in code like:

V(g)$someattr <- somevector

Thanks for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

垂暮老矣 2024-12-08 14:37:20

使用 V 生成顶点序列时,对 assignattr 的调用会存储用于创建序列的图的副本以及顶点序列对象本身。这样,当您执行诸如 V(g)$color = 'blue' 之类的操作时,可以在 g 的此副本的上下文中方便地计算顶点序列。如果您检查 igraph.vs 类可用的方法之一,这一点就会很清楚。

> methods(class='igraph.vs')
[1] [.igraph.vs     [<-.igraph.vs   $.igraph.vs     
lt;-.igraph.vs   print.igraph.vs

> `$.igraph.vs`
function (x, name) 
{
    get.vertex.attribute(get("graph", attr(x, "env")), name, 
        x)
}
<environment: namespace:igraph>

很明显,$ 索引操作将在用于创建顶点序列的图形环境的上下文中进行评估。

您提出了一个很好的观点,尽管这确实创建了图表的多个副本(可能会被垃圾收集,但了解这一点仍然很好)。如果您在创建顶点序列 vs = V(g) 后修改图 g 的属性,则可以轻松演示这一点。该属性在 g 中更新,但不在存储在附加到 vs 的环境中的 g 副本中更新。

> g = graph(c(0:1), directed=F)
> g = set.vertex.attribute(g, 'color', value='blue')
> vs = V(g)
> vs$color
[1] "blue" "blue"
> g = set.vertex.attribute(g, 'color', value='red')
> V(g)$color
[1] "red" "red"
> vs$color
[1] "blue" "blue"

When generating a vertex sequence with V, the calls to assign and attr store a copy of the graph that was used to create the sequence along with the vertex sequence object, itself. This way when you do something like V(g)$color = 'blue', the vertex sequence can be conveniently evaluated in the context of this copy of g. This is clear if you inspect one of the methods available for the igraph.vs class.

> methods(class='igraph.vs')
[1] [.igraph.vs     [<-.igraph.vs   $.igraph.vs     
lt;-.igraph.vs   print.igraph.vs

> `$.igraph.vs`
function (x, name) 
{
    get.vertex.attribute(get("graph", attr(x, "env")), name, 
        x)
}
<environment: namespace:igraph>

Here it is clear that the $ indexing operation will get evaluated in the context of the graph environment that was used to create the vertex sequence.

You bring up a good point though that this does create multiple copies of the graph (which presumably get garbage collected, but it's still good to be aware of). This is easily demonstrated if you modify attributes of a graph g, after you have already created a vertex sequence vs = V(g). The attribute is updated in g, but not in the copy of g that is stored in the environment attached to vs.

> g = graph(c(0:1), directed=F)
> g = set.vertex.attribute(g, 'color', value='blue')
> vs = V(g)
> vs$color
[1] "blue" "blue"
> g = set.vertex.attribute(g, 'color', value='red')
> V(g)$color
[1] "red" "red"
> vs$color
[1] "blue" "blue"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文