I am looking for help to group network graph nodes by colour [duplicate] - pandas

I created my graph, everything looks great so far, but I want to update color of my nodes after creation.
My goal is to visualize DFS, I will first show the initial graph and then color nodes step by step as DFS solves the problem.
If anyone is interested, sample code is available on Github

All you need is to specify a color map which maps a color to each node and send it to nx.draw function. To clarify, for a 20 node I want to color the first 10 in blue and the rest in green. The code will be as follows:
G = nx.erdos_renyi_graph(20, 0.1)
color_map = []
for node in G:
if node < 10:
color_map.append('blue')
else:
color_map.append('green')
nx.draw(G, node_color=color_map, with_labels=True)
plt.show()
You will find the graph in the attached image.

Refer to node_color parameter:
nx.draw_networkx_nodes(G, pos, node_size=200, node_color='#00b4d9')

has been answered before, but u can do this as well:
# define color map. user_node = red, book_nodes = green
color_map = ['red' if node == user_id else 'green' for node in G]
graph = nx.draw_networkx(G,pos, node_color=color_map) # node lables

In my case, I had 2 groups of nodes (from sklearn.model_selection import train_test_split). I wanted to change the color of each group (default color are awful!). It took me while to figure it out how to change it but, Tensor is numpy based and Matplotlib is the core of networkx library. Therefore ...
test=data.y
test=test.numpy()
test=test.astype(np.str_)
test[test == '0'] = '#C6442A'
test[test == '1'] = '#9E2AC6'
nx.draw(G, with_labels=True, node_color=test, node_size=400, font_color='whitesmoke')
Long story short: convert the Tensor in numpy array with string type, check your best Hex color codes for HTML (https://htmlcolorcodes.com/) and you are ready to go!

Related

Networkx: nodes in the network disappear when colouring

I have a network graph in networkx created from a dictionary and want to colour a subset of nodes in a specific colour.
I created the original network graph using
nx.draw_networkx(g, with_labels=False, node_size=20)
Then I tried to colour a specific node in a different colour using the suggested solution in How to set colors for nodes in NetworkX?
Problems:
The code colours the node, but at the same time makes a lot of the other nodes disappear. What am I doing wrong?
Once 1) is resolved, what is the best way to modify the code to colour several nodes?
Thank you for your help!
for node in g:
if node == 'Bob':
color_map.append('red')
else:
color_map.append('blue')
nx.draw(g, node_color=color_map, with_labels=False, node_size=20)
Here is a code example where you can color code multiple nodes with a mapping dictionary. I was not able to reproduce the issue of missing nodes, run this code with your data and see if any nodes are missing.
import networkx as nx
from matplotlib import pyplot as plt
g = nx.Graph()
g.add_edges_from([('Bob', 'Steve'), ('Bob', 'Jeff'), ('Jeff', 'George'), ('Jeff', 'Steve')])
node_map = {'Bob': 'red', 'Jeff': 'green'}
color_map = [node_map.get(n, 'blue') for n in g.nodes]
nx.draw_networkx(g, node_color=color_map, with_labels=True, node_size=200)
plt.show()

Show class probabilities from Numpy array

I've had a look through and I don't think stack has an answer for this, I am fairly new at this though any help is appreciated.
I'm using an AWS Sagemaker endpoint to return a png mask and I'm trying to display the probability as a whole of each class.
So first stab does this:
np.set_printoptions(threshold=np.inf)
pred_map = np.argmax(mask, axis=0)
non_zero_mask = pred_map[pred_map != 0]) # get everything but background
# print(np.bincount(pred_map[pred_map != 0]).argmax()) # Ignore this line as it just shows the most probable
num_classes = 6
plt.imshow(pred_map, vmin=0, vmax=num_classes-1, cmap='jet')
plt.show()
As you can see I'm removing the background pixels, now I need to show class 1,2,3,4,5 have X probability based on the number of pixels they occupy - I'm unsure if I'll reinvent the wheel by simply taking the total number of elements from the original mask then looping and counting each pixel/class number etc - are there inbuilt methods for this please?
Update:
So after typing this out had a little think and reworded some of searches and came across this.
unique_elements, counts_elements = np.unique(pred_map[pred_map != 0], return_counts=True)
print(np.asarray((unique_elements, counts_elements)))
#[[ 2 3]
#[87430 2131]]
So then I'd just calculate the % based on this or is there a better way? For example I'd do
87430 / 89561(total number of pixels in the mask) * 100
Giving 2 in this case a 97% probability.
Update for Joe's comment below:
rec = Record()
recordio = mx.recordio.MXRecordIO(results_file, 'r')
protobuf = rec.ParseFromString(recordio.read())
values = list(rec.features["target"].float32_tensor.values)
shape = list(rec.features["shape"].int32_tensor.values)
shape = np.squeeze(shape)
mask = np.reshape(np.array(values), shape)
mask = np.squeeze(mask, axis=0)
My first thought was to use np.digitize and write a nice solution.
But then I realized how you can hack it in 10 lines:
import numpy as np
import matplotlib.pyplot as plt
size = (10, 10)
x = np.random.randint(0, 7, size) # your classes, seven excluded.
# empty array, filled with mask and number of occurrences.
x_filled = np.zeros_like(x)
for i in range(1, 7):
mask = x == i
count_mask = np.count_nonzero(mask)
x_filled[mask] = count_mask
print(x_filled)
plt.imshow(x_filled)
plt.colorbar()
plt.show()
I am not sure about the axis convention with imshow
at the moment, you might have to flip the y axis so up is up.
SageMaker does not provide in-built methods for this.

