Hypergraph with networkx - python

is anyone familiar with networkx?
I try to get a hypergraph, where i want to set the Hyperedges as other colored nodes (size dependent on their value) out of an list. And i want to set the Nodes out of an other list.
The documentation and examples on the networkx website are really spare, but i am sure it is possible.
I started with this example, but this is only an example for different edges. Can someone tell me how i can put up two different set of nodes with different color/size in networkx?

Did you want something like this use nx.draw_networkx_nodes using nodelist parameter:
# Author: Aric Hagberg (hagberg#lanl.gov)
import matplotlib.pyplot as plt
import networkx as nx
G = nx.Graph()
G.add_edge('a', 'b', weight=0.6)
G.add_edge('a', 'c', weight=0.2)
G.add_edge('c', 'd', weight=0.1)
G.add_edge('c', 'e', weight=0.7)
G.add_edge('c', 'f', weight=0.9)
G.add_edge('a', 'd', weight=0.3)
elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] > 0.5]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] <= 0.5]
pos = nx.spring_layout(G) # positions for all nodes
# nodes
nx.draw_networkx_nodes(G, pos, node_size=700, nodelist=['e','f','b'])
nx.draw_networkx_nodes(G, pos, node_size=1400, nodelist=['c','a','d'], node_color='blue')
# edges
nx.draw_networkx_edges(G, pos, edgelist=elarge,
width=6)
nx.draw_networkx_edges(G, pos, edgelist=esmall,
width=6, alpha=0.5, edge_color='b', style='dashed')
# labels
nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif')
plt.axis('off')
plt.show()
Output:
And changing labels and shapes too:
# Author: Aric Hagberg (hagberg#lanl.gov)
import matplotlib.pyplot as plt
import networkx as nx
G = nx.Graph()
G.add_edge('a', 'b', weight=0.6)
G.add_edge('a', 'c', weight=0.2)
G.add_edge('c', 'd', weight=0.1)
G.add_edge('c', 'e', weight=0.7)
G.add_edge('c', 'f', weight=0.9)
G.add_edge('a', 'd', weight=0.3)
elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] > 0.5]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] <= 0.5]
pos = nx.spring_layout(G) # positions for all nodes
# nodes
nx.draw_networkx_nodes(G, pos, node_size=700, nodelist=['e','f','b'])
nx.draw_networkx_nodes(G, pos, node_size=1400, nodelist=['c','a','d'],
node_color='blue', node_shape='^')
# edges
nx.draw_networkx_edges(G, pos, edgelist=elarge,
width=6)
nx.draw_networkx_edges(G, pos, edgelist=esmall,
width=6, alpha=0.5, edge_color='b', style='dashed')
# labels
nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif',
labels={'f':'f','e':'e','b':'b'})
nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif', font_color='white',
labels={'d':'d','a':'a','c':'c'})
plt.axis('off')
plt.show()
Output:

Related

Unwanted edge displayed in the network which shouldn't exist in principle in hvplot.networkx

I'm using this code to make a network and have edges shown differently based on an edge attribute, in this case 'Polarity'. But the result I get has extra edge(s) which are not specified. Please have a look. I can't figure it out.
import networkx as nx
import hvplot.networkx as hvnx
G = nx.Graph()
G.add_edge('a', 'b', Polarity="positive")
G.add_edge('a', 'c', Polarity="positive")
G.add_edge('c', 'd', Polarity="positive")
G.add_edge('c', 'e', Polarity="negative")
G.add_edge('c', 'f', Polarity="negative")
G.add_edge('a', 'd', Polarity="negative")
elarge = [(u, v) for (u, v, attr) in G.edges(data=True) if attr['Polarity'] == "positive"]
esmall = [(u, v) for (u, v, attr) in G.edges(data=True) if attr['Polarity'] == "negative"]
pos = nx.spring_layout(G) # positions for all nodes
# nodes
nodes = hvnx.draw_networkx_nodes(G, pos, node_size=700)
# edges
edges1 = hvnx.draw_networkx_edges(
G, pos, edgelist=elarge, edge_width=6)
edges2 = hvnx.draw_networkx_edges(
G, pos, edgelist=esmall, edge_width=6, alpha=0.5, edge_color='blue', style='dashed')
labels = hvnx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif')
edges2 * nodes * labels
Why do I get additional edge(s) 'c','d' in this case? Thanks.

networkx directed graph can't add weight in the middle of the edges from pandas df

My dataframe columns are A,B,Weight. Around 50 rows
Here is my code
G = nx.from_pandas_edgelist(df, source='A',
target='B',
create_using=nx.DiGraph())
weight = nx.get_edge_attributes(G, 'Weight')
pos = nx.circular_layout(G, scale=1)
nx.draw(G, pos, with_labels=True)
nx.draw_networkx_nodes(G, pos, node_size=300)
nx.draw_networkx_edges(G, pos=pos, edgelist=G.edges(), edge_color='black')
nx.draw_networkx_labels(G, pos=pos, edge_labels=weight)
plt.show()
It can generate a directed graph that has many edges, and connect A to B.
But it still can't display the weight in the middle of the edge,
What should I do?
There are two errors that prevented this. First, you need to assign the edge attributes to the graph when defining it. Second, you need to use nx.draw_networkx_edge_labels() and not nx.draw_networkx_labels(). The latter is for node labels, not edge labels.
import pandas as pd
import networkx as nx
df = pd.DataFrame([[1, 2, 4], [3, 4, 2], [1, 3, 1]], columns=['A', 'B', 'Weight'])
G = nx.from_pandas_edgelist(df, source='A',
target='B',
create_using=nx.DiGraph(),
edge_attr='Weight')
weight = nx.get_edge_attributes(G, 'Weight')
pos = nx.circular_layout(G, scale=1)
nx.draw(G, pos, with_labels=True)
nx.draw_networkx_nodes(G, pos, node_size=300)
nx.draw_networkx_edges(G, pos=pos, edgelist=G.edges(), edge_color='black')
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=weight)
plt.show()
plots

How do I curve edges in networkX graph

I had previous asked this question on how to achieve curved edges in networkX. It was working fine with my previous data, but when I updated the data and the code I'm unsure where I'm going wrong. The edges are only curving for certain nodes, and actually adding connections twice. I don't know why it's drawing the edges twice, once in a straight line and once curved.
My code:
import matplotlib.pyplot as plt
import networkx as nx
G = nx.Graph()
G.add_edge("Ted", "May", weight=0.5)
G.add_edge("Ted", "Ray", weight=1)
G.add_edge("Ted", "Chris", weight=1)
G.add_edge("Ted", "Sam", weight=3)
G.add_edge("Ted", "April", weight=1)
G.add_edge("Ted", "Ana", weight=0)
G.add_edge("Ana", "Ryan", weight=1)
G.add_edge("Ana", "Jim", weight=0.5)
G.add_edge("Ana", "Ben", weight=1)
for0 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 0]
for05 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 0.5]
for1 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 1]
for15 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 1.5]
for3 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 3]
pos = nx.circular_layout(G) # positions for all nodes
ax=plt.gca()
# nodes
sc = nx.draw_networkx_nodes(G, pos, node_size=700)
# edges
nx.draw_networkx_edges(G, pos, edgelist=for0, width=0)
nx.draw_networkx_edges(G, pos, edgelist=for05, width=0.5)
nx.draw_networkx_edges(G, pos, edgelist=for1, width=1)
nx.draw_networkx_edges(G, pos, edgelist=for15, width=1.5)
nx.draw_networkx_edges(G, pos, edgelist=for3, width=3)
for edge in G.edges():
source, target = edge
rad = 0.2
arrowprops=dict(arrowstyle="-",
color='blue',
connectionstyle=f"arc3,rad={rad}",
linestyle= '-',
alpha=0.6,)
ax.annotate("",
xy=pos[source],
xytext=pos[target],
arrowprops=arrowprops
)
# labels
nx.draw_networkx_labels(G, pos, font_size=20, font_family="sans-serif")
plt.show()
The straight edges come from the nx.draw_networkx_edges() calls. If you remove them, you are left with just the curved edges, but they don't have the specified edge weights. You can update the for loop as below to get the curved edges with edge weights.
for edge in G.edges():
source, target = edge
rad = 0.2
arrowprops=dict(lw=G.edges[(source,target)]['weight'],
arrowstyle="-",
color='blue',
connectionstyle=f"arc3,rad={rad}",
linestyle= '-',
alpha=0.6)
ax.annotate("",
xy=pos[source],
xytext=pos[target],
arrowprops=arrowprops
)
The lw parameter sets the line width based on the "weight" edge attribute from the graph. If that's not what you want you can set it to some default value or remove it.

