-
-
Save bbengfort/a430d460966d64edc6cad71c502d7005 to your computer and use it in GitHub Desktop.
import networkx as nx | |
import graph_tool as gt | |
def get_prop_type(value, key=None): | |
""" | |
Performs typing and value conversion for the graph_tool PropertyMap class. | |
If a key is provided, it also ensures the key is in a format that can be | |
used with the PropertyMap. Returns a tuple, (type name, value, key) | |
""" | |
if isinstance(key, unicode): | |
# Encode the key as ASCII | |
key = key.encode('ascii', errors='replace') | |
# Deal with the value | |
if isinstance(value, bool): | |
tname = 'bool' | |
elif isinstance(value, int): | |
tname = 'float' | |
value = float(value) | |
elif isinstance(value, float): | |
tname = 'float' | |
elif isinstance(value, unicode): | |
tname = 'string' | |
value = value.encode('ascii', errors='replace') | |
elif isinstance(value, dict): | |
tname = 'object' | |
else: | |
tname = 'string' | |
value = str(value) | |
return tname, value, key | |
def nx2gt(nxG): | |
""" | |
Converts a networkx graph to a graph-tool graph. | |
""" | |
# Phase 0: Create a directed or undirected graph-tool Graph | |
gtG = gt.Graph(directed=nxG.is_directed()) | |
# Add the Graph properties as "internal properties" | |
for key, value in nxG.graph.items(): | |
# Convert the value and key into a type for graph-tool | |
tname, value, key = get_prop_type(value, key) | |
prop = gtG.new_graph_property(tname) # Create the PropertyMap | |
gtG.graph_properties[key] = prop # Set the PropertyMap | |
gtG.graph_properties[key] = value # Set the actual value | |
# Phase 1: Add the vertex and edge property maps | |
# Go through all nodes and edges and add seen properties | |
# Add the node properties first | |
nprops = set() # cache keys to only add properties once | |
for node, data in nxG.nodes_iter(data=True): | |
# Go through all the properties if not seen and add them. | |
for key, val in data.items(): | |
if key in nprops: continue # Skip properties already added | |
# Convert the value and key into a type for graph-tool | |
tname, _, key = get_prop_type(val, key) | |
prop = gtG.new_vertex_property(tname) # Create the PropertyMap | |
gtG.vertex_properties[key] = prop # Set the PropertyMap | |
# Add the key to the already seen properties | |
nprops.add(key) | |
# Also add the node id: in NetworkX a node can be any hashable type, but | |
# in graph-tool node are defined as indices. So we capture any strings | |
# in a special PropertyMap called 'id' -- modify as needed! | |
gtG.vertex_properties['id'] = gtG.new_vertex_property('string') | |
# Add the edge properties second | |
eprops = set() # cache keys to only add properties once | |
for src, dst, data in nxG.edges_iter(data=True): | |
# Go through all the edge properties if not seen and add them. | |
for key, val in data.items(): | |
if key in eprops: continue # Skip properties already added | |
# Convert the value and key into a type for graph-tool | |
tname, _, key = get_prop_type(val, key) | |
prop = gtG.new_edge_property(tname) # Create the PropertyMap | |
gtG.edge_properties[key] = prop # Set the PropertyMap | |
# Add the key to the already seen properties | |
eprops.add(key) | |
# Phase 2: Actually add all the nodes and vertices with their properties | |
# Add the nodes | |
vertices = {} # vertex mapping for tracking edges later | |
for node, data in nxG.nodes_iter(data=True): | |
# Create the vertex and annotate for our edges later | |
v = gtG.add_vertex() | |
vertices[node] = v | |
# Set the vertex properties, not forgetting the id property | |
data['id'] = str(node) | |
for key, value in data.items(): | |
gtG.vp[key][v] = value # vp is short for vertex_properties | |
# Add the edges | |
for src, dst, data in nxG.edges_iter(data=True): | |
# Look up the vertex structs from our vertices mapping and add edge. | |
e = gtG.add_edge(vertices[src], vertices[dst]) | |
# Add the edge properties | |
for key, value in data.items(): | |
gtG.ep[key][e] = value # ep is short for edge_properties | |
# Done, finally! | |
return gtG | |
if __name__ == '__main__': | |
# Create the networkx graph | |
nxG = nx.Graph(name="Undirected Graph") | |
nxG.add_node("v1", name="alpha", color="red") | |
nxG.add_node("v2", name="bravo", color="blue") | |
nxG.add_node("v3", name="charlie", color="blue") | |
nxG.add_node("v4", name="hub", color="purple") | |
nxG.add_node("v5", name="delta", color="red") | |
nxG.add_node("v6", name="echo", color="red") | |
nxG.add_edge("v1", "v2", weight=0.5, label="follows") | |
nxG.add_edge("v1", "v3", weight=0.25, label="follows") | |
nxG.add_edge("v2", "v4", weight=0.05, label="follows") | |
nxG.add_edge("v3", "v4", weight=0.35, label="follows") | |
nxG.add_edge("v5", "v4", weight=0.65, label="follows") | |
nxG.add_edge("v6", "v4", weight=0.53, label="follows") | |
nxG.add_edge("v5", "v6", weight=0.21, label="follows") | |
for item in nxG.edges_iter(data=True): | |
print item | |
# Convert to graph-tool graph | |
gtG = nx2gt(nxG) | |
gtG.list_properties() |
This TypeError is caused by converting the key and value to ascii. Simply remove the lines 13-15 and 30.
def get_prop_type(value, key=None):
"""
Performs typing and value conversion for the graph_tool PropertyMap class.
If a key is provided, it also ensures the key is in a format that can be
used with the PropertyMap. Returns a tuple, (type name, value, key)
"""
# Deal with the value
if isinstance(value, bool):
tname = 'bool'
elif isinstance(value, int):
tname = 'float'
value = float(value)
elif isinstance(value, float):
tname = 'float'
elif isinstance(value, unicode):
tname = 'string'
elif isinstance(value, dict):
tname = 'object'
else:
tname = 'string'
value = str(value)
return tname, value, key
Anybody knows how to convert from graph-tool to networkx?
I am currently working on it to get to know all the libraries. You could try this one: https://github.com/luerhard/pyintergraph/blob/master/convert/gt2nx.py
The previous comment's link seems to be dead, so this is a quick note to any who follow that I made a few tweaks to make this work with a 2.0+ version of NetworkX, Python3, and for my own purposes I converted to utf-8 instead of ascii for international usages. Code at https://gist.github.com/tomshaffner/7a2df7f9ec6b1be33dd0413897125683 if anyone wishes to start there and save some time. Thanks to the original author for a great start! If you see this maybe you'd care to update the original code?
Great contribution! But I'm facing the same problem here. =/