78

I'm starting to learn a bit of python (been using R) for data analysis. I'm trying to create two plots using seaborn, but it keeps saving the second on top of the first. How do I stop this behavior?

import seaborn as sns
iris = sns.load_dataset('iris')

length_plot = sns.barplot(x='sepal_length', y='species', data=iris).get_figure()
length_plot.savefig('ex1.pdf')
width_plot = sns.barplot(x='sepal_width', y='species', data=iris).get_figure()
width_plot.savefig('ex2.pdf')
Leb
  • 15,483
  • 10
  • 56
  • 75
Alex
  • 1,997
  • 1
  • 15
  • 32

4 Answers4

103

You have to start a new figure in order to do that. There are multiple ways to do that, assuming you have matplotlib. Also get rid of get_figure() and you can use plt.savefig() from there.

Method 1

Use plt.clf()

import seaborn as sns
import matplotlib.pyplot as plt

iris = sns.load_dataset('iris')

length_plot = sns.barplot(x='sepal_length', y='species', data=iris)
plt.savefig('ex1.pdf')
plt.clf()
width_plot = sns.barplot(x='sepal_width', y='species', data=iris)
plt.savefig('ex2.pdf')

Method 2

Call plt.figure() before each one

plt.figure()
length_plot = sns.barplot(x='sepal_length', y='species', data=iris)
plt.savefig('ex1.pdf')
plt.figure()
width_plot = sns.barplot(x='sepal_width', y='species', data=iris)
plt.savefig('ex2.pdf')
Leb
  • 15,483
  • 10
  • 56
  • 75
  • 8
    This answer "works", but it is a bit less preferred IMO as it relies on the matplotlib state machine interface rather than fully embracing the object-oriented interface. It's fine for quick plots, but at some point when scaling in complexity it would be better to use the latter. – mwaskom Mar 15 '16 at 20:28
18

I agree with a previous comment that importing matplotlib.pyplot is not the best software engineering practice as it exposes the underlying library. As I was creating and saving plots in a loop, then I needed to clear the figure and found out that this can now be easily done by importing seaborn only:

since version 0.11:

import seaborn as sns
import numpy as np

data = np.random.normal(size=100)
path = "/path/to/img/plot.png"

plot = sns.displot(data) # also works with histplot() etc
plot.fig.savefig(path)
plot.fig.clf() # this clears the figure

# ... continue with next figure

alternative example with a loop:

import seaborn as sns
import numpy as np

for i in range(3):
  data = np.random.normal(size=100)
  path = "/path/to/img/plot2_{0:01d}.png".format(i)

  plot = sns.displot(data)
  plot.fig.savefig(path)
  plot.fig.clf() # this clears the figure

before version 0.11 (original post):

import seaborn as sns
import numpy as np

data = np.random.normal(size=100)
path = "/path/to/img/plot.png"

plot = sns.distplot(data)
plot.get_figure().savefig(path)
plot.get_figure().clf() # this clears the figure

# ... continue with next figure
MF.OX
  • 2,366
  • 1
  • 24
  • 28
  • This approach does not work at the point of my comment here using seaborn 0.11.1 – RndmSymbl May 27 '21 at 08:34
  • @RndmSymbl Actually it still works but throws a lots of deprecation warnings about distplot() which might confuse the user. I have updated the answer to work with the new API using displot() and histplot(). Also, please note that if you use some Python IDE it will only display the latest plot - although intermediate plots are saved. – MF.OX May 28 '21 at 10:50
  • While it is true that the code in your answer does work. I find that the only reliable way to avoid figures overlapping each other is the ```plt.figure()``` call. I have a scenario where I am plotting a series of ```PairGrid()``` & ```FacetGrid()``` using combinations of ```histplot()```, ```lineplot()```, ```boxplot()``` and ```scatterplot()```. Using ```clf()```failed to prevent the issue. – RndmSymbl May 28 '21 at 16:44
13

Create specific figures and plot onto them:

import seaborn as sns
iris = sns.load_dataset('iris')

length_fig, length_ax = plt.subplots()
sns.barplot(x='sepal_length', y='species', data=iris, ax=length_ax)
length_fig.savefig('ex1.pdf')

width_fig, width_ax = plt.subplots()
sns.barplot(x='sepal_width', y='species', data=iris, ax=width_ax)
width_fig.savefig('ex2.pdf')
pir
  • 5,513
  • 12
  • 63
  • 101
mwaskom
  • 46,693
  • 16
  • 125
  • 127
0

I've found that if the interaction is turned off seaborn plot the heatmap normally.https://i.stack.imgur.com/LteoZ.png