Layer Python Seaborn and then Save to Disk - python

I am trying to layer a swarmplot on top of a violin chart just like the seaborn documentation has here: https://seaborn.pydata.org/generated/seaborn.catplot.html
But in that example they are just displaying to the screen so the following works
sns.catplot(data=df, x="age", y="class", kind="violin", color=".9", inner=None)
sns.swarmplot(data=df, x="age", y="class", size=3)
But I need to save to a file like so..
cat_plot = sns.catplot ([args go here])
cat_plot.savefig ([args])
How do I add a swarmplot to my cat_plot FacetGrid so when I save it they are layered on top of each other in the resulting jpg? Or is there another way I should be trying to accomplish this?

sns.catplot returns a FacetGrid with one or more subplots. When there is only one subplot, the subsequent sns.swarmplot() will draw onto that same subplot. Afterward, you can simply save the figure, which will include the original catplot together with all elements that have been added, either via other seaborn functions, or directly via matplotlib.
As catplot can create multiple subplots, the recommended way to add a smarmplot to all of them would be via g.map_dataframe(sns.swarmplot, x="age", y="class", size=3). (But as there is only one subplot in your example, your code also works with calling sns.swarmplot directly.)
import seaborn as sns
df = sns.load_dataset('titanic')
g = sns.catplot(data=df, x="age", y="class", kind="violin", color=".9", inner=None)
g.map_dataframe(sns.swarmplot, x="age", y="class", size=3)
g.savefig('combined-violin-swarmplot.png')

Related

Convert matplotlib plot to numpy list to show using opencv2

so I am making 4 types of plots in matplotlib through functions. Those include Pie Charts, Line Charts, Scatter Plot and area graphs. I want to get a numpy array of it, so I can display it using opencv2 or something else on django. I have tried this so far:
import matplotlib.pyplot as plt
import numpy as np
# Make a random plot...
fig = plt.figure()
fig.add_subplot(111)
# If we haven't already shown or saved the plot, then we need to
# draw the figure first...
fig.canvas.draw()
# Now we can save it to a numpy array.
data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))
But the problem is I cannot use a plot here, I have to use a figure which I don't want to use. I tried doing plt.plot([1,2,3,4,5]) for line graph as a test, but it turns out it returns a list, while I need a figure to use the tostring_rgb() What should be the alternative to this?
EDIT:
Suggested in comments for another question, I am not wanting to make a figure, I want to make a normal Plot with plt.plot() of line graph, and also plt.pie()

Plots in Python saving as blank images?

I've created several plots in Python and am attempting to save them as .png files or pdfs. I'm using the following code to create after the data is input:
plt.xlabel('Sersic Index Number', fontsize=16)
plt.ylabel('Number', fontsize=16)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.title('Voids In VIKING', fontsize=20)
And the plot shows up great. However, whenever I use
plt.savefig('Sersic_Voids.png')
to save, it does so and the file shows up on my computer. For every time and filetype I use, the document is blank, without the plot, axes, or anything.
EDIT1: I'm already using the plt.savefig() format to save, but not having any luck. I don't have any plt.show() functions in, and each Jupiter Notebook has about two plots I'm trying to save, neither of which work. I've tried cutting half of the code into a blank workbook to save the first plot, but still trouble. The beginning is input as:
from astropy.io import fits
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
To save matplotlib plots as a file in the PC. Go below way
import matplotlib
import matplotlib.pyplot as plt
Now to make and see a chart, use the .plot() method with passing values to plot. For example, I'll plot simple points as
plt.plot([0, 1, 2, 3, 4], [0, 20, 40, 60, 85])
To add axis-labels
plt.xlabel('Number of people')
plt.ylabel('Total Weight')
To pop-up the graph call .show() method as,
plt.show()
To save the graph which you just plotted use .savefig() method
plt.savefig('weight_calculation.png')
weight_calculation -> filename
You can also give the path to the directory you want to save
Use dpi to change the resolution of figures you want to save
There few other add ons which you can use like,
transparent, bbox_inches, and pad_inches.
Change bbox_inches to change the size of outer white box around the figure

Using plots as objects in python (jupyter lab)?

