0

I have edge information organised in a way that shows the edge's location within a regular-type Graph; where a regular graph is defined as one that looks like a "checker-board". Here is an example of how the data is organised:

(7, 3) (6, 3) 1.0
(7, 3) (8, 3) 1.0
(7, 3) (8, 2) 1.41421356237
(7, 3) (6, 4) 1.41421356237
(7, 3) (7, 4) 1.0
(7, 3) (6, 2) 1.41421356237
(7, 3) (7, 2) 1.0
(7, 3) (8, 4) 1.41421356237

Here, column 1 represents the first point's location (e.g. 7 columns over and 3 rows down for the very first point), column 2 represents the adjacent point, and column 3 represents edge weight value between the two points. The provided example shows all possible adjacent paths (including diagonals) for the point at location (7,3).

My code to create a graph with these edges looks as such:

import networkx as nx
edgelist = r'C:\filepath'
edges = nx.read_weighted_edgelist(edgelist, create_using= nx.Graph(), nodetype= int)
nx.draw_networkx(edges)

I am not getting an error but I am only receiving an empty output. Any thoughts on how to correct this? I am using Python 27. Thanks!

Zach
  • 35
  • 6
  • Your nodes are 2-d coordinates e.g., `(7, 3)` and `(6,3)`, but you've told it to expect nodes of type `int`. This will cause trouble. I suspect you may have to write a custom function to read in lines from this file and produce the network. – Joel Oct 16 '18 at 00:36
  • @Joel thanks for the idea. Do you have a suggestion for going about this? What, for instance, would be the proper form to have the nodes in? Without providing coordinates I am unsure of how to make the graph a regular-type graph. I apologise I am relatively new to Python and NetworkX. – Zach Oct 16 '18 at 03:38

1 Answers1

0

The node identity is, in principle, independent of its position. You could simplify the problem by creating a dummy identity for each node, and keep the node position stored in a different data structure that you then use when drawing the graph. For example, you could do the following:

import numpy as np
import matplotlib.pyplot as plt
import re
import networkx as nx

def load(fpath):
    # adapated from: https://stackoverflow.com/a/48097465/2912349
    data = []
    pattern='\((\d+, \d+)\)'
    with open(fpath, 'r') as f:
        for line in f:
            matches = re.findall(pattern, line)
            source, target = [tuple(map(lambda x:int(x),item.split(','))) for item in matches]
            weight = float(line.split(' ')[-1])
            data.append((source, target, weight))
    return data

data = load('test_grid.txt')
# print data

# determine unique nodes
sources = [source for source, _, _ in data]
targets = [target for _, target, _ in data]
coordinates = set(sources + targets)

# create mappings from node -> coordinate and vice versa
pos     = {ii : xy for ii, xy in enumerate(coordinates)}
inverse = {xy : ii for ii, xy in enumerate(coordinates)}

# create a more conventional edge list
edges = []
for (source_coord, target_coord, weight) in data:
    edge = (inverse[source_coord], inverse[target_coord], weight)
    edges.append(edge)

# create graph and plot
g = nx.Graph()
g.add_weighted_edges_from(edges)
nx.draw(g, pos)

enter image description here

This script assumes that your graph is stored in a text file at test_grid.txt. Change the path as necessary.

Paul Brodersen
  • 11,221
  • 21
  • 38
  • This is terrific, thanks a ton for commenting. I have one question for you: when calling the user-defined module portion: "data = load(fpath)" I am getting an error: "File "", line 2, in *next line* File "", line 13, in load *next line* ValueError: too many values to unpack." I believe the error might be associated with how the pattern is described? Though it looks correct to me, though. Any thoughts? – Zach Oct 17 '18 at 23:07
  • Or perhaps this is the source of the issue? https://stackoverflow.com/questions/1479776/too-many-values-to-unpack-exception – Zach Oct 17 '18 at 23:09
  • Okay found the issue here: if the input txt file has double digit values referencing coordinates, the pattern must look as such: "pattern='\((\d+, \d+)\)'". The code works perfectly with this included. Thank you! – Zach Oct 18 '18 at 00:42
  • Yeah, your example did not have any double digits, so I didn't match any. ;-P Glad you solved the issue yourself. If this works for you, don't forget to accept the answer. – Paul Brodersen Oct 18 '18 at 08:13