1

I am exporting an animation in python but the legend is repeating. I have only one plot and want to have one single legend item in every frame of the animation. This is my script:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
x = np.linspace(0., 10., 100)
y = np.linspace(0., 10., 100)
z = np.random.rand(100)
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot (111, projection="3d")

def init():
    # Plot the surface.
    ax.scatter3D(x, y, z, label='random', s=10)
    ax.set_zlabel('Z [m]')
    ax.set_ylabel('Y [m]')
    ax.set_xlabel('X [m]')
    plt.legend()
    ax.grid(None)
    return fig,

def animate(i):
    ax.view_init(elev=20, azim=i)
    return fig,

# Animate
ani = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=360, interval=200, blit=True)

# Export
ani.save('random data.gif', writer='pillow', fps=30, dpi=50)

And this is the animation in which legend is repeated three times:

enter image description here

I very much appreciate any help.

Ali_d
  • 1,089
  • 9
  • 24

3 Answers3

2

The issue is that init is called multiple times, You should avoid creating the graph in this function.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation

x = np.linspace(0., 10., 100)
y = np.linspace(0., 10., 100)
z = np.random.rand(100)
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot (111, projection="3d")

# Plot the surface.
ax.scatter3D(x, y, z, label='random', s=10)
ax.set_zlabel('Z [m]')
ax.set_ylabel('Y [m]')
ax.set_xlabel('X [m]')
plt.legend()
ax.grid(None)

def init():
    return fig,

def animate(i):
    ax.view_init(elev=20, azim=i)
    return fig,

# Animate
ani = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=360, interval=200, blit=True)

# Export
ani.save('random data.gif', writer='pillow', fps=30, dpi=50)

Output:

enter image description here

mozway
  • 194,879
  • 13
  • 39
  • 75
1

Hmm, it's not much of an answer, but I can't comment and still wanted to share this information:

I ran your script and it works fine for me:

enter image description here

I'm using anaconda environments, this is the one I used to run the script:

enter image description here

SjoCi
  • 101
  • 6
1

As was suggested here, replace plt.legend() with the following 3 lines:

def init():
    # Plot the surface.
    ax.scatter3D(x, y, z, label='not random', s=10)
    ax.set_zlabel('Z [m]')
    ax.set_ylabel('Y [m]')
    ax.set_xlabel('X [m]')

    # REPLACE plt.legend() STARTS HERE
    handles, labels = plt.gca().get_legend_handles_labels()
    by_label = dict(zip(labels, handles))
    plt.legend(by_label.values(), by_label.keys())
    # REPLACE plt.legend() ENDS HERE    

    ax.grid(None)
    return fig, 

enter image description here

Dr. Prof. Patrick
  • 1,280
  • 2
  • 15
  • 27
  • This fixes the legend, but there is still multiple times the same graph overlayed (you would see it if you added a incrementing value on x for example) – mozway Jan 25 '23 at 09:37