In [1]:
import numpy as np

def create_sample_data():
    # Creates 100 points in R^3.
    X = []
    np.random.seed(1)
    for i in range(10):
        cluster_center = np.random.normal(scale=2, size=3)
        cluster = np.random.normal(size=(10, 3)) + cluster_center
        X += cluster.flatten().tolist()
    
    X = np.array(X).reshape((100, 3)).T
    
    return X - X.mean(axis=1).reshape((3,1))

In [2]:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML

def scatter3d(X, seconds=10, fps=10):

    # Angular step.
    step = 360 / (fps * seconds)
    
    # Create figure with 3d axis.
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    artist = ax.scatter(X[0], X[1], X[2])

    def animate(i):    
        ax.view_init(30, i * step)
        return (artist, )
    
    anim = animation.FuncAnimation(
        fig, animate, frames=fps * seconds, interval=1000/fps, 
        blit=True)
    return HTML(anim.to_html5_video())

In [3]:
X = create_sample_data()
scatter3d(X)


Out[3]: