Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redrawing Seaborn Figures for Animations

Some seaborn methods like JointPlot create new figures on each call. This makes it impossible to create a simple animation like in matplotlib where iterative calls to plt.cla() or plt.clf() allow to update the contents of a figure without closing/opening the window each time.

The only solution I currently see is:

for t in range(iterations):
    # .. update your data ..

    if 'jp' in locals():
        plt.close(jp.fig)

    jp = sns.jointplot(x=data[0], y=data[1])
    plt.pause(0.01)

This works because we close the previous window right before creating a new one. But of course, this is far from ideal.

Is there a better way? Can the plot somehow be done directly on a previously generated Figure object? Or is there a way to prevent these methods to generate new figures on each call?

like image 335
runDOSrun Avatar asked Sep 15 '17 10:09

runDOSrun


People also ask

How do I change my style in seaborn?

Seaborn has five built-in themes to style its plots: darkgrid , whitegrid , dark , white , and ticks . Seaborn defaults to using the darkgrid theme for its plots, but you can change this styling to better suit your presentation needs. To use any of the preset themes pass the name of it to sns. set_style() .

What is the seaborn Despine () function used for?

The despine() is a function that removes the spines from the right and upper portion of the plot by default. sns. despine(left = True) helps remove the spine from the left.


1 Answers

Unfortunately, sns.jointplot creates a figure by itself. In order to animate the jointplot, one might therefore reuse this created figure instead of recreating a new one in each interation.

jointplot internally creates a JointGrid, so it makes sense to directly use this and plot the joint axes and the marginals individually. In each step of the animation one would then update the data, clear the axes and set them up just as during creation of the grid. Unfortunately, this last step involves a lot of code lines.

The final code may then look like:

import matplotlib.pyplot as plt
import matplotlib.animation
import seaborn as sns
import numpy as np

def get_data(i=0):
    x,y = np.random.normal(loc=i,scale=3,size=(2, 260))
    return x,y

x,y = get_data()
g = sns.JointGrid(x=x, y=y, size=4)
lim = (-10,10)

def prep_axes(g, xlim, ylim):
    g.ax_joint.clear()
    g.ax_joint.set_xlim(xlim)
    g.ax_joint.set_ylim(ylim)
    g.ax_marg_x.clear()
    g.ax_marg_x.set_xlim(xlim)
    g.ax_marg_y.clear()
    g.ax_marg_y.set_ylim(ylim)
    plt.setp(g.ax_marg_x.get_xticklabels(), visible=False)
    plt.setp(g.ax_marg_y.get_yticklabels(), visible=False)
    plt.setp(g.ax_marg_x.yaxis.get_majorticklines(), visible=False)
    plt.setp(g.ax_marg_x.yaxis.get_minorticklines(), visible=False)
    plt.setp(g.ax_marg_y.xaxis.get_majorticklines(), visible=False)
    plt.setp(g.ax_marg_y.xaxis.get_minorticklines(), visible=False)
    plt.setp(g.ax_marg_x.get_yticklabels(), visible=False)
    plt.setp(g.ax_marg_y.get_xticklabels(), visible=False)


def animate(i):
    g.x, g.y = get_data(i)
    prep_axes(g, lim, lim)
    g.plot_joint(sns.kdeplot, cmap="Purples_d")
    g.plot_marginals(sns.kdeplot, color="m", shade=True)

frames=np.sin(np.linspace(0,2*np.pi,17))*5
ani = matplotlib.animation.FuncAnimation(g.fig, animate, frames=frames, repeat=True)

plt.show()

enter image description here

like image 129
ImportanceOfBeingErnest Avatar answered Sep 20 '22 00:09

ImportanceOfBeingErnest