通过 Matplotlib 用 Dash 绘制有向图

Posted

技术标签:

【中文标题】通过 Matplotlib 用 Dash 绘制有向图【英文标题】:Plotting a directed graph with Dash through Matplotlib 【发布时间】:2019-12-20 07:31:26 【问题描述】:

似乎 Dash 无法通过 plotly 处理有向网络图。所以我正在通过 Matplotlib 使用 mpl_to_plotly 渲染图形。 一个图确实在网站上呈现,但没有边缘,并且有以下控制台输出:

当!该路径集合超出了这个世界。我完全不知道 怎么办呢! Plotly 只能导入链接的路径集合 到“数据”坐标

Matplotlib 代码

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)

在 Dash 中调用

dcc.Graph(id='network-graph', figure=plotly_fig)

还有其他方法可以在 Dash 中处理网络有向图吗?或者另一种使用 matplotlib 技术的方法?

【问题讨论】:

你试过 mpl_to_plotly(mpl_fig, resize=False, strip_style=False, verbose=False)? 感谢您的建议。这给出了与以前相同的结果。 【参考方案1】:

Plotly 中存在一个未解决的问题,即 mpl_to_ploty 不适用于 draw_networkx_edges (link)。

Plotly 本身也不支持有向边 (link),不过它们可能会使用注释中的箭头进行模拟。

鉴于该图形可能是使用 Plotly 语法手动构建的,例如作为(没有 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)

【讨论】:

以上是关于通过 Matplotlib 用 Dash 绘制有向图的主要内容,如果未能解决你的问题,请参考以下文章

用Matplotlib绘制渐变的彩色曲线

用Matplotlib绘制渐变的彩色曲线

如何使用 matplotlib 在 python 中绘制 3D 密度图

用matplotlib绘制简单的折线

用 Matplotlib 绘制 SVM?

用python的matplotlib和numpy库绘制股票K线均线和成交量的整合效果(含量化验证交易策略代码)