I am following this example showing how to draw networkx graphs with plotly: Network graphs in Python
All I want is to find a way to use discontinuous color bar and the result should be something like β1β is red, β2β is blue etc. with no interpolation between integers. The numbers are already integers here, but as it is noted in the documentation (Discrete colors in Python), if the input is an array of numbers, it will be treated as a continues color scale.
I tried adding a str() around each appended number as
node_adjacencies.append(str(len(adjacencies[1])))
but this returns this error
raise ValueError(
ValueError:
Invalid element(s) received for the 'color' property of scatter.marker
Invalid elements include: ['12', '12', '15', '12', '9', '8', '4', '6', '8', '10']
The 'color' property is a color and may be specified as:
- A hex string (e.g. '#ff0000')
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
- A named CSS color:
aliceblue, antiquewhite, aqua, aquamarine, azure,
beige, bisque, black, blanchedalmond, blue,
blueviolet, ...,
yellow, yellowgreen
- A number that will be interpreted as a color
according to scatter.marker.colorscale
- A list or array of any of the above
Any ideas how to fix this? Any alternative method to assign colors?
You are searching for a discrete colorbar. Helpful topics:
Applying these two to the example from the docs you stated:
import plotly.graph_objects as go
import networkx as nx
import numpy
G = nx.random_geometric_graph(200, 0.125)
edge_x = []
edge_y = []
for edge in G.edges():
x0, y0 = G.nodes[edge[0]]['pos']
x1, y1 = G.nodes[edge[1]]['pos']
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines')
node_x = []
node_y = []
for node in G.nodes():
x, y = G.nodes[node]['pos']
node_x.append(x)
node_y.append(y)
node_adjacencies = []
node_text = []
for node, adjacencies in enumerate(G.adjacency()):
node_adjacencies.append(len(adjacencies[1]))
node_text.append('# of connections: '+str(len(adjacencies[1])))
# ------ this is the part where the discrete color bar is created ------
# how many colors do we need?
unique_values = len(set(node_adjacencies))
# create spaced numbers between 0 and 1
# double the values, i.e. 0, 0, 1, 1, 2, 2
color_bar_values = [val for val in np.linspace(0, 1, unique_values) for _ in range(2)]
# get some color values, you could also use a list of strings such as ['red', 'green'...] instead of px.colors.qualitative.Alphabet
# double the values, i.e. 'red', 'red', 'green', 'green'
discrete_colors = [val for val in px.colors.qualitative.Alphabet for _ in range(2)]
# combine values and colors, start colors at index 1
colorscale = [[value, color] for value, color in zip(color_bar_values, discrete_colors[1:])]
# delete first and last list item
colorscale.pop(0)
colorscale.pop(-1)
# ceate trace
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers',
hoverinfo='text',
marker=dict(
showscale=True,
colorscale=colorscale, # our discrete colorscale
color=node_adjacencies,
cmin=min(node_adjacencies),
cmax=max(node_adjacencies),
size=10,
line_width=2,
colorbar=dict(
title='Month',
tickvals= node_adjacencies, # custom tick vals and text
ticktext= node_adjacencies
)
),
text=node_text
)
# create figure
fig = go.Figure(data=[edge_trace, node_trace],
layout=go.Layout(
title='<br>Network graph made with Python',
titlefont_size=16,
showlegend=False,
hovermode='closest',
margin=dict(b=20,l=5,r=5,t=40),
annotations=[ dict(
text="Python code: <a href='https://plotly.com/ipython-notebooks/network-graphs/'> https://plotly.com/ipython-notebooks/network-graphs/</a>",
showarrow=False,
xref="paper", yref="paper",
x=0.005, y=-0.002 ) ],
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
)
fig.show()