Saving matplotlib subplot figure to image file

2024/4/15 2:28:25

I'm fairly new to matplotlib and am limping along. That said, I haven't found an obvious answer to this question.

I have a scatter plot I wanted colored by groups, and it looked like plotting via a loop was the way to roll.

Here is my reproducible example, based on the first link above:

import matplotlib.pyplot as plt
import pandas as pd
from pydataset import datadf = data('mtcars').iloc[0:10]
df['car'] = df.indexfig, ax = plt.subplots(1)
plt.figure(figsize=(12, 9))
for ind in df.index:ax.scatter(df.loc[ind, 'wt'], df.loc[ind, 'mpg'], label=ind)
ax.legend(bbox_to_anchor=(1.05, 1), loc=2)
# plt.savefig('file.png')

Uncommenting yields what I want:

good plot

Searching around, it looked like plt.savefig() is the way to save a file; if I re-comment out and run plt.savefig() instead, I get a blank white picture. This question, suggests this is cause by calling show() before savefig(), but I have it entirely commented out. Another question has a comment suggesting I can save the ax object directly, but that cuts off my legend:

chopped legend

The same question has an alternative that uses fig.savefig() instead. I get the same chopped legend.

There's this question which seems related, but I'm not plotting a DataFrame directly so I'm not sure how to apply the answer (where dtf is the pd.DataFrame they're plotting):

plot = dtf.plot()
fig = plot.get_figure()

Thanks for any suggestions.

Edit: to test the suggestion below to try tight_layout(), I ran this and still get a blank white image file:

fig, ax = plt.subplots(1)
plt.figure(figsize=(12, 9))
for ind in df.index:ax.scatter(df.loc[ind, 'wt'], df.loc[ind, 'mpg'], label=ind)
ax.legend(bbox_to_anchor=(1.05, 1), loc=2)

Remove the line plt.figure(figsize=(12, 9)) and it will work as expected. I.e. call savefig before show.

The problem is that the figure being saved is the one created by plt.figure(), while all the data is plotted to ax which is created before that (and in a different figure, which is not the one being saved).

For saving the figure including the legend use the bbox_inches="tight" option

plt.savefig('test.png', bbox_inches="tight")

Of course saving the figure object directly is equally possible,

fig.savefig('test.png', bbox_inches="tight")

For a deeper understanding on how to move the legend out of the plot, see this answer.

Related Q&A

Numpy - Dot Product of a Vector of Matrices with a Vector of Scalars

I have a 3 dimensional data set that I am trying to manipulate in the following way. data.shape = (643, 2890, 10) vector.shape = (643,)I would like numpy to see data as a 643 length 1-D array of 2890x1…

delete node in binary search tree python

The code below is my implement for my binary search tree, and I want to implement delete method to remove the node. Below is my implementation, but when I perform bst = BSTRee() bst.insert(5) bst.inser…

ImportError: cannot import name cbook when using PyCharms Profiler

I am trying to run the PyCharm profiler but I get the following error message:Traceback (most recent call last):File "/home/b3053674/ProgramFiles/pycharm-2017.1.4/helpers/profiler/…

Replicating SAS first and last functionality with Python

I have recently migrated to Python as my primary tool for analysis and I am looking to be able to replicate the first. & last. functionality found in SAS. The SAS code would be as follows;data data…

Can mypy track string literals?

Is there anyway to make this work from typing import Literal def foo(bar: Literal["bar"]) -> Literal["foo"]:foo = "foo"return foobar = "bar" foo(bar)Here are …

Lazy loading of attributes

How would you implement lazy load of object attributes, i.e. if attributes are accessed but dont exist yet, some object method is called which is supposed to load these?My first attempt isdef lazyload…

Using pythons property while loading old objects

I have a rather large project, including a class Foo which recently needed to be updated using the @property decorator to create custom getter and setter methods.I also stored several instances of Foo …

How to replace all those Special Characters with white spaces in python?

How to replace all those special characters with white spaces in python ?I have a list of names of a company . . . Ex:-[myfiles.txt] MY company.INCOld Wine pvtmaster-minds ltd"apex-labs ltd"…

Python 3.x : move to next line

Ive got a small script that is extracting some text from a .html file.f = open(local_file,"r") for line in f:searchphrase = <span class="positionif searchphrase in line:print("fo…

Why couldnt Julia superset python?

The Julia Language syntax looks very similar to python, while the concept of a class (if one should address it as such a thing) is more what you use in C. There were many reasons why the creators decid…