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
相关产品推荐
相关产品推荐

