首页 > 解决方案 > 对于以networkx图为背景的大型数据集,使用matplotlib将多列动画为点非常慢

问题描述

在我之前的问题(如何使用 python 中的 NaN 的 pandas 数据帧中的 matplotlib 将多个列动画化为点)中,我设法将数据帧中的多个点动画化为动画。

但是,我想将动画的背景设置为网络图,以便点看起来像在网络的线上移动。

在 python 中使用来自 Pandas 数据框的 matplotlib 如何将多列动画化为点中的代码和 NaN

我创建了一个新的 MCV 示例,代码如下:

import random
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import math
import pandas as pd
from matplotlib import animation
#from JSAnimation import IPython_display
%matplotlib inline

# initialise graph object
G = nx.Graph()
color_map =[]
G.add_node(1, pos=(1, 0)); color_map.append('r')
G.add_node(2, pos=(2, 0)); color_map.append('r')
G.add_node(3, pos=(3, -1)); color_map.append('r')
G.add_node(4, pos=(3, 1)); color_map.append('r')
G.add_node(5, pos=(4, -1)) ;color_map.append('r')
G.add_node(6, pos=(4, 1)); color_map.append('r')
G.add_node(7, pos=(5, 0)); color_map.append('r')
G.add_node(8, pos=(6, 0));  color_map.append('r')

e = [(1, 2, 1), 
    (2, 3, 1), 
    (2, 4, 2), 
    (3, 5, 5), 
    (4, 6, 2), 
    (5, 7, 1), 
    (6, 7, 2), 
    (7, 8, 1)]

G.add_weighted_edges_from(e)
labels = nx.get_edge_attributes(G,'weight')

nx.draw(G,nx.get_node_attributes(G, 'pos'))
nx.draw_networkx_edge_labels(G,nx.get_node_attributes(G, 'pos'),edge_labels=labels)
nx.draw_networkx_labels(G,nx.get_node_attributes(G, 'pos'))

df_x = pd.DataFrame(data=
    np.array(
    [[np.NaN, np.NaN, np.NaN, np.NaN], 
     [1, np.nan, np.NaN,np.NaN], 
     [1.5, 4, np.NaN,np.NaN], 
     [2, 5, 3,4]]
        ), index= [1, 2, 3, 4], columns=[1, 2, 3, 4])
print(df_x)

df_y = pd.DataFrame(data=np.array(
    [[np.NaN, np.NaN, np.NaN, np.NaN], 
     [0, np.nan, np.NaN,np.NaN], 
     [0, -1, np.NaN,np.NaN], 
     [0, 0, 1,1]]
    ), index= [1, 2, 3, 4], columns=[1, 2, 3, 4])

%matplotlib notebook
from matplotlib import animation
#from JSAnimation import IPython_display
#from IPython.display import HTML

fig = plt.figure(figsize=(10,10))
ax = plt.axes()
nx.draw(G,nx.get_node_attributes(G, 'pos'),node_size = 10)
n_steps = df_x.index 

graph, = plt.plot([],[],'o')

def get_data_x(i):
    return df_x.loc[i]

def get_data_y(i):
    return df_y.loc[i]


def animate(i):
    x = get_data_x(i)
    y= get_data_y(i)
    graph.set_data(x,y)
    return graph,

animation.FuncAnimation(fig, animate, frames=n_steps, repeat=True, blit = True)

这将创建一个可行的动画,该动画有效。但是,当我使用一个非常大的数据集时(pandas 数据帧索引约为 8000 行 * 800 列,而不是我发布的示例 pandas 数据集),动画需要很长时间(小时左右)才能渲染,而且大多数时候我的浏览器(谷歌浏览器)崩溃。

所以我想可能是因为它需要重绘每一帧的网络图?如何将背景设置为 networkx 图?从那里开始,它只是绘图点,对吗?我的实际图有点大(~5000 个节点,~6000 个边)。

希望任何人都可以帮助我加快动画的渲染速度!

标签: pythonpandasdataframeanimationmatplotlib

解决方案


经过一番挖掘,当我尝试在 jupyter 笔记本中使用 matplotlib 将大型数据集动画化为动画时,我发现没有“简单”的解决方案。我刚刚决定将所有内容都写入一个 mp4 文件,该文件同样适用于动画。

我的代码包括 MVC 示例:

import random
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import math
import pandas as pd
from matplotlib import animation
#from JSAnimation import IPython_display
%matplotlib inline

# initialise graph object
G = nx.Graph()
color_map =[]
G.add_node(1, pos=(1, 0)); color_map.append('r')
G.add_node(2, pos=(2, 0)); color_map.append('r')
G.add_node(3, pos=(3, -1)); color_map.append('r')
G.add_node(4, pos=(3, 1)); color_map.append('r')
G.add_node(5, pos=(4, -1)) ;color_map.append('r')
G.add_node(6, pos=(4, 1)); color_map.append('r')
G.add_node(7, pos=(5, 0)); color_map.append('r')
G.add_node(8, pos=(6, 0));  color_map.append('r')

e = [(1, 2, 1), 
    (2, 3, 1), 
    (2, 4, 2), 
    (3, 5, 5), 
    (4, 6, 2), 
    (5, 7, 1), 
    (6, 7, 2), 
    (7, 8, 1)]

G.add_weighted_edges_from(e)
labels = nx.get_edge_attributes(G,'weight')

nx.draw(G,nx.get_node_attributes(G, 'pos'))
nx.draw_networkx_edge_labels(G,nx.get_node_attributes(G, 'pos'),edge_labels=labels)
nx.draw_networkx_labels(G,nx.get_node_attributes(G, 'pos'))

df_x = pd.DataFrame(data=
    np.array(
    [[np.NaN, np.NaN, np.NaN, np.NaN], 
     [1, np.nan, np.NaN,np.NaN], 
     [1.5, 4, np.NaN,np.NaN], 
     [2, 5, 3,4]]
        ), index= [1, 2, 3, 4], columns=[1, 2, 3, 4])
print(df_x)

df_y = pd.DataFrame(data=np.array(
    [[np.NaN, np.NaN, np.NaN, np.NaN], 
     [0, np.nan, np.NaN,np.NaN], 
     [0, -1, np.NaN,np.NaN], 
     [0, 0, 1,1]]
    ), index= [1, 2, 3, 4], columns=[1, 2, 3, 4])

def get_data_x(i):
    return df_x.loc[i]

def get_data_y(i):
    return sdf_y.loc[i]

def animate(i):
    x = get_data_x(i)
    y= get_data_y(i)   
    graph.set_data(x,y)
    return graph,

# Set up formatting for the movie files
Writer = animation.writers['ffmpeg']
writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)

fig = plt.figure(figsize=(20,20))
ax = plt.axes()

nx.draw(G,nx.get_node_attributes(G, 'pos'),node_size = 1)

n_steps = df_x.index 

graph, = plt.plot([],[],'o')

ani = animation.FuncAnimation(fig, animate, frames= n_steps, interval=1, repeat=True, blit = True)
ani.save('path/file.mp4', writer=writer)

推荐阅读