Removing duplicates from animation's lened of a 3d plot in python

Question:

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.

Asked By: Ali_d

||

Answers:

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

Answered By: SjoCi

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

Answered By: Dr. Prof. Patrick

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

Answered By: mozway