A. Stam
A. Stam

Reputation: 2222

Alter X and Y coordinates of graph vertices in iGraph

I'm using the igraph package to plot a graph that I've created in yEd. This is a graph that should be overlaid on a geographical map, so one of the first things I want to do is alter the vertex coordinates so that they match up to the longitude/latitude they represent. (simple linear transformation)

I tried to use the GraphML format, but iGraph cannot read GraphML files that were created by yEd, so instead, I've saved the graph as a GML file. The structure of the vertex information looks like this:

node [
    id  0
    label   ""
    graphics [
        x   2181.0043222386603
        y   1463.6747524664843
        w   5.2609883750396875
        h   5.1510372122625085
        type    "ellipse"
        raisedBorder    0
        fill    "#FFCC00"
        outline "#000000"
    ]
]

As you can see, the coordinates are saved within the graphics attribute. This is valid GML syntax (at least AFAIK). However, this attribute is not processed correctly by load_graph and iGraph doesn't save the coordinates. When I try to extract the vertex attributes, I get this:

> vertex_attr(g) %>% glimpse()
# List of 3
#  $ id      : num [1:73] 0 1 2 3 4 5 6 7 8 9 ...
#  $ label   : chr [1:73] "" "" "" "" ...
#  $ graphics: chr [1:73] "qÑÜ\020#8" "qÑÜ\020#8" "qÑÜ\020#8" "qÑÜ\020#8" ...

How do I load the graph correctly, including x and y coordinates?

Upvotes: 0

Views: 1108

Answers (1)

Esther
Esther

Reputation: 1115

From the igraph documentation, it says that one of the limitations of its ability to read GML is

Only node and edge attributes are used, and only if they have a simple type: integer, real or string. So if an attribute is an array or a record, then it is ignored. This is also true if only some values of the attribute are complex.

Which is probably why it's having trouble with the graphics attribute. igraph should be able to read graphml format as well, but likely encounters the same hurdle.

Luckily, if you need a workaround, GML is a human-readable format that is relatively easy to parse out. If you just need the x and y coordinates of the nodes for example, you can do something like this:

library(igraph)

g <- read_graph("graph.gml", format="gml") #create graph object

z <- readLines("graph.gml") #create character vector from which to grep out attributes

id <- trimws(gsub("\t\tid\t", " ", z[grep("\t\tid\t", z)])) #retrive node ids 
totid <- length(id) #retrieve number of nodes

#grep for and extract x and y attributes
xcor <- as.numeric(trimws(gsub("\t\t\tx\t", " ", z[grep("\t\t\tx\t", z)])))[1:totid]    
ycor <- as.numeric(trimws(gsub("\t\t\ty\t", " ", z[grep("\t\t\ty\t", z)])))[1:totid]

#edges will also have x and y coordinates, so we need to index by the number of nodes

#add attributes back into graph object
g <- set.vertex.attribute(g, "x", value=xcor) 
g <- set.vertex.attribute(g, "y", value=ycor)

Upvotes: 1

Related Questions