I just started switching from R to python, and have been a bit confused by the way plots are handled.
In R, I would generate a scatter plot this way:
myPlot <- ggplot(myData, aes(x=x, y=y)) + geom_point(). myPlot will be treated as an object, I can save it, copy it, pass it, or just plot it later.
However, in python I couldn't figure out how to do it. For example, when I use:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({
'X': [1,2,3],
'Y': [4,5,6]
})
ax = df.plot(kind="scatter", x='X', y='Y')
all I want to do here is to save the plot to an object, so that it can be easily plotted later without executing all the code again (it's easy to redo in this dummy case but my data is far more complicated)
It seems that I was able to save some information into "ax", as suggested online, but I couldn't figure out how to reproduce the plot with the object "ax".
Thank you so much~
Have a look at the visualization section of the pandas docs.
ax in your example indeed holds the plot object. Depending on your environment you can save it to a figure or display it inline.
The easiest way is just to plt.show().

Is It Possible To Set Transparency When Using LineCollection in Matplotlib?

There are a number of helpful posts for using LineCollections in Matplotlib.
I have working code, but am having trouble figuring out how to set the transparency of the lines. For example, in Pandas it's as easy as doing:
df.plot(kind='line',alpha=.25)
However, I chose the LineCollection method because I want to plot a dataframe with >15k lines and the above example does not work.
I've tried adding ax.set_alpha(.25) in my code:
fig, ax = plt.subplots()
ax.set_xlim(np.min(may_days), np.max(may_days))
ax.set_ylim(np.min(may_segments.min()), np.max(may_segments.max()))
line_segments = LineCollection(may_segments,cmap='jet')
line_segments.set_array(may_days)
ax.add_collection(line_segments)
ax.set_alpha(.05)
ax.set_title('Daily May Data')
plt.show()
but there is no change.
Unfortunately I cannot provide a sample of the data with which I'm working; however, I've found the second example this Matplotlib gallery doc to be easy to copy.
You do it the same way you'd do it in pandas.
line_segments = LineCollection(may_segments, cmap='jet', alpha=0.05)

Change Spyder and Matplotlib figure size for saved plots only

I would like to view matplotlib plots inside Spyders IPython console in one size and save figures to a multipage PDF in a different size.
Currently I set the figure size as follows:
plt.rc('axes', grid=True)
plt.rc('figure', figsize=(12, 8))
plt.rc('legend', fancybox=True, framealpha=1)
Then I plot some figures and save them to a list for saving a PDF later on. This works just fine when used alone. The plots are approriately sized for viewing in Spyder IPython console.
At the end of my script I have a loop to go through each of the figures I want to save. In here I want to set the layout and figure size exactly for better printing on an A3 paper.
with PdfPages('multi.pdf') as pdf:
for fig in figs:
fig.tight_layout()
fig.set_size_inches(420/25.4, 297/25.4)
pdf.savefig(figure=fig)
The output PDF is just like I want it to be, but the problem is with the plots shown inside Spyder. Changing the figure size while saving also affects the plots viewed inside Spyder. And using the size of an A3 makes the plots way too big.
So the question is: How do I change the size of saved PDF figures without changing the size of figures shown inside Spyder?
As suggested by #ImportanceOfBeingErnest, changing the figure size back after saving should work and may probably solved you problem.
But, depending on your specific problem, it is possible that you are going to face scaling issues since the size of the figures saved in the pdf is much bigger than the size of those displayed in the IPython console. If you scale everything to look great on the pdf, then it is possible that everything is going to look too big in IPython as shown in the example below:
If you don't need the plot to be interactive in IPython, a solution may be to generate your figures to look good for the pdf and display a scaled bitmap version of them in the IPython console as shown in the code below:
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
import numpy as np
from IPython.display import Image, display
try: # Python 2
from cStringIO import StringIO as BytesIO
except ImportError: # Python 3
from io import BytesIO
# Generate a matplotlib figures that looks good on A3 format :
fig, ax = plt.subplots()
ax.plot(np.random.rand(150), np.random.rand(150), 'o', color='0.35', ms=25,
alpha=0.85)
ax.set_ylabel('ylabel', fontsize=46, labelpad=25)
ax.set_xlabel('xlabel', fontsize=46, labelpad=25)
ax.tick_params(axis='both', which='major', labelsize=30, pad=15,
direction='out', top=False, right=False, width=3, length=10)
for loc in ax.spines:
ax.spines[loc].set_linewidth(3)
# Save figure to pdf in A3 format:
w, h = 420/25.4, 297/25.4
with PdfPages('multi.pdf') as pdf:
fig.set_size_inches(w, h)
fig.tight_layout()
pdf.savefig(figure=fig)
plt.close(fig)
# Display in Ipython a sclaled bitmap using a buffer to save the png :
buf = BytesIO()
fig.savefig(buf, format='png', dpi=90)
display(Image(data=buf.getvalue(), format='png', width=450, height=450*h/w,
unconfined=True))
which shows in the IPython console as:
Thank you #ImportanceOfBeingErnest for pointing out the solution.
I went with a solution that allows me to set plt.rc in the beginning to my taste and then revert to the set values after exporting the figures to a PDF.
First I set the values I use:
plt.rc('axes', grid=True)
plt.rc('figure', figsize=(12, 8))
plt.rc('legend', fancybox=True, framealpha=1)
With these I can plot what I need with just the default values. Then I create the PDF with:
with PdfPages('multi.pdf') as pdf:
for fig in figs:
fig.set_size_inches(420/25.4, 297/25.4)
pdf.savefig(figure=fig, bbox_inches='tight')
fig.set_size_inches(plt.rcParams.get('figure.figsize'))
With this I can get the fig.tight_layout() only on the exported figure and restore the figure size to the default value set earlier.

Categories