Python 随着时间的推移在 Scatter3d 中绘制动画标记样式或点
Python plotly animate marker styles or points in Scatter3d over time
我有一个基于 plotly 和 Dash 的应用程序,带有 3D 散点图。数据头看起来像这样:
'Classname' 'Date' '0' '1' '2'
B 1542 0.95 0.98 0.80
B 1725 1.00 1.00 0.75
C 1620 0.74 0.36 0.85
我得到了 26 个 classes。并非每个 class 每年都有代表。现在我想通过 Date
变量为数据点设置动画,但其余数据应该始终可见,这样我就可以看到数据点在点云中的位置。
示例:所有数据点都是灰色的,只有当前数据框的点用颜色突出显示。
因为我不知道这是否可能,所以我只是尝试将动画帧添加为具有不同样式的附加点。但是动画不起作用,我不知道为什么。我可以看到 'data'、一个滑块和按钮,但没有动画帧。如果我点击 PLAY 没有任何反应。
有时,如果我在图表中单击周围,会突然出现一些额外的 'diamond' 点,但这是非常错误的,动画仍然无法正常工作。看起来像这样:
我坚持 this documentation and also tried the advice in 问题。
这是我创建图形的代码:
def animate_time_tsne(dff):
# make figure
fig_dict = {
"data": [],
"layout": {},
"frames": []
}
years = np.unique(dff['Date'])
styles = np.unique(dff['Classname'])
fig_dict["layout"]["hovermode"] = "closest"
fig_dict["layout"]["updatemenus"] = [
{
"buttons": [
{
"args": [None, {"frame": {"duration": 500, "redraw": False},
"fromcurrent": True, "transition": {"duration": 300,
"easing": "quadratic-in-out"}}],
"label": "Play",
"method": "animate"
},
{
"args": [[None], {"frame": {"duration": 0, "redraw": False},
"mode": "immediate",
"transition": {"duration": 0}}],
"label": "Pause",
"method": "animate"
}
],
"direction": "left",
"pad": {"r": 10, "t": 87},
"showactive": False,
"type": "buttons",
"x": 0.1,
"xanchor": "right",
"y": 0,
"yanchor": "top"
}
]
sliders_dict = {
"active": 0,
"yanchor": "top",
"xanchor": "left",
"currentvalue": {
"font": {"size": 20},
"prefix": "Year:",
"visible": True,
"xanchor": "right"
},
"transition": {"duration": 300, "easing": "cubic-in-out"},
"pad": {"b": 10, "t": 50},
"len": 0.9,
"x": 0.1,
"y": 0,
"steps": []
}
# create data
colors = px.colors.qualitative.Dark24 + px.colors.qualitative.Light24,
for i, style in enumerate(styles):
data_by_style = dff[dff['Classname'] == style]
data_dict = go.Scatter3d(
x=data_by_style['0'], y=data_by_style['1'], z=data_by_style['2'],
mode='markers', marker={'color': colors[0][i], 'size':5},
name=style,
#customdata=[data_by_style['Filename'], data_by_style['Classname']]
)
fig_dict['data'].append(data_dict)
fig_dict['data'] = fig_dict['data']*2
# create frames
for year in years:
if not np.isnan(year):
frame = {"data": [], "name": str(year), "traces":[1]}
data_by_year = dff[dff['Date'] == year]
for style in styles:
data_by_year_style = data_by_year[data_by_year['Classname'] == style]
data_dict = go.Scatter3d(
x=data_by_year_style['0'], y=data_by_year_style['1'],
z=data_by_year_style['2'],
mode='markers',
marker={'size': 15, 'symbol': 'diamond', 'color':colors[0][-1]},
name=style
)
frame['data'].append(data_dict)
fig_dict['frames'].append(frame)
slider_step = {"args": [
[year],
{"frame": {"duration": 300, "redraw": False},
"mode": "immediate",
"transition": {"duration": 300}}
],
"label": year,
"method": "animate"}
sliders_dict["steps"].append(slider_step)
fig_dict["layout"]["sliders"] = [sliders_dict]
return go.Figure(fig_dict)
我用 go.figure 找不到它,但我用 plotly express 找到了一个可行的解决方案。
dff.dropna(subset=['Date'], inplace=True) # drop nan values
dff = dff.sort_values('Date', ascending=True)
x_range = [dff['0'].min(), dff['0'].max()]
y_range = [dff['1'].min(), dff['1'].max()]
z_range = [dff['2'].min(), dff['2'].max()]
colors = px.colors.qualitative.Dark24 + px.colors.qualitative.Light24
fig = px.scatter_3d(
dff, x='0', y='1', z='2',
animation_frame='Date',
range_x=x_range, range_y=y_range, range_z=z_range,
height=900, width=1200
)
fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 300
fig.layout.updatemenus[0].buttons[0].args[1]['transition']['duration'] = 100
for x in fig.frames:
x.data[0]['marker']['color'] = '#ff00c2'
x.data[0]['marker']['symbol'] = 'diamond'
x.data[0]['marker']['size'] = 20
styles = np.unique(dff['Classname'])
for i, style in enumerate(styles):
data_by_style = dff[dff['Classname'] == style]
fig.add_trace(go.Scatter3d(
x=data_by_style['0'], y=data_by_style['1'], z=data_by_style['2'],
mode='markers',
marker={'color': colors[i], 'size': 5},
name=style,
opacity=0.1
))
return fig
我有一个基于 plotly 和 Dash 的应用程序,带有 3D 散点图。数据头看起来像这样:
'Classname' 'Date' '0' '1' '2'
B 1542 0.95 0.98 0.80
B 1725 1.00 1.00 0.75
C 1620 0.74 0.36 0.85
我得到了 26 个 classes。并非每个 class 每年都有代表。现在我想通过 Date
变量为数据点设置动画,但其余数据应该始终可见,这样我就可以看到数据点在点云中的位置。
示例:所有数据点都是灰色的,只有当前数据框的点用颜色突出显示。
因为我不知道这是否可能,所以我只是尝试将动画帧添加为具有不同样式的附加点。但是动画不起作用,我不知道为什么。我可以看到 'data'、一个滑块和按钮,但没有动画帧。如果我点击 PLAY 没有任何反应。
有时,如果我在图表中单击周围,会突然出现一些额外的 'diamond' 点,但这是非常错误的,动画仍然无法正常工作。看起来像这样:
我坚持 this documentation and also tried the advice in
这是我创建图形的代码:
def animate_time_tsne(dff):
# make figure
fig_dict = {
"data": [],
"layout": {},
"frames": []
}
years = np.unique(dff['Date'])
styles = np.unique(dff['Classname'])
fig_dict["layout"]["hovermode"] = "closest"
fig_dict["layout"]["updatemenus"] = [
{
"buttons": [
{
"args": [None, {"frame": {"duration": 500, "redraw": False},
"fromcurrent": True, "transition": {"duration": 300,
"easing": "quadratic-in-out"}}],
"label": "Play",
"method": "animate"
},
{
"args": [[None], {"frame": {"duration": 0, "redraw": False},
"mode": "immediate",
"transition": {"duration": 0}}],
"label": "Pause",
"method": "animate"
}
],
"direction": "left",
"pad": {"r": 10, "t": 87},
"showactive": False,
"type": "buttons",
"x": 0.1,
"xanchor": "right",
"y": 0,
"yanchor": "top"
}
]
sliders_dict = {
"active": 0,
"yanchor": "top",
"xanchor": "left",
"currentvalue": {
"font": {"size": 20},
"prefix": "Year:",
"visible": True,
"xanchor": "right"
},
"transition": {"duration": 300, "easing": "cubic-in-out"},
"pad": {"b": 10, "t": 50},
"len": 0.9,
"x": 0.1,
"y": 0,
"steps": []
}
# create data
colors = px.colors.qualitative.Dark24 + px.colors.qualitative.Light24,
for i, style in enumerate(styles):
data_by_style = dff[dff['Classname'] == style]
data_dict = go.Scatter3d(
x=data_by_style['0'], y=data_by_style['1'], z=data_by_style['2'],
mode='markers', marker={'color': colors[0][i], 'size':5},
name=style,
#customdata=[data_by_style['Filename'], data_by_style['Classname']]
)
fig_dict['data'].append(data_dict)
fig_dict['data'] = fig_dict['data']*2
# create frames
for year in years:
if not np.isnan(year):
frame = {"data": [], "name": str(year), "traces":[1]}
data_by_year = dff[dff['Date'] == year]
for style in styles:
data_by_year_style = data_by_year[data_by_year['Classname'] == style]
data_dict = go.Scatter3d(
x=data_by_year_style['0'], y=data_by_year_style['1'],
z=data_by_year_style['2'],
mode='markers',
marker={'size': 15, 'symbol': 'diamond', 'color':colors[0][-1]},
name=style
)
frame['data'].append(data_dict)
fig_dict['frames'].append(frame)
slider_step = {"args": [
[year],
{"frame": {"duration": 300, "redraw": False},
"mode": "immediate",
"transition": {"duration": 300}}
],
"label": year,
"method": "animate"}
sliders_dict["steps"].append(slider_step)
fig_dict["layout"]["sliders"] = [sliders_dict]
return go.Figure(fig_dict)
我用 go.figure 找不到它,但我用 plotly express 找到了一个可行的解决方案。
dff.dropna(subset=['Date'], inplace=True) # drop nan values
dff = dff.sort_values('Date', ascending=True)
x_range = [dff['0'].min(), dff['0'].max()]
y_range = [dff['1'].min(), dff['1'].max()]
z_range = [dff['2'].min(), dff['2'].max()]
colors = px.colors.qualitative.Dark24 + px.colors.qualitative.Light24
fig = px.scatter_3d(
dff, x='0', y='1', z='2',
animation_frame='Date',
range_x=x_range, range_y=y_range, range_z=z_range,
height=900, width=1200
)
fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 300
fig.layout.updatemenus[0].buttons[0].args[1]['transition']['duration'] = 100
for x in fig.frames:
x.data[0]['marker']['color'] = '#ff00c2'
x.data[0]['marker']['symbol'] = 'diamond'
x.data[0]['marker']['size'] = 20
styles = np.unique(dff['Classname'])
for i, style in enumerate(styles):
data_by_style = dff[dff['Classname'] == style]
fig.add_trace(go.Scatter3d(
x=data_by_style['0'], y=data_by_style['1'], z=data_by_style['2'],
mode='markers',
marker={'color': colors[i], 'size': 5},
name=style,
opacity=0.1
))
return fig