Search code examples
rigraph

Pass a string as literal to create a graph object


We can pass literals to make a graph as below:

# 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

Thought passing a string would work, but it doesn't. (This is a small example "A-B", imagine a long complex string):

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

Either I am using a wrong function or I need another function to drop the quotes. cat, noquote didn't work. Ideas?


Edit 1: I would want to avoid string manipulation: split "A-B" into "from" and "to", then using graph_from_dataframe. For example, splitting into 2 columns would not work for a simple input of "A-B-C".

Edit 2: Motivation came from another question where I thought I could use igraph package as a solution. I substituted dots with dashes, wanted to convert that string into a graph object, but realised literal doesn't like string input.

So the longer question: How would I convert below into a graph object?

# 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

Edit 3: There is now a related open GitHub issue 475 to address this functionality.


Solution

  • Split the input by comma, parse into an expression and call the internal graph_from_literal_i. No packages other than igraph are used.

    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
    

    If there are no commas in the input then this one-liner would also work:

    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