Curved edges in NetworkX

I currently have the following code for my networkx graph:
import matplotlib.pyplot as plt
import networkx as nx
g = nx.Graph()
# add edges
g.add_edge("a", "b", weight=0.6)
g.add_edge("a", "c", weight=0.2)
g.add_edge("c", "d", weight=0.1)
g.add_edge("c", "e", weight=0.7)
g.add_edge("c", "f", weight=0.9)
g.add_edge("a", "d", weight=0.3)
# group edges by attribute "weight"
elarge = [
(u, v) for (u, v, d) in g.edges(data=True)
if d["weight"] > 0.5]
esmall = [
(u, v) for (u, v, d) in g.edges(data=True)
if d["weight"] <= 0.5]
# compute the positions of nodes
pos = nx.circular_layout(g)
# plot the graph nodes
nx.draw_networkx_nodes(g, pos, node_size=700)
# plot the graph edges
nx.draw_networkx_edges(g, pos, edgelist=elarge, width=6)
nx.draw_networkx_edges(
g, pos, edgelist=esmall, width=6,
alpha=0.5, edge_color="b", style="dashed")
# annotate the nodes
nx.draw_networkx_labels(
g, pos, font_size=20, font_family="sans-serif")
# graphics config
plt.axis("off")
plt.show() # wait before exiting
which has the following output:
But what I want is for the connecting lines to be curved not straight. I couldn't find a line style in matplotlib that allows me to do that.
Similarly to this answer, you could do:
plt.figure(figsize=(15,8))
pos = nx.circular_layout(G) # positions for all nodes
ax = plt.gca()
for edge in G.edges():
source, target = edge
rad = 0.2
c = edge in elarge
arrowprops=dict(arrowstyle="-",
color='black' if c else 'blue',
connectionstyle=f"arc3,rad={rad}",
linestyle= '-' if c else '--',
alpha=0.6,
linewidth=5)
ax.annotate("",
xy=pos[source],
xytext=pos[target],
arrowprops=arrowprops
)
# nodes
nx.draw_networkx_nodes(G, pos, node_size=700, node_color='black')
# labels
nx.draw_networkx_labels(G, pos, font_size=20,
font_family="sans-serif",
font_color ='white')
plt.box(False)
plt.show()

Plotting a directed graph with Dash through Matplotlib

