使用Plotly制作动画3D曲面图

6

我希望在Plotly中制作一个动态的三维表面图来可视化研究数据。目标是查看温度随时间变化在盒子内的演化过程。但我不知道如何实现动画效果。

目前我只有一个给定时间点的绘图。 以下是我的代码:

import plotly
import plotly.graph_objects as go
#import plotly.express as px
import pandas as pd
#import numpy as np

#read CSV
z_data = pd.read_csv('data1.csv')# Read data from a csv

fig = go.Figure(data=[go.Surface(z=z_data.values)])

#projection 2D
fig.update_traces(contours_z=dict(show=True, usecolormap=True,
                                  highlightcolor="tomato", project_z=True),
                                  colorscale='portland')

#fig
fig.update_layout(title='data HEATPILES', autosize=False, width=650, height=500, margin=dict(l=0, r=0, b=0, t=0))

#show
plotly.offline.plot(fig)

data1.csv只包含这个: data1.csv

但我有更多基于时间的点位置数据,并希望制作一个动画图,这样我们可以清晰地看到时间上的演变。

这是在特定时间的结果 给定时间的绘图结果

我在plotly文档中看到,可以利用px.scatter和px.line进行动画制作(来自此处),并且从这里可以了解如何使用影像进行动画制作,所以我想使用曲面图也是可能的。

如果您能帮我,我将不胜感激! 谢谢您的帮助,

Theophile

2个回答

2

以下是完整的代码:

import pandas as pd
import plotly.graph_objects as go

z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv').values
print(z_data)
z_data2 = z_data * 1.1
z_data3 = z_data * 1.2
z_data4 = z_data * 0.5

z_data_list = []
z_data_list.append(z_data)
z_data_list.append(z_data2)
z_data_list.append(z_data3)
z_data_list.append(z_data4)
z_data_list.append(z_data)
z_data_list.append(z_data2)
z_data_list.append(z_data3)
z_data_list.append(z_data4)

fig = go.Figure(
    data=[go.Surface(z=z_data_list[0])],
    layout=go.Layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None])])]),
    frames=[go.Frame(data=[go.Surface(z=k)], name=str(i)) for i, k in enumerate(z_data_list)]
)

fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor="tomato", project_z=True), colorscale='portland')

fig.update_layout(title='data HEATPILES', autosize=False, width=650, height=500, margin=dict(l=0, r=0, b=0, t=0))

def frame_args(duration):
    return {
            "frame": {"duration": duration},
            "mode": "immediate",
            "fromcurrent": True,
            "transition": {"duration": duration, "easing": "linear"},
        }

sliders = [
            {
                "pad": {"b": 10, "t": 60},
                "len": 0.9,
                "x": 0.1,
                "y": 0,
                "steps": [
                    {
                        "args": [[f.name], frame_args(0)],
                        "label": str(k),
                        "method": "animate",
                    }
                    for k, f in enumerate(fig.frames)
                ],
            }
        ]
    
fig.update_layout(sliders=sliders)
   
import plotly.io as pio

ii = 1
pio.write_html(fig, file="Live3D_"+str(ii)+".html", auto_open=True)
# plotly.offline.plot(fig)

1
谢谢!我希望作者能接受这个答案。 - Schach21
我尝试更改"duration"参数以改变转换速度,但是没有起作用,你有什么猜测吗?另外,你是如何想出这段代码的呢?我只是想问问,因为在未来我也想编写自己的代码。Plotly文档有点难以找到/探索。 - Schach21
1
如果您想更改播放按钮动画中帧的持续时间,则需要修改按钮定义“buttons = [dict(label =”Play“,method =”animate“,args = [None]”。 “def frame_args(duration):”参数调整滑块帧速率“args”:[[f.name],frame_args(0)]”,其中为0,因为我们手动更改幻灯片模式中的帧。但是假设您有很多帧并且要创建gif,即使gif也有限制,最小帧持续时间为20毫秒。 - bitbang
我应该使用什么代替args=[None]?如果我想要50毫秒,语法是args=["duration":50]吗?你分享的链接谈到了可能的args,但似乎没有一个是关于帧或转换持续时间的。 - Schach21
不确定,但我在某个地方读到Plotly使用d3.js后端。如果你需要速度,不建议使用plotly,请查看此处-> https://docs.juliaplots.org/latest/backends/#[Plotly-/-PlotlyJS](https://github.com/spencerlyon2/PlotlyJS.jl)。尝试这个“args=[None, {"frame": {"duration": 2000, "redraw": True},"fromcurrent": True, "transition": {"duration": 0}}]”,2000毫秒效果很好 :) - bitbang
显示剩余3条评论

0
经过充分的研究,我编写了这段代码以绘制适当的平滑三维曲面图。只需将数据框放入此函数中即可。您将获得一个适当的平滑曲面图。如果遇到任何错误,请仅选择数据框中为数字的特征。

'data_frame = data_frame.select_dtypes(include='number')'

from scipy import interpolate
from mpl_toolkits.mplot3d import axes3d, Axes3D

def surface(data_frame, title=None, title_x=0.5, title_y=0.9):

    X, Y = np.mgrid[-10:10:complex(0,data_frame.shape[0]), 
-10:10:complex(0,data_frame.shape[1])]
    Z = data_frame.values

    xnew, ynew = np.mgrid[-1:1:80j, -1:1:80j]
    tck = interpolate.bisplrep(X, Y, Z, s=0)
    znew = interpolate.bisplev(xnew[:,0], ynew[0,:], tck)

    fig = go.Figure(data=[go.Surface(z=znew)])
    fig.update_layout(template='plotly_dark', 
                      width=800, 
                      height=800,
                      title = title,
                      title_x = title_x, 
                      title_y = title_y
                     )
    return fig

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