将字符串作为文本字面量传递以创建图形对象。

8

我们可以传递字面值来创建以下图形:

# 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。例如,将其拆分为2列对于简单输入"A-B-C"不起作用。

编辑2: 动机来自另一个问题,我认为可以使用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问题475来解决这个功能。


请问您能否解释一下为什么要将此请求作为字符串而不是表达式,并给出动机?graph_from_literal的目的是为了能够快速创建用于实验的图形。期望的是您手动输入表达式。然后,据我所见,无论您是否使用引号键输入,都没有关系。 - Szabolcs
@Szabolcs 请查看“编辑2”。 - zx8754
1
感谢您的解释。有关在R/igraph中添加字符串支持的讨论在此处。欢迎发表评论。就个人而言,我认为所提出的应用程序是一种hack(非常方便的hack,但仍然是一种hack,因为它与graph_from_literal的预期使用不一致)。 - Szabolcs
@Szabolcs 很好,我也在考虑在GitHub上发布它。现在通过这次编辑,并将活动问题链接到此贴文,希望“动机”更加明确。 - zx8754
3个回答

5

将输入通过逗号分隔,解析为表达式并调用内部的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

1
一行代码略微简单,如下所示:do.call(graph_from_literal, as.list(parse(text = "A-B"))) - Roland
"graph_from_literal_i" 不错,谢谢。我想知道为什么还没有 "graph_from_string"。 - zx8754

1
也许我们可以做类似这样的事情。
> 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

0

你可以每行一个边来创建数据帧:

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包(v2.0.1)于2021-09-20创建


我知道graph_as_xxx函数,希望避免数据操作。如果输入是“A-B-C”,这种方法将无法工作。 - zx8754
好的。请在您的问题中明确要求超图。 - danlooo
好的,我会编辑帖子,假设“一个长而复杂的字符串”已经足够清楚了。 - zx8754
"A-B-C" 不表示超图,它是 "A-B, B-C" 的缩写。 - Szabolcs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接