Getting an object in Python Matplotlib - object

To make a plot, I have written my code in the following fashion:
from pylab import *
x = [1,2,3]
y = [1,2,3]
matplotlib.pyplot.scatter(x,y,label='Blah')
matplotlib.pyplot.legend(title='Title')
matplotlib.pyplot.show()
I want to change the font size of the legend title. The way to go about this is to get the legend object and then change the title that way (e.g., How to set font size of Matplotlib axis Legend?)
Instead of rewriting all my code using ax.XXX, figure.XXX, etc, is there any way to get at the legend object from the code I have written, and then go from there?
That is to say, how do I define
Legend
from my original piece of code, such that
Title = Legend.get_title()
Title.set_fontsize(30)
would get at the title object and then allow me to play with .get_title()?
I think I'm on the verge of a eureka moment regarding object-orientated languages. I have a feeling a good answer will give me that eureka moment!
cheers,
Ged

First, in your code you should stick to using either from pylab import * and then use the imported methods directly, or import matplotlib.pyplot as plt and then plt.* instead of matplotlib.pyplot.*. Both these are "conventions" when it comes to working with matplotlib. The latter (i.e. pyplot) is generally preferred for scripting, as pylab is mainly used for interactive plotting.
To better understand the difference between pylab and pyplot see the matplotlib FAQ.
Over to the problem at hand; to "get" an object in Python, simply assign the object to a variable.
from pylab import *
x = [1,2,3]
y = [1,2,3]
scatter(x,y,label='Blah')
# Assign the Legend object to a variable leg
leg = legend(title='Title')
leg_title = leg.get_title()
leg_title.set_fontsize(30)
# Optionally you can use the one-liner
#legend(title='Title').get_title().set_fontsize(30)
show()
Visual comparison (rightmost subplot produced with the above code):

Related

Why will Seaborn function 'regplot' not run in Jupyter?

I am having trouble with code Seaborn regplot function in Jupyter notebooks using Watson-Studio.
Using Python 3.6, the code appears to get stuck whilst processing, and this happens until I stop the code.
When I run this using IDLE on my Mac, the code runs perfectly and the plot shows.
Seems to happen with plots lmplot and regplot, however boxplots etc do show as normal.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
df = pd.read_csv(csv.csv)
sns.regplot(x = 'independent', y = 'dependent', data = df)
The expected results should be a graph of the linear relationship between the two variables, however I am just getting a loading bar.
When I stop running the kernel, the graph exists as a scatterplot with no line of best fit. Of course this has the error in notebook as 'Keyboard Interrupted'.
Could this possibly be a bug? Thanks for your help.
Set ci parameter to none and it will solve your problem.
sns.regplot(x = 'independent', y = 'dependent', data = df, ci = None)

Main figure legend outside of subplots

I have a number of subplots within a single figure. Each figure plots multiple lines that represent the same thing (represented by color) but in different situations (different subplots). I would like to create a legend at the base of the figure showing what the color of the line means. However, I running into a problem with getting the legend to not overlap the subplots and if I can adjust the axes, getting the legend to save.
I have tried a few different solutions with some help here but have been unable to adapt to subplots. Below is an example code that I am working with.
import numpy as np
import matplotlib.pyplot as plt
m1=1
m2=10
x=np.linspace(0,100,num=101,endpoint=True)
y1m1=m1*x**2
y2m1=m1*x**0.5
y1m2=m2*x**2
y2m2=m2*x**0.5
fig=plt.figure(figsize=(4,4))
ax1=fig.add_subplot(211)
ax1.plot(x,y1m1,'b',label=r'$x^2$')
ax1.plot(x,y2m1,'r',label=r'$\sqrt{x}$')
ax2=fig.add_subplot(212)
ax2.plot(x,y1m2,'b')
ax2.plot(x,y2m2,'r')
fig.legend(loc='lower center',ncol=2)
fig.tight_layout()
fig.savefig('examplefig.png',dpi=300)
plt.show()
My goal is to save the output to a png for a good figure.
This is one way of doing it using the suggestion provided here. The idea is to add the legend at position with respect to a given axis object. In your case, since you want to add the legend at the base, it is preferred you specify the position relative to ax2. Using ncol=2 is a matter of personal choice.
fig=plt.figure(figsize=(4,4))
ax1=fig.add_subplot(211)
l1, = ax1.plot(x,y1m1,'b')
l2, = ax1.plot(x,y2m1,'r')
ax2=fig.add_subplot(212)
ax2.plot(x,y1m2, 'b')
ax2.plot(x,y2m2, 'r')
ax2.legend(handles = [l1,l2] , labels=[r'$x^2$', r'$\sqrt{x}$'],
bbox_to_anchor=(0.7, -0.2), ncol=2)
fig.tight_layout()

Python matplotlib pyplot module always draws on existing figure window when figure title is the same

