You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Plotly在Python中实现每日新增数据的3D动画折线图

用Plotly实现3D动画折线图(逐行扩展+涨跌幅色彩映射)

数据预处理

基于你提供的股票数据生成代码,先将涨跌幅数据转换为累计净值(初始值100),并整理成适合Plotly 3D图的格式:

import yfinance as yf
import pandas as pd
import plotly.graph_objects as go

# 生成股票数据(原始代码)
stocks = ["AAPL", "MSFT"]
df_stocks = pd.DataFrame()
for stock in stocks:
    df = yf.download(stock, start="2022-01-01", end="2022-07-01", group_by='ticker')
    df['perct'] = df['Close'].pct_change()
    df_stocks[stock] = df['perct']

df_stocks.iloc[0] = 0
df_stocks += 1
df_stocks = df_stocks.cumprod()*100
df_stocks -= 100 

# 转换为累计净值(初始值100)
df_net_value = 100 + df_stocks

# 转换成长格式,方便处理每个数据点
df_long = df_net_value.reset_index().melt(id_vars='Date', var_name='Stock', value_name='NetValue')
# 关联涨跌幅数据(用于颜色映射)
df_long['Change'] = df_stocks.reset_index().melt(id_vars='Date', var_name='Stock', value_name='Change')['Change']

# 给股票分配Y轴数值(3D图需要数值型Y轴)
stock_y_map = {"AAPL": 0, "MSFT": 1}
df_long['Y'] = df_long['Stock'].map(stock_y_map)

构建动画帧

为每一天生成一个帧,每个帧包含从初始日到当前日的所有数据点,同时动态扩展X轴范围:

# 初始化帧列表
frames = []

# 获取所有日期
dates = df_long['Date'].unique()

# 生成初始帧(仅第一天数据)
initial_data = df_long[df_long['Date'] == dates[0]]
frames.append(go.Frame(
    data=[go.Scatter3d(
        x=initial_data['Date'],
        y=initial_data['Y'],
        z=initial_data['NetValue'],
        mode='lines+markers',
        marker=dict(
            size=6,
            color=initial_data['Change'],
            colorscale=[[0, '#8B0000'], [0.5, '#FFFFFF'], [1, '#006400']],
            cmin=df_long['Change'].min(),
            cmax=df_long['Change'].max(),
            colorbar=dict(title='涨跌幅(%)')
        ),
        line=dict(width=3)
    )],
    name=str(dates[0])
))

# 生成后续帧
for i in range(1, len(dates)):
    current_data = df_long[df_long['Date'] <= dates[i]]
    frames.append(go.Frame(
        data=[go.Scatter3d(
            x=current_data['Date'],
            y=current_data['Y'],
            z=current_data['NetValue'],
            mode='lines+markers',
            marker=dict(
                size=6,
                color=current_data['Change'],
                colorscale=[[0, '#8B0000'], [0.5, '#FFFFFF'], [1, '#006400']],
                cmin=df_long['Change'].min(),
                cmax=df_long['Change'].max(),
                colorbar=dict(title='涨跌幅(%)')
            ),
            line=dict(width=3)
        )],
        name=str(dates[i]),
        layout=go.Layout(
            scene=dict(
                xaxis=dict(range=[dates[0], dates[i]])
            )
        )
    ))

构建完整图表并添加控制组件

设置图表布局,添加播放/暂停按钮,完成动画配置:

# 初始布局
fig = go.Figure(
    data=frames[0]['data'],
    frames=frames,
    layout=go.Layout(
        title='股票累计净值3D动画折线图',
        scene=dict(
            xaxis=dict(title='日期', type='date'),
            yaxis=dict(title='股票', tickvals=[0,1], ticktext=['AAPL','MSFT']),
            zaxis=dict(title='累计净值(初始100)'),
            camera=dict(eye=dict(x=1.5, y=1.5, z=0.5))
        ),
        updatemenus=[dict(
            type='buttons',
            showactive=False,
            buttons=[dict(
                label='播放',
                method='animate',
                args=[None, dict(
                    frame=dict(duration=300, redraw=True),
                    transition=dict(duration=50),
                    fromcurrent=True
                )]
            ), dict(
                label='暂停',
                method='animate',
                args=[[None], dict(
                    frame=dict(duration=0, redraw=False),
                    transition=dict(duration=0)
                )]
            )]
        )]
    )
)

# 显示图表
fig.show()

关键说明

  • 逐行扩展数据:每个帧包含从初始日到当前日的全部数据,X轴范围随帧动态更新,确保始终显示已添加的所有日期。
  • 色彩映射:自定义颜色刻度将负涨跌幅(下跌)映射为深红色系,正涨跌幅(上涨)映射为深绿色系,数值越极端颜色越深。
  • 3D布局:Y轴用数值映射股票名称,Z轴展示累计净值,可通过拖拽视角调整查看角度。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:05:26