Edge colors in barplots based on hue/palette

I am trying to set the edge color for the barplot created using seaborn. The issue seems to be when I use hue parameter.
Instead of having a separate color for each individual bar, the edgecolor parameter applies the color to the whole hue/group.
Reproducing the issue via this simple example.
tips = sns.load_dataset("tips")
t_df = tips.groupby(['day','sex'])['tip'].mean().reset_index()
Hence t_df will be ,
clrs = ["#348ABD", "#A60628"]
t_ax = sns.barplot(x='day',y='tip',hue='sex',data=t_df,alpha=0.75,palette= sns.color_palette(clrs),edgecolor=clrs)
plt.setp(t_ax.patches, linewidth=3) # This is just to visualize the issue.
The output this gives ,
What I want is the blue bar should be having blue edge color and same for red. What code change would this require ?
This is somewhat hacky but it gets the job done:
import matplotlib.patches
# grab everything that is on the axis
children = t_ax.get_children()
# filter for rectangles
for child in children:
if isinstance(child, matplotlib.patches.Rectangle):
# match edgecolors to facecolors
clr = child.get_facecolor()
child.set_edgecolor(clr)
EDIT:
#mwaskom's suggestion is obviously much cleaner. For completeness:
for patch in t_ax.patches:
clr = patch.get_facecolor()
patch.set_edgecolor(clr)

Using Weights to Draw a Graph with NetworkX

I have a list of edges:
[[0,0,0], [0,1,1], [0,2,1], [2,3,2], ....[n,m,t]]
Where index 0 is a node, index 1 in the list is a node to, and index 2 is the weight value.
What I want to do is something like this:
```
0
/ \
1 2 All values of weights of 1
\
3 all values of weight of 2
```
Orientation does not matter, it's just easier to draw vertically in the editor.
I would like to export this using matplotlib.
Thanks!
Is the list of edges you presented representative of all your data? If it is, you don't even need the weights to draw the image you want (given your example).
In the code below I'm using graphviz_layout to calculate the graph/tree layout. Note that the code is written for Python 2. Again, I'm using only the edges info without considering weights.
import networkx as nx
import matplotlib.pyplot as plt
data = [[0,0,0], [0,1,1], [0,2,1], [2,3,2]]
G = nx.Graph()
for row in data:
G.add_edge(row[0], row[1])
pos = nx.graphviz_layout(G, prog='dot') # compute tree layout
nx.draw(G, pos, with_labels=True, node_size=900, node_color='w') # draw tree and show node names
plt.show() # show image
Output:

How to set the nodes color with a given graph

I am using networkx and matplotlib
Now I want to set the color of nodes,and I read the graph from text file
G=nx.read_edgelist("Edge.txt")
nx.draw(G)
plt.show()
Here is the Edge file of example
0 1
0 2
3 4
Here is what I did,and is failed
import networkx as nx
import matplotlib.pyplot as plt
G = nx.read_edgelist("Edge.txt")
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G,pos,node_list=[0,1,2],node_color='B')
nx.draw_networkx_nodes(G,pos,node_list=[3,4],node_color='R')
plt.show()
the result is a lot of blue nodes without edges
So if I want to set the NodeListA=[0,1,2] to blue, NodeListB=[3,4] to red
How can I do that?
draw the nodes explicitly by calling the top-level function, draw_networkx_nodes
and pass in your node list as the value for the parameter node_list, and value for the parameter node_color, like so
nx.draw_network_nodes(G, pos, node_list=NodeListA, node_color="#5072A7")
the argument pos is just a python dictionary whose keys are the nodes of the graph and the values are x, y positions; an easy to to supply pos is to pass your graph object to spring_layout which will return the dictionary.
pos = nx.spring_layout(G)
alternatively, you can pass in the dictionary directly, e.g.,
pos = {
0:(2,2),
1:(3,5),
2:(1,2),
3:(5,5),
4:(7,4)
}
the likely cause of the code in the OP to execute is the call to read_edgelist; in particular, the file passed in is probably incorrectly formatted.
here's how to check this and also how to fix it:
G = nx.path_graph(5)
df = "/path/to/my/graphinit.edgelist"
nx.write_edgelist(G, df) # save a properly formatted edgelist file
G = nx.read_edgelist(df) # read that file back in