Plotly 中多个 Sankey 子图的问题
Trouble with Multiple Sankey Subplots in Plotly
所以我一直在尝试创建一个包含多个 Sankey 图的图。具体来说,我不断收到一条错误消息 "Invalid property specified for object of type plotly.graph_objs.Sankey: 'xaxis'"。这似乎是在脚本到达 append_trace 命令时调用的。这是一个简单的示例代码,我在 Jupyter notebook 中 运行:
import plotly.tools as tools
import plotly.offline as offline
import plotly.graph_objs as go
offline.init_notebook_mode(connected = True)
trace1 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Joe", "Molly", "Gavin", "Octavio", "Leslie", "Natasha"],
color = ["blue", "red", "green", "yellow", "brown", "magenta"]
),
link = dict(
source = [0,1,3],
target = [5,5,0],
value = [6,8,3]
)
)
trace2 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Russia", "Gambia", "Sweden", "Bolivia", "Timor-Leste", "Kazakhstan", "Bhutan"],
color = ["red", "black", "brown", "magenta", "yellow", "blue", "orange"]
),
link = dict(
source = [0,1,4,6],
target = [7,7,7,3],
value = [6,8,3,3]
)
)
fig = tools.make_subplots(rows = 2, cols = 1)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 2, 1)
fig['layout'].update(
title = "Basic Sankey Diagram with Two Subplots",
font = dict(
size = 10
)
)
offline.iplot(fig)
当我 运行 它时,我得到以下回溯:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-dd6268edf7ab> in <module>
37 fig = tools.make_subplots(rows = 2, cols = 1)
38
---> 39 fig.append_trace(trace1, 1, 1)
40 fig.append_trace(trace2, 2, 1)
41
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in append_trace(self, trace, row, col)
1222 """, DeprecationWarning)
1223
-> 1224 self.add_trace(trace=trace, row=row, col=col)
1225
1226 def _set_trace_grid_position(self, trace, row, col):
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in add_trace(self, trace, row, col)
1069 return self.add_traces(data=[trace],
1070 rows=[row] if row is not None else None,
-> 1071 cols=[col] if col is not None else None
1072 )[0]
1073
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in add_traces(self, data, rows, cols)
1152 if rows is not None:
1153 for trace, row, col in zip(data, rows, cols):
-> 1154 self._set_trace_grid_position(trace, row, col)
1155
1156 # Make deep copy of trace data (Optimize later if needed)
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _set_trace_grid_position(self, trace, row, col)
1259 "An axis object for ({r},{c}) subplot "
1260 "cell got deleted.".format(r=row, c=col))
-> 1261 trace['xaxis'] = ref[0]
1262 trace['yaxis'] = ref[1]
1263
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in __setitem__(self, prop, value)
2823 # ### Validate prop ###
2824 if prop not in self._validators:
-> 2825 self._raise_on_invalid_property_error(prop)
2826
2827 # ### Get validator for this property ###
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _raise_on_invalid_property_error(self, *args)
3006 full_obj_name=full_obj_name,
3007 invalid_str=invalid_str,
-> 3008 prop_descriptions=self._prop_descriptions))
3009
3010 def update(self, dict1=None, **kwargs):
ValueError: Invalid property specified for object of type plotly.graph_objs.Sankey: 'xaxis'
我没有在我的跟踪中指定 xaxis,所以这到底是从哪里来的?似乎这部分可能与它有关:
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _set_trace_grid_position(self, trace, row, col)
1259 "An axis object for ({r},{c}) subplot "
1260 "cell got deleted.".format(r=row, c=col))
-> 1261 trace['xaxis'] = ref[0]
1262 trace['yaxis'] = ref[1]
1263
这是一个错误吗?我不知道。
有人帮忙!
尝试 this way 不附加操作:
将此添加到两条轨迹的定义中。
type='sankey',
将您的两个子图定义为数据数组。
data = Data([trace1, trace2])
定义fig
:
fig = dict(data=[data], layout=layout)
py.iplot(fig, validate=False)
最后,您需要使用字典添加布局定义,如我所引用的 post 所示。
我在 Plotly 社区论坛上 cross-posted 这个问题 here 并收到了解决它的答案(大部分)。我会在这里复制答案,这样即使 link 死了它也会被保留。
The trouble you’re running into is that make_subplots and append_trace only work for cartesian trace types right now. This is something we’re planning to improve for version 4, but in the meantime, the best approach is to specify the position of each sankey trace individually using the domain property.
import plotly.offline as offline
import plotly.graph_objs as go
offline.init_notebook_mode(connected = True)
trace1 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Joe", "Molly", "Gavin", "Octavio", "Leslie", "Natasha"],
color = ["blue", "red", "green", "yellow", "brown", "magenta"]
),
link = dict(
source = [0,1,3],
target = [5,5,0],
value = [6,8,3]
),
domain={
'x': [0, 0.45]
}
)
trace2 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Russia", "Gambia", "Sweden", "Bolivia", "Timor-Leste", "Canada", "Bhutan"],
color = ["red", "black", "brown", "magenta", "yellow", "blue", "orange"]
),
link = dict(
source = [0,1,4,6],
target = [7,7,7,3],
value = [6,8,3,3]
),
domain={
'x': [0.55, 1.0]
}
)
data = [trace1, trace2]
layout = go.Layout(
title = "Basic Sankey Diagram",
font = dict(
size = 10
)
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
这会并排生成两个子图:
我们可以指定 'y' 来垂直放置子图,而不是在域中指定 'x'。
这是一个很好的 hack,缺少对 Sankey 子图的 built-in 支持。唯一的缺点是我看不出如何为子图指定单独的标题。
所以我一直在尝试创建一个包含多个 Sankey 图的图。具体来说,我不断收到一条错误消息 "Invalid property specified for object of type plotly.graph_objs.Sankey: 'xaxis'"。这似乎是在脚本到达 append_trace 命令时调用的。这是一个简单的示例代码,我在 Jupyter notebook 中 运行:
import plotly.tools as tools
import plotly.offline as offline
import plotly.graph_objs as go
offline.init_notebook_mode(connected = True)
trace1 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Joe", "Molly", "Gavin", "Octavio", "Leslie", "Natasha"],
color = ["blue", "red", "green", "yellow", "brown", "magenta"]
),
link = dict(
source = [0,1,3],
target = [5,5,0],
value = [6,8,3]
)
)
trace2 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Russia", "Gambia", "Sweden", "Bolivia", "Timor-Leste", "Kazakhstan", "Bhutan"],
color = ["red", "black", "brown", "magenta", "yellow", "blue", "orange"]
),
link = dict(
source = [0,1,4,6],
target = [7,7,7,3],
value = [6,8,3,3]
)
)
fig = tools.make_subplots(rows = 2, cols = 1)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 2, 1)
fig['layout'].update(
title = "Basic Sankey Diagram with Two Subplots",
font = dict(
size = 10
)
)
offline.iplot(fig)
当我 运行 它时,我得到以下回溯:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-dd6268edf7ab> in <module>
37 fig = tools.make_subplots(rows = 2, cols = 1)
38
---> 39 fig.append_trace(trace1, 1, 1)
40 fig.append_trace(trace2, 2, 1)
41
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in append_trace(self, trace, row, col)
1222 """, DeprecationWarning)
1223
-> 1224 self.add_trace(trace=trace, row=row, col=col)
1225
1226 def _set_trace_grid_position(self, trace, row, col):
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in add_trace(self, trace, row, col)
1069 return self.add_traces(data=[trace],
1070 rows=[row] if row is not None else None,
-> 1071 cols=[col] if col is not None else None
1072 )[0]
1073
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in add_traces(self, data, rows, cols)
1152 if rows is not None:
1153 for trace, row, col in zip(data, rows, cols):
-> 1154 self._set_trace_grid_position(trace, row, col)
1155
1156 # Make deep copy of trace data (Optimize later if needed)
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _set_trace_grid_position(self, trace, row, col)
1259 "An axis object for ({r},{c}) subplot "
1260 "cell got deleted.".format(r=row, c=col))
-> 1261 trace['xaxis'] = ref[0]
1262 trace['yaxis'] = ref[1]
1263
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in __setitem__(self, prop, value)
2823 # ### Validate prop ###
2824 if prop not in self._validators:
-> 2825 self._raise_on_invalid_property_error(prop)
2826
2827 # ### Get validator for this property ###
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _raise_on_invalid_property_error(self, *args)
3006 full_obj_name=full_obj_name,
3007 invalid_str=invalid_str,
-> 3008 prop_descriptions=self._prop_descriptions))
3009
3010 def update(self, dict1=None, **kwargs):
ValueError: Invalid property specified for object of type plotly.graph_objs.Sankey: 'xaxis'
我没有在我的跟踪中指定 xaxis,所以这到底是从哪里来的?似乎这部分可能与它有关:
/anaconda3/lib/python3.7/site-packages/plotly/basedatatypes.py in _set_trace_grid_position(self, trace, row, col)
1259 "An axis object for ({r},{c}) subplot "
1260 "cell got deleted.".format(r=row, c=col))
-> 1261 trace['xaxis'] = ref[0]
1262 trace['yaxis'] = ref[1]
1263
这是一个错误吗?我不知道。
有人帮忙!
尝试 this way 不附加操作:
将此添加到两条轨迹的定义中。
type='sankey',
将您的两个子图定义为数据数组。
data = Data([trace1, trace2])
定义fig
:
fig = dict(data=[data], layout=layout)
py.iplot(fig, validate=False)
最后,您需要使用字典添加布局定义,如我所引用的 post 所示。
我在 Plotly 社区论坛上 cross-posted 这个问题 here 并收到了解决它的答案(大部分)。我会在这里复制答案,这样即使 link 死了它也会被保留。
The trouble you’re running into is that make_subplots and append_trace only work for cartesian trace types right now. This is something we’re planning to improve for version 4, but in the meantime, the best approach is to specify the position of each sankey trace individually using the domain property.
import plotly.offline as offline
import plotly.graph_objs as go
offline.init_notebook_mode(connected = True)
trace1 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Joe", "Molly", "Gavin", "Octavio", "Leslie", "Natasha"],
color = ["blue", "red", "green", "yellow", "brown", "magenta"]
),
link = dict(
source = [0,1,3],
target = [5,5,0],
value = [6,8,3]
),
domain={
'x': [0, 0.45]
}
)
trace2 = go.Sankey(
node = dict(
pad = 15,
thickness = 20,
line = dict(
color = "black",
width = 0.5
),
label = ["Russia", "Gambia", "Sweden", "Bolivia", "Timor-Leste", "Canada", "Bhutan"],
color = ["red", "black", "brown", "magenta", "yellow", "blue", "orange"]
),
link = dict(
source = [0,1,4,6],
target = [7,7,7,3],
value = [6,8,3,3]
),
domain={
'x': [0.55, 1.0]
}
)
data = [trace1, trace2]
layout = go.Layout(
title = "Basic Sankey Diagram",
font = dict(
size = 10
)
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
这会并排生成两个子图:
我们可以指定 'y' 来垂直放置子图,而不是在域中指定 'x'。
这是一个很好的 hack,缺少对 Sankey 子图的 built-in 支持。唯一的缺点是我看不出如何为子图指定单独的标题。