【问题标题】:Pass a string as literal to create a graph object将字符串作为文字传递以创建图形对象
【发布时间】:2021-09-20 09:44:29
【问题描述】:

我们可以传递文字来制作如下图:

# R version 4.0.2 (2020-06-22)
library(igraph) # igraph_1.2.6

graph_from_literal(A-B)
# IGRAPH 7e5604a UN-- 2 1 -- 
# + attr: name (v/c)
# + edge from 7e5604a (vertex names):
#   [1] A--B

认为传递字符串会起作用,但事实并非如此。 (这是一个小例子"A-B",想象一个很长的复杂字符串):

graph_from_literal("A-B")
# IGRAPH 8b32703 UN-- 1 0 -- 
# + attr: name (v/c)
# + edges from 8b32703 (vertex names):

# objects are not the same
identical_graphs(graph_from_literal(A-B),
                 graph_from_literal("A-B"))
# [1] FALSE

要么我使用了错误的函数,要么我需要另一个函数来删除引号。 catnoquote 不起作用。想法?


编辑 1: 我想避免字符串操作:将“A-B”拆分为“from”和“to”,然后使用 graph_from_dataframe。例如,对于 "A-B-C" 的简单输入,拆分为 2 列不起作用。

编辑 2: 动机来自 another question,我认为我可以使用 igraph 包作为解决方案。我用破折号替换了点,想将该字符串转换为图形对象,但意识到 literal 不喜欢字符串输入。

那么更长的问题:我如何将下面的转换为图形对象?

# input
c('0.1', '0.1.1', '0.1.2', '0.11', '0.12', '0.11.1', '0.12.1', '0.12.2')

# expected output:
graph_from_literal(0-1, 0-1-1, 0-1-2, 0-11, 0-12, 0-11-1, 0-12-1, 0-12-2)
# IGRAPH 0792a00 UN-- 5 7 -- 
# + attr: name (v/c)
# + edges from 0792a00 (vertex names):
#   [1] 0--1  0--11 0--12 1--2  1--11 1--12 2--12

编辑 3:现在有一个相关的开放GitHub issue 475 来解决此功能。

【问题讨论】:

  • 你能否激发这个请求并解释为什么你想把它写成一个字符串而不是一个表达式? graph_from_literal 的目的是能够快速创建图表以进行实验。期望您手动输入表达式。然后,据我所知,您输入的内容是否带引号都没有关系。
  • @Szabolcs 请参阅“编辑 2”。
  • 感谢您的解释。关于向 R/igraph 添加字符串支持的讨论是here。随意发表评论。就个人而言,我认为提议的应用程序是一个 hack(一个非常方便的 hack,但仍然是一个 hack,因为它与 graph_from_literal 的预期用途不一致)。
  • @Szabolcs 太好了,我也想在 GitHub 上发布它。现在有了编辑,并且有这个帖子的活跃问题链接,希望“动机”很清楚。

标签: r igraph


【解决方案1】:

用逗号分割输入,解析成表达式并调用内部graph_from_literal_i。没有使用除 igraph 以外的任何包。

graph_from_string <- function(x) {
  e <- str2expression(strsplit(x, ",")[[1]])
  do.call(igraph:::graph_from_literal_i, list(e))
}

# test 1
graph_from_string("A-B")
## IGRAPH 063d605 UN-- 2 1 -- 
## + attr: name (v/c)
## + edge from 063d605 (vertex names):
## [1] A--B

# test 2 - a more complex example
graph_from_string("A-B-C, D-E")
## IGRAPH b155b39 UN-- 5 3 -- 
## + attr: name (v/c)
## + edges from b155b39 (vertex names):
## [1] A--B B--C D--E

如果输入中没有逗号,那么这个单行也可以:

do.call("graph_from_literal", list(parse(text = "A-B")[[1]]))
## IGRAPH dad0219 UN-- 2 1 -- 
## + attr: name (v/c)
## + edge from dad0219 (vertex names):
## [1] A--B

【讨论】:

  • 单行略简单如do.call(graph_from_literal, as.list(parse(text = "A-B")))
  • "graph_from_literal_i" 不错,谢谢。我想知道为什么“graph_from_string”不存在。
【解决方案2】:

也许我们可以这样做

> x <- "A-B-C, D-E"

> eval(str2lang(sprintf("graph_from_literal(%s)", x)))
IGRAPH ab43602 UN-- 5 3 -- 
+ attr: name (v/c)
+ edges from ab43602 (vertex names):
[1] A--B B--C D--E

【讨论】:

    【解决方案3】:

    您可以改为制作每行一条边的数据框:

    library(tidyverse)
    library(igraph)
    #> 
    #> Attaching package: 'igraph'
    #> The following objects are masked from 'package:dplyr':
    #> 
    #>     as_data_frame, groups, union
    #> The following objects are masked from 'package:purrr':
    #> 
    #>     compose, simplify
    #> The following object is masked from 'package:tidyr':
    #> 
    #>     crossing
    #> The following object is masked from 'package:tibble':
    #> 
    #>     as_data_frame
    #> The following objects are masked from 'package:stats':
    #> 
    #>     decompose, spectrum
    #> The following object is masked from 'package:base':
    #> 
    #>     union
    
    list("A-B", "A-C") %>%
      tibble(edge = .) %>%
      unnest(edge) %>%
      separate(edge, into = c("from", "to"), sep = "-") %>%
      graph_from_data_frame(directed = FALSE)
    #> IGRAPH 011a563 UN-- 3 2 -- 
    #> + attr: name (v/c)
    #> + edges from 011a563 (vertex names):
    #> [1] A--B A--C
    

    reprex package (v2.0.1) 于 2021-09-20 创建

    【讨论】:

    • 我知道graph_as_xxx 函数,希望避免数据操作。如果输入是“A-B-C”,这将不起作用。
    • 好的。请在您的问题中明确要求超图。
    • 好的,将编辑帖子,假设“a long complex string”已经足够清楚了。
    • A-B-C 不表示超图。它是A-B, B-C 的缩写。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多