I recently installed python-igraph (version=0.7.1.post6 on windows 10) and I would like to generate networks with communities using LFR benchmark, but I didn't find the specific function to do that.
Is there a function (in igraph) that create LFR benchmark? If not, are there any other recommended modules that enables generating such graphs (and contain SOTA community detection algorithms as in igraph)?
Thanks,
Gal
from networkx.algorithms.community import LFR_benchmark_graph
As pointed out, it is defined inside the networkx package and this means that you can import it to igraph. A minimum working example would go like this.
import igraph as ig
from networkx.algorithms import community
def import_nx_network(net):
graph = ig.Graph(n=net.number_of_nodes(), directed=False)
graph.add_edges(net.edges())
return graph
def LFR_graph(N, τ1, τ2, μ, **kwargs):
net = community.LFR_benchmark_graph(N, τ1, τ2, μ, **kwargs)
graph = import_nx_network(net)
return graph
Related
I am trying to create and process graphs, for example, checking if a graph contains a cycle and I'm doing this in python.
Is there an API or Library that has implemented these basic capabilities?
So, I know about NetworkX library.
import networkx as nx
G1 = nx.Graph()
G1.add_edges_from([(0, 1),(0, 2),(0, 3),(8, 9)])
l = list(nx.strongly_connected_components(G1))
# Gives a list of all strong connected components
# You can also try
# l = list(nx.weakly_connected_components(G1))
# To check if the we can reach from one node to other in undirected graph
for graph in l:
nx.draw_networkx(graph)
It is has been quite easy to use with pandas and numpy in various projects.
Thanks at first for actually taking the time to help me :-)
I want to create a undirected graph from waterways for example from the canals of Venice or Amsterdam.
OpenStreetMaps has such a graph of a waterway network of these cities, but the OSMnx package does not have such a filter to filter the waterways (or maybe I don't know it yet ;-) ).
import osmnx as ox
G = ox.graph_from_bbox(52.36309012572587,4.890326718121118,52.36590601699889,4.898316757037793, network_type='all')
G_projected = ox.project_graph(G)
ox.plot_graph(G_projected)
I thought I was possible to just download the whole map, and then filter on just the waterway network. But I don't know how to go further about this. OSMnx would be the best as I then immediately have a graph which I can use for functions of networksx such as Dijkstra's shortest path.
Another way I was thinking of was overpass package:
import overpass
import networkx as nx
import matplotlib.pyplot as plt
api= overpass.API()
data = api.get('way(52.36309012572587,4.890326718121118,52.36590601699889,4.898316757037793);(._;>;)', verbosity='geom')
[f for f in data.features if f.geometry['type'] == "LineString"]
But this still doesn't work, because I haven't figured out how to filter the data and transform it to a graph for so that networkx can use it.
Hope you guys (and girls :-) ) can help me, because I have no clue how to go further.
Kind regards,
Jeroen
You can use OSMnx to get other types of infrastructure such as canals, railways, powerlines, etc, as described in this example, using the custom_filter parameter:
import osmnx as ox
ox.config(use_cache=True, log_console=True)
G = ox.graph_from_place('Amsterdam', retain_all=False, truncate_by_edge=False,
simplify=True, custom_filter='["waterway"~"canal"]')
fig, ax = ox.plot_graph(G)
I'm just picking up NetworkX and trying to learn how to use it with Shapefiles.
Right now I have a .shp with a road network that I want to represent in a Graph with NetworkX, so that I can find the shortest path between 2 GPS points. I tried using this, but the problem is that when I run the write_shp() function I lose edges because DiGraph does not allow more than one edge between the same two nodes. The arrow in the figure below shows an example of an edge I lose by using a DiGraph.
So I was wondering if there's any way to create a MultiDiGraph so I don't lose any edges, or if there's any way around it that I could use. I was thinking maybe I could write some code to extract the attributes from the Shapefile and create the MultiDiGraph without using NetworkX's read_shp(), but I don't have any experience at all working with graphs, so I'm not exactly sure if it'd be possible.
I'd really appreciate any help or guidance you could give me, or if I've missed any documentation please let me know. Thanks in advance.
As best I can follow from your question, the following will do it, basically copied from the original read_shp command.
def read_multi_shp(path):
"""
copied from read_shp, but allowing MultiDiGraph instead.
"""
try:
from osgeo import ogr
except ImportError:
raise ImportError("read_shp requires OGR: http://www.gdal.org/")
net = nx.MultiDiGraph() # <--- here is the main change I made
def getfieldinfo(lyr, feature, flds):
f = feature
return [f.GetField(f.GetFieldIndex(x)) for x in flds]
def addlyr(lyr, fields):
for findex in xrange(lyr.GetFeatureCount()):
f = lyr.GetFeature(findex)
flddata = getfieldinfo(lyr, f, fields)
g = f.geometry()
attributes = dict(zip(fields, flddata))
attributes["ShpName"] = lyr.GetName()
if g.GetGeometryType() == 1: # point
net.add_node((g.GetPoint_2D(0)), attributes)
if g.GetGeometryType() == 2: # linestring
attributes["Wkb"] = g.ExportToWkb()
attributes["Wkt"] = g.ExportToWkt()
attributes["Json"] = g.ExportToJson()
last = g.GetPointCount() - 1
net.add_edge(g.GetPoint_2D(0), g.GetPoint_2D(last), attr_dict=attributes) #<--- also changed this line
if isinstance(path, str):
shp = ogr.Open(path)
lyrcount = shp.GetLayerCount() # multiple layers indicate a directory
for lyrindex in xrange(lyrcount):
lyr = shp.GetLayerByIndex(lyrindex)
flds = [x.GetName() for x in lyr.schema]
addlyr(lyr, flds)
return net
I changed the returned graph from a DiGraph to a MultiDigraph and I had to change the add_edge command since the MultiDiGraph version has different syntax from DiGraph
If the multi-lines are disconnected at the joint, I think this library python-s2g(https://github.com/caesar0301/python-s2g) could help you. Even networkx's Graph object is used under the hood, those multi-paths are actually recorded by the graph data.
I have implemented a solution here: https://gitlab.com/njacadieux/upstream_downstream_shortests_path_dijkstra
I read the shapefile using GeoPandas and not the networkx.readwrite.nx_shp.read_shp. When I build the graph, I check for parallel edges. If found, rather than skipping them, as does the networkx.readwrite.nx_shp.read_shp function, I split the parallel edges in two edges of equal length and then divide the user length by 2. The user length variable field name must be given.
I am starting to use this interface now, I have some experience with Python but nothing extensive. I am calculating the transitivity and community structure of a small graph:
import networkx as nx
G = nx.read_edgelist(data, delimiter='-', nodetype=str)
nx.transitivity(G)
#find modularity
part = best_partition(G)
modularity(part, G)
I get the transitivity just fine, however - there is the following error with calculating modularity.
NameError: name 'best_partition' is not defined
I just followed the documentation provided by the networkx site, is there something I am doing wrong?
As far as I can tell best_partition isn't part of networkx. It looks like you want to use https://sites.google.com/site/findcommunities/ which you can install from https://bitbucket.org/taynaud/python-louvain/src
Once you've installed community try this code:
import networkx as nx
import community
import matplotlib.pyplot as plt
G = nx.random_graphs.powerlaw_cluster_graph(300, 1, .4)
nx.transitivity(G)
#find modularity
part = community.best_partition(G)
mod = community.modularity(part,G)
#plot, color nodes using community structure
values = [part.get(node) for node in G.nodes()]
nx.draw_spring(G, cmap = plt.get_cmap('jet'), node_color = values, node_size=30, with_labels=False)
plt.show()
edit: How I installed the community detection library
ryan#palms ~/D/taynaud-python-louvain-147f09737714> pwd
/home/ryan/Downloads/taynaud-python-louvain-147f09737714
ryan#palms ~/D/taynaud-python-louvain-147f09737714> sudo python3 setup.py install
I just met the same error NameError: name 'best_partition' is not defined when using this example code.
This error occurs because I named my python file as networkx.py, then when we execute this program
import networkx as nx
This program may import the networkx we defined instead of the library. In the program, best_partition is not defined. So this error occur.
Having same name with library is not appropriate. Maybe you should check this!
I am a very, very mediocre programmer, but I still aim to use the igraph python library to determine the effect of a user's centrality in a given forum to predict his later contributions to that forum.
I got in touch with someone else who used the NetworkX library to do something similar, but given the current size of the forum, calculating exact centrality indices is virtually impossible--it just takes too much time.
This was his code though:
import networkx as netx
import sys, csv
if len(sys.argv) is not 2:
print 'Please specify an input graph.'
sys.exit(1)
ingraph = sys.argv[1]
graph = netx.readwrite.gpickle.read_gpickle(ingraph)
num_nodes = len(graph.nodes())
print '%s nodes found in input graph.' % num_nodes
print 'Recording data in centrality.csv'
# Calculate all of the betweenness measures
betweenness = netx.algorithms.centrality.betweenness_centrality(graph)
print 'Betweenness computations complete.'
closeness = netx.algorithms.centrality.closeness_centrality(graph)
print 'Closeness computations complete.'
outcsv = csv.writer(open('centrality.csv', 'wb'))
for node in graph.nodes():
outcsv.writerow([node, betweenness[node], closeness[node]])
print 'Complete!'
I tried to write something similar with the igraph library (which allows to make quick estimates rather than exact calculations), but I cannot seem to write data to a CSV file.
My code:
import igraph
import sys, csv
from igraph import *
graph = Graph.Read_Pajek("C:\karate.net")
print igraph.summary(graph)
estimate = graph.betweenness(vertices=None, directed=True, cutoff=2)
print 'Betweenness computation complete.'
outcsv = csv.writer(open('estimate.csv', 'wb'))
for v in graph.vs():
outcsv.writerow([v, estimate[vs]])
print 'Complete!'
I can't find how to call individual vertices (or nodes, in NetworkX jargon) in the igraph documentation, so that's where I am getting error messages). Perhaps I am forgetting something else as well; I am probably too bad a programmer to notice :P
What am I doing wrong?
So, for the sake of clarity, the following eventually proved to do the trick:
import igraph
import sys, csv
from igraph import *
from itertools import izip
graph = Graph.Read_GML("C:\stack.gml")
print igraph.summary(graph)
my_id_to_igraph_id = dict((v, k) for k, v in enumerate(graph.vs["id"]))
estimate = graph.betweenness(directed=True, cutoff=16)
print 'Betweenness computation complete.'
print graph.vertex_attributes()
outcsv = csv.writer(open('estimate17.csv', 'wb'))
outcsv.writerows(izip(graph.vs["id"], estimate))
print 'Complete!'
As you already noticed, individual vertices in igraph are accessed using the vs attribute of your graph object. vs behaves like a list, so iterating over it will yield the vertices of the graph. Each vertex is represented by an instance of the Vertex class, and the index of the vertex is given by its index attribute. (Note that igraph uses continuous numeric indices for both the vertices and the edges, so that's why you need the index attribute and cannot use your original vertex names directly).
I presume that what you need is the name of the vertex that was stored originally in your input file. Names are stored in the name or id vertex attribute (depending on your input format), so what you need is probably this:
for v in graph.vs:
outcsv.writerow([v["name"], estimate[v.index]])
Note that vertex attributes are accessed by indexing the vertex object as if it was a dictionary. An alternative is to use the vs object directly as a dictionary; this will give you a list containing the values of the given vertex attribute for all vertices. E.g.:
from itertools import izip
for name, est in izip(graph.vs["name"], estimate):
outcsv.writerow([name, est])
An even faster version using generator expressions:
outcsv.writerows(izip(graph.vs["name"], estimate))