I would like to draw a dynamic network to show how it changes over time as new observations are added. I've found how to animate a network given two single states (here called s_pos, t_pos), but what i'm looking for goes a little further, as I would like to populate my network row by row. I imagine that I need to update G by iterating through my dataframe within the function anim(t); which I struggle to achieve.
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# data
df = pd.DataFrame({'Date': ["2022-11-28", "2022-11-29", "2022-11-30", "2022-12-01"],
'ID' : ['A', 'B', 'C', 'A'],
'Value': ['X', 'Y', 'X', 'Z']})
# network
G = nx.from_pandas_edgelist(df, source='ID', target='Value')
# two states as an example
s_pos = nx.spring_layout(G)
t_pos = nx.circular_layout(G)
fig = plt.figure(figsize=(8, 8))
# animation function with smooth interpolation between states
def anim(t):
global s_pos
global t_pos
interpolation = {i: s_pos[i]*(1-t/299) + t_pos[i] * t/299 for i in list(t_pos.keys())}
plt.clf()
plt.cla()
nx.draw(G, pos=interpolation,
with_labels=True,
node_size = 5000)
# run and save
ani = animation.FuncAnimation(fig, anim, repeat=False, frames=300, interval=20)
f = r'path\network.gif'
writergif = animation.PillowWriter(fps=30)
ani.save(f, writer=writergif)
If I understand your question correctly that you would like to have your network progressively (row by row) appear in your animation, one way to do that would be to create a new network Gt
in the anim
function based on the rows of the dataframe up to t
. At each step of the animation, you can also clear the plot with ax.clear()
as in this post.
See example below:
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# data
df = pd.DataFrame({'Date': ["2022-11-28", "2022-11-29", "2022-11-30", "2022-12-01"],
'ID' : ['A', 'B', 'C', 'A'],
'Value': ['X', 'Y', 'X', 'Z']})
G = nx.from_pandas_edgelist(df, source='ID', target='Value') # create full graph G for reference
s_pos = nx.spring_layout(G)
t_pos = nx.circular_layout(G)
fig,ax = plt.subplots(figsize=(8, 8))
# animation function with smooth interpolation between states
def anim(t):
Gt=nx.from_pandas_edgelist(df.iloc[0:t], source='ID', target='Value') #create graph based n the row of the data frame up to t
interpolation = {i: s_pos[i]*(1-t/299) + t_pos[i] * t/299 for i in list(t_pos.keys())}
ax.clear() #clear axes
nx.draw(Gt, pos=interpolation,with_labels=True,node_size = 500,ax=ax)
ax.set_xlim([-1.5,1.5])
ax.set_ylim([-1.5,1.5])
# run and save
ani = animation.FuncAnimation(fig, anim, repeat=False, frames=300, interval=100)
plt.show()