I am a new python user but an experienced Matlab user. I am recently debugging a python script, and when I manually re-run the script multiple times, I found a somewhat annoying issue of matplotlib: it always draws on existing figure window, overlapping on existing plot, if the figure title is the same.
The script I am debugging looks like this:
import matplotlib.pyplot as plt
# Some calculations here
plt.figure('Results') # The script will only create one figure
# plot the data
# End of the script
A simple search on Google shows that if I don't explicitly specify figure title, or give each figure a different handle, matplotlib can create separate figure windows, and true, it works.
However, is there a way to create multiple figure windows with the same title, without giving them different handles (which in my case, I had to do it manually) in python? In Matlab it will always create separate figure window no matter what figure title you give it.
The argument to figure is an identifier. If it is left empty anew figure will be created, else the figure with that identifier will be activiated. The documentation makes this rather clear:
matplotlib.pyplot.figure(num=None, ...)
num : integer or string, optional, default: none
If not provided, a new figure will be created, and the figure number will be incremented. The figure objects holds this number in a number attribute. If num is provided, and a figure with this id already exists, make it active, and returns a reference to it. If this figure does not exists, create it and returns it. If num is a string, the window title will be set to this figure’s num.
Hence in order to create a new figure, leave this argument out or specify differing ones. In order to set the window's title, use set_window_title.
The following will create two figures with the same window title.
import matplotlib.pyplot as plt
plt.figure()
plt.gcf().canvas.set_window_title('Results')
plt.plot([1,2,3])
plt.figure()
plt.gcf().canvas.set_window_title('Results')
plt.plot([2,3,1], color="crimson")
plt.show()
From the first paragraph of your question, ...
when I manually re-run the script multiple times, I found a somewhat
annoying issue of matplotlib: it always draws on existing figure
window
I think that simply clearing the figure (at the start of the script) would make your repeated runs of the script useable.
import matplotlib.pyplot as plt
# compute results here - random here as a standin.
import numpy as np
x = np.random.randn(500)
plt.figure("Results"); plt.clf()
# plot results here...
plt.hist(x, bins=20, histtype='step')
Now, each time you run the script, you will draw the results on a blank canvas and not over the top of the old results.
The figures below illustrate the difference, after 3 runs of the script (in ipython): left - without the plt.clf(), and right - with plt.clf() at the start.

Quantile-Quantile Plot using Seaborn and SciPy

Can anyone give me a way to do a qq plot in Seaborn as a test for normality of data? Or failing that, at least in matplotlib.
Thanks in advance
After reading the wikipedia article, I understand that the Q-Q plot is a plot of the quantiles of two distributions against each other.
numpy.percentile allows to obtain the percentile of a distribution. Hence you can call numpy.percentile on each of the distributions and plot the results against each other.
import numpy as np
import matplotlib.pyplot as plt
a = np.random.normal(5,5,250)
b = np.random.rayleigh(5,250)
percs = np.linspace(0,100,21)
qn_a = np.percentile(a, percs)
qn_b = np.percentile(b, percs)
plt.plot(qn_a,qn_b, ls="", marker="o")
x = np.linspace(np.min((qn_a.min(),qn_b.min())), np.max((qn_a.max(),qn_b.max())))
plt.plot(x,x, color="k", ls="--")
plt.show()
Try statsmodels.api.qqplot().
Using same data as above, this example shows a normal distribution plotted against a normal distribution, resulting in fairly straight line:
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
a = np.random.normal(5, 5, 250)
sm.qqplot(a)
plt.show()
This example shows a Rayleigh distribution plotted against normal distribution, resulting in a slightly concave curve:
a = np.random.rayleigh(5, 250)
sm.qqplot(a)
plt.show()
I'm not sure if this still recent, but I notice that neither of the answers really addresses the question, which asks how to do qq-plots with scipy and seaborn, but doesn't mention statsmodels. In fact, qq-plots are available in scipy under the name probplot:
from scipy import stats
import seaborn as sns
stats.probplot(x, plot=sns.mpl.pyplot)
The plot argument to probplot can be anything that has a plot method and a text method. Probplot is also quite flexible about the kinds of theoretical distributions it supports.
At seaborn-qqplot addon documentation an example is shown. Also see.
Working with pycharm and windows 10 I had difficulties installing the library with:
pip install seaborn-qqplot
in my virtual environment. The import line:
from seaborn_qqplot import pplot
was not recognized.
With (commands for PyCharm): file -> settings -> Project -> Python Interpreter -> + (Install) I could import pplot from seaborn_qqplot and could create a Quantile - Quantile plot.

Python3x + MatPlotLib - Updating a chart?

I am new to both the python and matplotlib languages and working on something for my husband.
I hope you guys can help me out.
I would like to pull in a file using Open, read it, and update a graph with it's values.
Sounds easy enough right? Not so much in practice.
Here is what I have so far to open and chart the file. This works fine as it is to chart the file 1 time.
import matplotlib.pyplot as plt
fileopen = open('.../plotresults.txt', 'r').read()
fileopen = eval(fileopen) ##because the file contains a dict and security is not an issue.
print(fileopen) ## So I can see it working
for key,value in fileopen.items():
plot1 = value
plt.plot(plot1, label=str(key))
plt.legend()
plt.show()
Now I would like to animate the chart or update it so that I can see changes to the data. I have tried to use matplotlib's animation feature but it is advanced beyond my current knowledge.
Is there a simple way to update this chart, say every 5 minutes?
Note:
I tried using Schedule but it breaks the program (maybe a conflict between schedule and having matplotlib figures open??).
Any help would be deeply appreciated.
Unfortunately you will just waste time trying to get a clean solution without either using matplotlib's animation feature or using the matplotlib OO interface.
As a dirty hack you can use the following:
from threading import Timer
from matplotlib import pyplot as plt
import numpy
# Your data generating code here
def get_data():
data = numpy.random.random(100)
label = str(data[0]) # dummy label
return data, label
def update():
print('update')
plt.clf()
data, label = get_data()
plt.plot(data, label=label)
plt.legend()
plt.draw()
t = Timer(0.5, update) # restart update in 0.5 seconds
t.start()
update()
plt.show()
It spins off however a second thread by Timer. So to kill the script, you have to hit Ctrl-C twice on the console.
I myself would be interested if there is a cleaner way to do this in this simple manner in the confines of the pyplot machinery.
Edits in italic.

Resources