我正在为一个改编自https://plot.ly/python/network-graphs/的networkx图的plot.ly包装器。我无法弄清楚如何根据权重更改每个连接的宽度。权重在attr_dict
中为weight
。我尝试设置go.Line
个对象,但它无法正常工作:(。有任何建议吗?(如果可能,还有教程链接:))。从我在matplotlib中创建的绘图中附加网络结构的示例。
如何在图表中为每个连接设置单独的线宽?
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
答案 0 :(得分: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(...))
编辑:好的,所以事实证明,问题不仅仅是我现在坐下来的“线条”:
你有line
参数作为类似dict的对象列表,而plotly期望它是一个类似dict的对象。建立权重列表然后立即将所有权重添加到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]
避免这种情况。