In networkx, I found drawing labels of edges is very easy but I how can I draw length or relative distance of edges?
Here is my test code
G = nx.Graph()
G.add_edge(0, 1, length=1)
G.add_edge(0, 2, length=5)
pos = nx.spring_layout(G)
length = nx.get_node_attributes(G, 'length')
What I mean is the plot should show length between nodes since edge has its corresponding length. Here is example
the distance between 0 and 2 looks larger than that between 0 and 1.
Your example shows the length of each edge as a text label. That is, the text gives the length of the edge. But since most networks are not embedded in 2D, they cannot be positioned in a 2D picture that gives the right perspective for lengths as assigned to the graphs.
For example, a triangle graph can have lengths 3, 4 and 12. These cannot be realized in a length-scaled version even though it is a valid graph with valid edge lengths.
If you have an embedding of the nodes into the 2D plane (dict of nodes to 2-tuple position pairs) you can use that to draw the network as you like. But NetworkX does not provide a way to find this embedding. There is a recent Pull Request for planarity testing using NetworkX (#3040).
Aric Hagberg has some code that works with planar graphs. Take a look at this thread:
https://groups.google.com/forum/#!topic/networkx-discuss/FdhFedwvtrc
Related
I am working with networks undergoing a number of disrupting events. So, a number of nodes fail because of a given event. Therefore there is a transition between the image to the left to that to the right:
My question: how can I find the disconnected subgraphs, even if they contain only 1 node? My purpose is to count them and render as failed, as in my study this is what applies to them. By semi-isolated nodes, I mean groups of isolated nodes, but connected to each other.
I know I can find isolated nodes like this:
def find_isolated_nodes(graph):
""" returns a list of isolated nodes. """
isolated = []
for node in graph:
if not graph[node]:
isolated += node
return isolated
but how would you amend these lines to make them find groups of isolated nodes as well, like those highlighted in the right hand side picture?
MY THEORETICAL ATTEMPT
It looks like this problem is addressed by the Flood Fill algorithm, which is explained here. However, I wonder how it could be possible to simply count the number of nodes in the giant component(s) and then subtract it from the number of nodes that appear still active at stage 2. How would you implement this?
If I understand correctly, you are looking for "isolated" nodes, meaning the nodes not in the largest component of the graph. As you mentioned, one method to identify the "isolated" nodes is to find all the nodes NOT in the largest component. To do so, you can just use networkx.connected_components, to get a list of the components and sort them by size:
components = list(nx.connected_components(G)) # list because it returns a generator
components.sort(key=len, reverse=True)
Then you can find the largest component, and get a count of the "isolated" nodes:
largest = components.pop(0)
num_isolated = G.order() - len(largest)
I put this all together in an example where I draw a Erdos-Renyi random graph, coloring isolated nodes blue:
# Load modules and create a random graph
import networkx as nx, matplotlib.pyplot as plt
G = nx.gnp_random_graph(10, 0.15)
# Identify the largest component and the "isolated" nodes
components = list(nx.connected_components(G)) # list because it returns a generator
components.sort(key=len, reverse=True)
largest = components.pop(0)
isolated = set( g for cc in components for g in cc )
# Draw the graph
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos=pos, nodelist=largest, node_color='r')
nx.draw_networkx_nodes(G, pos=pos, nodelist=isolated, node_color='b')
nx.draw_networkx_edges(G, pos=pos)
plt.show()
I am trying to have nodes connect to a main node with different distances.
What I have so far:
import networkx as nx
G = nx.empty_graph( 3 , create_using= None)
G.add_edge(0,1)
G.add_edge(0,2)
Graph with equal distance to a main node
However, as it can be seen from the image, the distance between the node on either side have equal distance to the main node. Is there a way to have their distance to the main node different?
There are two parts to your question:
Part 1 - Distance between nodes:
In network theory, the distance between nodes is represented by the weight of the edge between them. So you can add all your edges with weights to your network with the following line:
G = nx.Graph()
G.add_weighted_edges_from([(0,1,4.0),(0,2,5.0)])
You can randomize the weights on the edges above for random distance between nodes.
Part 2 - Network Visualization:
I understand that you're more concerned with how the network graph is shown. If you use nx.draw_random(G) you can get randomized distances between your nodes, and suggest that you save a picture when you get the desired figure, as it randomizes every time you run.
Hope it helps... :)
I need to build something like an Erdos-Renyi model (random graph):
I need to create it from a dictionary of node positions that is generated by a deterministic function. This means that I cannot allow Python to randomly decide where each node goes to, as I want to decide it. The function is:
pos = dict( (n, n) for n in G.nodes() ).
I was thinking of creating an adjacency matrix first, in order to randomly generate something similar to pairs of (start, endpoint) of each edge, like this:
G=np.random.randint(0, 1, 25).reshape(5, 5)
Then I was thinking of somehow turning the matrix into my list of edges, like this:
G1=nx.grid_2d_graph(G)
but of course it does not work since this function takes 2 args and I am only giving it 1.
My questions:
How to create this kind of graph in NetworkX?
How to make sure that all nodes are connected?
How to make sure that, upon assigning the 1 in the matrix, each pair of nodes has the same probability of landing a 1?
Example for point 3. Imagine we created the regular grid of points which positions are determined according to pos. When we start connecting the network and we select the first node, we want to make sure that the endpoint of this first edge is one of the N-1 nodes left in the network (except the starting node itself). Anyhow, we want to make sure that all N-1 nodes have the same probability of being connected to the node we first analyze.
Thanks a lot!
I will try to build on the previous questions concerning this problem to be consistent. Given that you have the keys of the grid_2d_graph as 'n' and not (i,j) with the relabel nodes function:
N = 10
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() )
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.relabel_nodes(G,labels,False)
now you can set the pos dictionary to map from the 'n' keyed nodes to the positions you already have by switching keys with values. And then simply call the Erdos-Renyi function to create the graph that has a probability 'p' that an edge exists between any two nodes (except a self edge) as you described in point 3. Then draw with the pos dictionary.
pos = {y:x for x,y in labels.iteritems()}
G2 = nx.erdos_renyi_graph(100,0.1)
nx.draw_networkx(G2, pos=pos, with_labels=True, node_size = 300)
print G.nodes()
plt.axis('off')
plt.show()
As for ensuring that the graph is connected in point 2 You can not guarantee that the graph is connected with a probability 1, but you can read a bit about the size of the Giant component in Erdos-Renyi graph. But to avoid getting into theoretical details, one is almost sure that the graph will be connected when lambda which is n*p (here they are 100*0.1) is greater than 4. Though for smaller graphs (like 100 nodes) you better increase lambda. From my own experience using n= 100 and p = 0.1, produced a non-connected graph for only about 0.2% of the times and that is after thousands of simulations. And anyway you can always make sure if the produced graph is connected or not with the is_connected method.
I need to compute the density of a subgraph made of vertices belonging to the same attribute "group".
ie., let g be an iGraph graph,
g.vs.select(group = 1)
gives me an object with all vertices belonging to group 1
Is there any way to compute density on the graph which is formed by these vertices and the connections between them?
In a fashion similar to this maybe?
g2.vs(g2.vs.select(group = i)).density()
Try this:
g.vs.select(group=1).subgraph().density()
I would like to separate existing data of vertices and edges into two or more graphs that are not connected. I would like to give the following as example:
Imagine two hexagons on top of each other but are lying in different Z.
Hexagon 1 has the following vertices A(0,0,1), B(1,0,2), C(2,1,2), D(1,2,1), E(0,2,1), F(-1,2,1). The connectivity is as following: A-B, B-C, C-D, D-E, E-F, F-A. This part of Graph 1 as all the vertices are connected in this layer.
Hexagon2 has the following vertices A1(0,0,6), B1(1,0,7), C1(2,1,7), D1(1,2,8), E1(0,2,7), F1(-1,2,6). The connectivity is as following: A1-B1, B1-C1, C1-D1, D1-E1, E1-F1, F1-A1. This is part of Graph 2
My data is in the following form: list of Vertices and list of Edges that i can form graphs with. I would like to eliminate graph 2 and give only vertices and connectivity of graph 1 to polygon determination part of my algorithm. My real data contains around 1000 connected polygons as graph 1 and around 100 (much larger in area) polygons as graph 2. I would like to eliminate graph 2.
The problem you're describing relates to connected components.
The Python Networkx module has functions for dealing with this type of graph problems. You're looking for the connected_components function which returns all of the components, you can then pick the appropriate one (possible by number of vertices).