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

Python 3D FuncAnimation无绘图输出:基于多pandas DataFrame逐帧渲染

3D散点动画无输出问题修复方案

核心错误原因

  • 散点对象初始化错误:原代码scatters中存储的是全零DataFrame,而非matplotlib 3D散点实例,_offsets3d是Axes3D.scatter()返回的散点对象的专属属性,不可作用于DataFrame,这是赋值后数据始终为0的核心原因
  • 逐帧函数逻辑错误:每帧都会遍历所有300个csv文件,没有按帧索引读取对应文件,相当于每帧都会覆盖写入所有文件数据,最终只会保留最后一个csv的内容
  • 动画参数配置错误:interval参数单位为毫秒,原代码设置为5000000000相当于每帧间隔约58天,动画完全无法正常推进
  • 缺失渲染触发逻辑:代码末尾未调用plt.show(),运行后不会弹出绘图窗口;且未显式在画布上创建初始散点对象,无内容可渲染
  • 语法错误:animate_scatters函数缩进错误、末尾存在多余三重引号,函数未正确闭合

修正后可运行代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
import os

def animate_scatters(iteration, csv_list, data_root, scatters):
    # 仅读取当前帧对应的数据文件
    file = csv_list[iteration]
    embedding = pd.read_csv(os.path.join(data_root, file), delimiter=',')
    embedding.columns = ["X","Y","Z","JD"]
    # 更新散点坐标,需传入可迭代的一维序列
    scatters._offsets3d = (embedding.X, embedding.Y, embedding.Z)
    return scatters,

def main(data_root, save=True):
    # 预读取所有csv文件路径,避免逐帧重复遍历目录
    csv_list = sorted([item for item in os.listdir(data_root) 
                      if not os.path.isdir(os.path.join(data_root,item)) 
                      and ".csv" in item])
    iterations = len(csv_list)
    # 提前读取第一个文件设置坐标轴范围,避免数据超出显示区域
    sample_df = pd.read_csv(os.path.join(data_root, csv_list[0]), delimiter=',')
    sample_df.columns = ["X","Y","Z","JD"]
    x_min, x_max = sample_df.X.min(), sample_df.X.max()
    y_min, y_max = sample_df.Y.min(), sample_df.Y.max()
    z_min, z_max = sample_df.Z.min(), sample_df.Z.max()

    # 创建画布与3D坐标轴
    fig = plt.figure()
    ax = p3.Axes3D(fig, auto_add_to_figure=True)

    # 初始化散点对象,而非存储DataFrame
    init_x = np.zeros(sample_df.shape[0])
    init_y = np.zeros(sample_df.shape[0])
    init_z = np.zeros(sample_df.shape[0])
    scatters = ax.scatter(init_x, init_y, init_z)

    # 设置坐标轴属性
    ax.set_xlim3d([x_min, x_max])
    ax.set_xlabel('X')
    ax.set_ylim3d([y_min, y_max])
    ax.set_ylabel('Y')
    ax.set_zlim3d([z_min, z_max])
    ax.set_zlabel('Z')
    ax.set_title('3D散点动画示例')

    # 创建动画,interval设置为每帧间隔50毫秒,对应20fps
    ani = animation.FuncAnimation(
        fig, animate_scatters, iterations, 
        fargs=(csv_list, data_root, scatters),
        interval=50, blit=False, repeat=False
    )

    if save:
        # 需提前安装ffmpeg才可保存视频
        Writer = animation.writers['ffmpeg']
        writer = Writer(fps=20, metadata=dict(artist='Me'), bitrate=1800, extra_args=['-vcodec', 'libx264'])
        ani.save('3d-iris.mp4', writer=writer)
    
    # 弹出绘图窗口显示动画
    plt.show()

data = '/Users/melanietu/Desktop/IRIS/3d'
main(data, save=True)

注:如果不需要保存视频,可将save参数设为False,运行后直接弹出动画窗口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 02:06:04