It seems Dash is unable to process directed network graphs via plotly. So I am going through Matplotlib to render the graph using mpl_to_plotly.
A graph does render on the site, but without the edges, and there is the following console output:
Dang! That path collection is out of this world. I totally don't know
what to do with it yet! Plotly can only import path collections linked
to 'data' coordinates
Matplotlib code
mpl_fig , ax = plt.subplots()
G = nx.Graph()
G.add_edge('a', 'b', weight=0.6)
G.add_edge('a', 'c', weight=0.2)
G.add_edge('c', 'd', weight=0.1)
G.add_edge('c', 'e', weight=0.7)
G.add_edge('c', 'f', weight=0.9)
G.add_edge('a', 'd', weight=0.3)
elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] > 0.5]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] <= 0.5]
pos = nx.spring_layout(G) # positions for all nodes
# nodes
nx.draw_networkx_nodes(G, pos, node_size=700)
# edges
nx.draw_networkx_edges(G, pos, edgelist=elarge,
width=6)
nx.draw_networkx_edges(G, pos, edgelist=esmall,
width=6, alpha=0.5, edge_color='b', style='dashed')
# labels
nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif')
# error with plotly no supporting this kind of thing. Ty exporting to image and just show the image. Sucks becaues it is not interactive... but at least im showing what I want.
print(pos)
#plt.show()
plotly_fig = mpl_to_plotly(mpl_fig)
called in Dash via
dcc.Graph(id='network-graph', figure=plotly_fig)
Is there another method to process network directed graphs in Dash? Or another way to use the matplotlib technique?
There is an opened issue in Plotly that mpl_to_ploty doesn't work with draw_networkx_edges (link).
Also Plotly doesn't natively support directed edges (link), they might be simulated with arrows from annotations though.
Given that graph figure might be constructed manually with Plotly syntax, e.g. as (without Matplotlib):
import networkx as nx
import dash
import dash_core_components as dcc
import dash_html_components as html
G = nx.DiGraph()
G.add_edge('a', 'b', weight=0.6)
G.add_edge('a', 'c', weight=0.2)
G.add_edge('c', 'd', weight=0.1)
G.add_edge('c', 'e', weight=0.7)
G.add_edge('c', 'f', weight=0.9)
G.add_edge('a', 'd', weight=0.3)
elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] > 0.5]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] <= 0.5]
pos = nx.spring_layout(G) # positions for all nodes
Xn=[pos[k][0] for k in pos]
Yn=[pos[k][1] for k in pos]
labels = [k for k in pos]
nodes=dict(type='scatter',
x=Xn,
y=Yn,
mode='markers+text',
marker=dict(size=28, color='rgb(31,120,180)'),
textfont=dict(size=22, color='#DBD700'),
text=labels,
hoverinfo='text')
Xaxis=dict(showline=False, zeroline=False, showgrid=False, showticklabels=True,
mirror='allticks', ticks='inside', ticklen=5, tickfont = dict(size=14),
title='')
Yaxis=dict(showline=False, zeroline=False, showgrid=False, showticklabels=True,
mirror='allticks', ticks='inside', ticklen=5, tickfont = dict(size=14),
title='')
annotateELarge = [ dict(showarrow=True, arrowsize=0.9, arrowwidth=6, arrowhead=5, standoff=14, startstandoff=4,
ax=pos[arrow[0]][0], ay=pos[arrow[0]][1], axref='x', ayref='y',
x=pos[arrow[1]][0], y=pos[arrow[1]][1], xref='x', yref='y'
) for arrow in elarge]
annotateESmall = [ dict(showarrow=True, arrowsize=1.5, arrowwidth=2, arrowhead=5, opacity=0.5, standoff=14, startstandoff=4,
ax=pos[arrow[0]][0], ay=pos[arrow[0]][1], axref='x', ayref='y',
x=pos[arrow[1]][0], y=pos[arrow[1]][1], xref='x', yref='y'
) for arrow in esmall]
layout=dict(width=800, height=600,
showlegend=False,
xaxis=Xaxis,
yaxis=Yaxis,
hovermode='closest',
plot_bgcolor='#E5ECF6',
annotations= annotateELarge + annotateESmall, #arrows
)
plotly_fig = dict(data=[nodes], layout=layout)
#Dash page stub
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[
dcc.Graph(id='network-graph', figure=plotly_fig)
])
if __name__ == '__main__':
app.run_server(debug=True)

Categories