我实际上也遇到过类似的问题,相信我花了 2 个半小时才弄明白。让我们通过一个例子来理解。
fig = make_subplots(rows=1,cols=2,subplot_titles=('First plot','Second plot'),
specs=[[{'type': 'scene'}, {'type': 'scene'}]])
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3]), row=1,col=1)
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3], z=[0,1,2,3]), row=1,col=2)
fig.update_layout(title='Add Custom Data')
fig.show()
这将创建两个简单的 scatter3d 图,其中 hoverdata 是 x、y 和 z 轴。现在您想将数据 m=[9,8,7,6,5] 添加到第一个绘图中。您可以在 text 参数中解析 m 并添加 hovertemplate。
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
text=[9,8,7,6], hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}'), row=1,col=1)
这应该可以正常工作。但是现在我们想在第一个图(或任何图)中再添加一个列表,例如 n=[5,6,7,8]。这次我们将使用customdata 参数。
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
text=[9,8,7,6],customdata=[5,6,7,8],
hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}<br>n:%{customdata}'), row=1,col=1)
现在,如果我们想添加我们的第三个自定义数据列表怎么办。棘手的部分来了。不能解析自定义数据中两个列表的列表,然后调用customdata[0]和customdata[1],没那么简单。我们的第三个列表是k=[2,4,6,8]。
我们需要这样的customdata=[[[5],[2]],[[6],[4]],[[7],[6]],[[8],[8]]],它应该可以正常工作。基本上我们需要给出一个单独的列表(或数组),其中每个元素是您要显示的所有点的列表。
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
text=[9,8,7,6],customdata=[[[5],[2]],
[[6],[4]],
[[7],[6]],
[[8],[8]]],
hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}<br>n:%{customdata[0]}<br>k:%{customdata[1]}'), row=1,col=1)
我们几乎完成了,但还剩下一件事。像我们在 customdata 中给出的那样手动创建列表需要做很多工作,因此我们将使用强大的库 import numpy as np 自动化它
n = [5,6,7,8]
k = [2,4,6,8]
nk = np.empty(shape=(4,2,1), dtype='object')
nk[:,0] = np.array(n).reshape(-1,1)
nk[:,1] = np.array(k).reshape(-1,1)
fig.add_trace(go.Scatter3d(x=[0,1,2,3],y=[0,1,2,3],z=[0,1,2,3],
text=[9,8,7,6],customdata=nk,
hovertemplate='<br>x:%{x}<br>y:%{y}<br>z:%{z}<br>m:%{text}<br>n:%{customdata[0]}<br>k:%{customdata[1]}'), row=1,col=1)
轰!
如果要直接从数据框中添加数据,可以解析 df['Column name'] 代替 np.array(n)。