Could I generate a graph from the following data, where the node "root" is the the node with label "V_ini" and it has edges with the different items of a given list "List":
V_ini=(0,0,0)
List=[(a,b,c),(1,0,1),(1,2,2)]
The expected result is a graph like that:
(0,0,0)->(a,b,c)
(0,0,0)->(1,0,1)
(0,0,0)->(1,2,2)
Related
I`m trying to remove all nodes within a Graph that has an specific attribute value.
I have seen this: python networkx remove nodes and edges with some condition
But in that case the degree is a property and not an attribute.
My graph has an attribute call "Line" which could have different values like: A, B, C.
So for example I want to remove all nodes with attribute "Line" equal to A
You can filter nodes in your graph with a subgraph view:
filter_node = lambda node: G.nodes[node]['Line'] == 'A'
filtered_nodes = list(nx.subgraph_view(G, filter_node=filter_node).nodes)
You can then remove these nodes from the graph:
G.remove_nodes_from(e)
I have a social network graph 'G'.
I'm trying to check that they keys of my graph are in the characteristics dataset as well.
I ran this command:
for node in G.nodes():
if node in caste1.keys():
pass
else:
G = G.remove_node(node)
It shows an error RuntimeError: dictionary changed size during iteration
The RuntimeError is self-explanatory. You're changing the size of an object you're iterating within the iteration. It messes up the looping.
What you can do is to first iterate across the nodes to get the ones you would like to remove, and store it in a separate variable. Then you can iterate with this variable to remove the nodes:
# Identify nodes for removal
nodes2remove = [node for node in G.nodes() if node not in caste1.keys()]
# Remove target-nodes
for node in nodes2remove:
G = G.remove_node(node)
So, I've a data structure of graph as follows:
graph = {'graphData': {'nodes': List of Nodes,
'edges': List of Edges,}
}
In addition to that, I've a list of subgraphs as follows:
In first step, I add those subgraphs having one node as SOI [3 under Annotation 3] together to form something like this:
The following code take care of it:
for coreferanceGraph in unattached_graphs:
coreferanceGraph = self.merge_entity_in_graph(soi_node, coreferanceGraph, "value-entityName")
if coreferanceGraph:
edges_in_coreferenceGraph = coreferanceGraph['graphData']['edges']
nodes_in_coreferenceGraph = coreferanceGraph['graphData']['nodes']
for node in nodes_in_coreferenceGraph:
if node not in graph['graphData']['nodes']:
graph['graphData']['nodes'].append(node)
for edge in edges_in_coreferenceGraph:
if edge not in graph['graphData']['edges']:
graph['graphData']['edges'].append(edge)
attached_graphs.append(coreferanceGraph)
else:
continue
What happens in above code is that:
For every unattached subgraph in 1st image, I find if any subgraph has SOI node using function merge_entity_in_graph(). If SOI is present in subgraph, the subgraph is returned, and added to original Graph variables of structure defined defined by variables graph = dict().
In next step, I want to recursively add all those sugraphs in Image 1, to be added to open nodes present. In my case, according to Image 2, thats Ec, Ep, E1.
What I expect is:
Had there been more subgraphs with one of their nodes as Ef, Eq, Er, they also would have been added recursively.
My question is, how do I achieve this? I've written a method as follows, but not sure weather approach is right or not:
def add_other_subgraphs(self, subgraph, node, all_nodes, graph, coreference_graphs):
"""
Args:
subgraph (dict):
node (dict):
all_nodes (list):
graph (dict):
Returns:
"""
subgraph_edges = subgraph['graphData']['edges']
subgraph_nodes = subgraph['graphData']['nodes']
for node in subgraph_nodes:
if node not in graph['graphData']['nodes']:
graph['graphData']['nodes'].append(node)
for edge in subgraph_edges:
if edge not in graph['graphData']['edges']:
graph['graphData']['edges'].append(edge)
for node in graph['graphData']['nodes']:
coreference_graph = self.fetch_coreference_graph(node, coreference_graphs)
if coreference_graph:
graph = self.add_other_subgraphs(coreference_graph, node, all_nodes, graph, coreference_graphs)
else:
return graph
return graph
And the function add_other_subgraphs() will be called for each of Nodes i.e. Ec, Ep, E1
I have a graph with four nodes with two directional edges betweeen each node (a to b and b to a), so I use a multi Digraph. The graph already has the 'weight' attribute defined by default which for my case represent the capacity of each edge for traffic flow. I need to define two more attributes for each edge, let's say tcv1 and tcv2.
Being a beginner with Python and networkx I am not able to figure this out. Some google search took me here but I could not use it correctly.
add_attribute_to_edge(router_matrix, tmp_path[0][0], tmp_path[0][1], 'tcv1', traffic_cv[0])
I used code above where router_matrix is graph, tmp_path[x][x] will represent a node name like 'a' or 'b', tcv1 is the attribute and traffic_cv[0] in code will be an integer calculated. Printing tcv1 only gives {}.
Can someone suggest a solution or point out where I go wrong.
You could use the add_edge function to add new attributes to existing edges in a MultiDiGraph, but you need to watch out for the key keyword (its value needs to be 0).
In my example I add the tcv1 attribute the first "a" -> "b" edge (I use your variable names and my example graph created with add_edges_from):
import networkx as nx
router_matrix = nx.MultiDiGraph()
# add two weighted edges ("a" -> "b" and "b" -> "a")
router_matrix.add_edges_from([
("a", "b", {"weight": 0.5}),
("b", "a", {"weight": 0.99})
])
# print list of edges with all data
print(router_matrix.edges(data=True))
tmp_path = [["a", "b"], ["b", "a"]]
traffic_cv = [42, 66]
# add "tcv1" for only the first edge of tmp_path
router_matrix.add_edge(tmp_path[0][0], tmp_path[0][1], key=0, tcv1=traffic_cv[0])
print(router_matrix.edges(data=True))
To add tcv1 to all edges, you could use router_matrix.edges() to iterate trough all edges (note that here I use the G[src_node][dest_node][key][attribute] syntax instead of add_edge):
# add new attribute to all edges
counter = 0
for src, dest in router_matrix.edges():
router_matrix[src][dest][0]['tcv1'] = traffic_cv[counter]
counter += 1
print(router_matrix.edges(data=True))
I have an assignment to create a graph/map of nodes.
GRAPH = {}
""" ===================================================================
This function makes a network out of the two nodes
node1, node2 and puts them in a dictionary: graph
---------------------
node1 : Dictionary
key: node2 [neighbouring node]
value: 1
---------------------
node2 : Dictionary
key: node1 [neighbouring node]
value: 1
===================================================================== """
def make_link(graph, node1, node2):
if node1 not in graph:
graph[node1] = {}
(graph[node1])[node2] = 1
if node2 not in graph:
graph[node2] = {}
(graph[node2])[node1] = 1
return graph
flights = []
flights.append(("LAX","DFW"))
flights.append(("SAE","LAX"))
flights.append(("ORD","LAX"))
flights.append(("ORD","SAE"))
for (x,y) in flights:
make_link(GRAPH, x, y)
print GRAPH
Output:
codewingx#CodeLair:~/repo/python/Graphs$ python map.py
{'DFW': {'LAX': 1}, 'LAX': {'DFW': 1, 'ORD': 1, 'SAE': 1}, 'ORD': {'LAX': 1, 'SAE': 1}, 'SAE': {'ORD': 1, 'LAX': 1}}
I find it redundant as only the connected nodes are having a value of 1.
Q1. Shouldn't I be using a list of connected nodes instead of the inner dictionaries?
like:
{'DFW': ['LAX'], 'LAX': ['DFW', 'ORD', 'SAE'], 'ORD':['LAX','SAE'],'SAE':['ORD','LAX']}
Q2. Should I be adding all nodes and give them a value of 1 when connected else 0?
Q1: No. Dict of lists is slower for membership tests. You can avoid the redundant 1 values by using a dict of sets.
However, when working with graphs, there's frequently extra info we want to associate with nodes and edges ("labels", "coloring"). E.g. in your example you might store flight price or duration for each edge - it would naturally take the place of the 1s.
(This works well for directed graphs, where LAX->SAE and SAE->LAX prices are independent. Undirected graphs are trickier to implement; a neat trick is a dict whose keys are 2-element frozensets; but it might be simplest to duplicate data.)
Q2: No reason to, wasteful (most graphs have much less than n**2 edges) and is hard to maintain when dynamically adding/removing nodes. You could use collections.defaultdict(int) to simulate 0 wherever you haven't stored 1 (caveat: it'll store the 0s when accessed) but I recommend only looking at node2 in graph[node1] for connectivity checks, leaving graph[node1][node2] for extra edge data, if any.