如何在网络样式的Plotly图中设置每条线的宽度?(Python 3.6 | plot.ly)

7
我正在为我的networkx图绘制编写plot.ly包装器,修改自https://plot.ly/python/network-graphs/。我无法弄清楚如何根据权重更改每个连接的宽度。权重在attr_dict中作为weight给出。我尝试设置go.Line对象,但没有起作用:(。您有什么建议吗?(如果可能,请提供教程链接 :))附上一个示例,显示来自我在matplotlib中制作的绘图的网络结构。

如何为plotly中的每个连接设置单独的线宽?

enter image description here

import requests
from ast import literal_eval
import plotly.offline as py
from plotly import graph_objs as go
py.init_notebook_mode(connected=True)

# Import Data
pos = literal_eval(requests.get("https://pastebin.com/raw/P5gv0FXw").text)
df_plot = pd.DataFrame(pos).T
df_plot.columns = list("xy")
edgelist = literal_eval(requests.get("https://pastebin.com/raw/2a8ErW7t").text)
_fig_kws={"figsize":(10,10)}

# Plotting Function
def plot_networkx_plotly(df_plot, pos, edgelist, _fig_kws):
    # Nodes
    node_trace = go.Scattergl(
                         x=df_plot["x"],
                         y=df_plot["y"],
                         mode="markers",
    )
    # Edges
    edge_trace = go.Scattergl(
                         x=[], 
                         y=[],
                         line=[],
                         mode="lines"
    )

    for node_A, node_B, attr_dict in edgelist:
        xA, yA = pos[node_A]
        xB, yB = pos[node_B]
        edge_trace["x"] += [xA, xB, None]
        edge_trace["y"] += [yA, yB, None]
        edge_trace["lines"].append(go.Line(width=attr_dict["weight"],color='#888'))

    # Data
    data = [node_trace, edge_trace]
    layout = {
                "width":_fig_kws["figsize"][0]*100,
                "height":_fig_kws["figsize"][1]*100,

    }
    fig = dict(data=data, layout=layout)

    py.iplot(fig)
    return fig
plot_networkx_plotly(df_plot, pos, edgelist, _fig_kws)

# ---------------------------------------------------------------------------
# PlotlyDictValueError                      Traceback (most recent call last)
# <ipython-input-72-4a5d0e26a71d> in <module>()
#      46     py.iplot(fig)
#      47     return fig
# ---> 48 plot_networkx_plotly(df_plot, pos, edgelist, _fig_kws)

# <ipython-input-72-4a5d0e26a71d> in plot_networkx_plotly(df_plot, pos, edgelist, _fig_kws)
#      25                          y=[],
#      26                          line=[],
# ---> 27                          mode="lines"
#      28     )
#      29 

# ~/anaconda/lib/python3.6/site-packages/plotly/graph_objs/graph_objs.py in __init__(self, *args, **kwargs)
#     375         d = {key: val for key, val in dict(*args, **kwargs).items()}
#     376         for key, val in d.items():
# --> 377             self.__setitem__(key, val, _raise=_raise)
#     378 
#     379     def __dir__(self):

# ~/anaconda/lib/python3.6/site-packages/plotly/graph_objs/graph_objs.py in __setitem__(self, key, value, _raise)
#     430 
#     431         if self._get_attribute_role(key) == 'object':
# --> 432             value = self._value_to_graph_object(key, value, _raise=_raise)
#     433             if not isinstance(value, (PlotlyDict, PlotlyList)):
#     434                 return

# ~/anaconda/lib/python3.6/site-packages/plotly/graph_objs/graph_objs.py in _value_to_graph_object(self, key, value, _raise)
#     535             if _raise:
#     536                 path = self._get_path() + (key, )
# --> 537                 raise exceptions.PlotlyDictValueError(self, path)
#     538             else:
#     539                 return

# PlotlyDictValueError: 'line' has invalid value inside 'scattergl'

# Path To Error: ['line']

# Current path: []
# Current parent object_names: []

# With the current parents, 'line' can be used as follows:

# Under ('figure', 'data', 'scattergl'):

#     role: object

使用Ian Kent的答案进行更新:

我认为以下代码无法更改所有线条的权重。我尝试使用 weights 列表将所有宽度设置为 0.1 并得到了以下绘图: enter image description here

但是当我使用 width=0.1 时,它可以适用于所有线条: enter image description here

1个回答

1
我认为问题出在你的代码中以下这行:

我认为问题出在你的代码中以下这行:

edge_trace["lines"].append(go.Line(width=attr_dict["weight"],color='#888'))

尝试使用“line”而不是“lines”。这是Plotly API中有些令人困惑的方面,但在散点图中,模式是复数形式,用于更改轨迹属性的参数名称是单数形式。因此,
trace = go.Scatter(mode = 'markers', marker = dict(...))
trace = go.Scatter(mode = 'lines', line = dict(...))

编辑:好吧,现在我坐下来看了一下,发现问题比“lines”还多:
您的line参数是一个类似于字典的对象列表,而plotly希望它是一个单个的类似于字典的对象。构建重量列表,然后一次性将所有重量添加到line属性中似乎可以解决问题:
edge_trace = go.Scattergl(
                     x=[],
                     y=[],
                     mode="lines"
)

weights = []
for node_A, node_B, attr_dict in edgelist:
    xA, yA = pos[node_A]
    xB, yB = pos[node_B]
    edge_trace["x"] += [xA, xB, None]
    edge_trace["y"] += [yA, yB, None]
    weights.append(attr_dict["weight"])

edge_trace['line'] = dict(width=weights,color='#888')

此外,您正在节点前绘制线条,从而遮挡了它们。您应该进行更改。
data = [node_trace, edge_trace]

data = [edge_trace, node_trace]

避免这种情况。


嗨@Ian-Kent,感谢您的回答!您所说的模式和属性字典是有道理的。但是,我不知道宽度向量是否相应地更新了。我更新了我的答案,展示了一些关于您的答案的图表(代码)[https://pastebin.com/3KUjmC8n]。此外,感谢您提供节点和边缘排序的提示! - O.rka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接