Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Marker Style/Color in Python Probplot

I am using Python 2.7 and have created a probability plot using the scipy.stats.probplot function. I want to change elements of the figure such as color/shape/size of the markers and the color/width of the best fit trend line. The documentation for probplot doesn't seem to have any option for changing these items.

Here is a my code (relevant portion):

#data is a list of y-values sampled from a lognormal distribution
d = getattr(stats, 'lognorm')
param = d.fit(data)
fig = plt.figure(figsize=[6, 6], dpi=100)
ax = fig.add_subplot(111)
fig = stats.probplot(data, dist='lognorm', sparams=param, plot=plt, fit=False)
#These next 3 lines just demonstrate that some plot features
#can be changed independent of the probplot function.
ax.set_title("")
ax.set_xlabel("Quantiles", fontsize=20, fontweight='bold')
ax.set_ylabel("Ordered Values", fontsize=20, fontweight='bold')
plt.show()

I tried grabbing the xy-data and creating my own scatter plot with ax.get_xydata() and fig.get_xydata(). However both of these failed as neither object has get_xydata() as a function. The figure that my code currently generates is:

the plot generated by probplot

like image 633
TravisJ Avatar asked Dec 19 '22 16:12

TravisJ


1 Answers

The key is the combination with matplotlib.

You can access the line object from the axes object using ax.get_lines(). Then, the properties can be changed accordingly.

You may have to figure out which index relates to the markers and which to the line(s). In the example below, the markers come first, hence:

ax.get_lines()[0].set_marker('p')

and the trend line is second:

ax.get_lines()[1].set_linewidth(12.0)

The example below is based on the probplot documentation:

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

nsample = 100
np.random.seed(7654321)

fig = plt.figure()
ax = fig.add_subplot(111)
x = stats.t.rvs(3, size=nsample)
res = stats.probplot(x, plot=plt)

ax.get_lines()[0].set_marker('p')
ax.get_lines()[0].set_markerfacecolor('r')
ax.get_lines()[0].set_markersize(12.0)

ax.get_lines()[1].set_linewidth(12.0)

plt.show()

The plot this creates looks ugly, but demonstrates the functionality:

updated markers


The text (r^2=0.9616) can be accessed through more general get_children from the axes:

ax.get_children()[2].set_fontsize(22.0)

Without detailed knowledge of the indexing for these items, you can try with:

print ax.get_children()

which gives you:

[<matplotlib.lines.Line2D object at 0x33f4350>, <matplotlib.lines.Line2D object at 0x33f4410>, 
<matplotlib.text.Text object at 0x33f4bd0>, <matplotlib.spines.Spine object at 0x2f2ead0>, 
<matplotlib.spines.Spine object at 0x2f2e8d0>, <matplotlib.spines.Spine object at 0x2f2e9d0>, 
<matplotlib.spines.Spine object at 0x2f2e7d0>, <matplotlib.axis.XAxis object at 0x2f2eb90>, 
<matplotlib.axis.YAxis object at 0x2f37690>, <matplotlib.text.Text object at 0x2f45290>, 
<matplotlib.text.Text object at 0x2f45310>, <matplotlib.text.Text object at 0x2f45390>, 
<matplotlib.patches.Rectangle object at 0x2f453d0>]
like image 104
Schorsch Avatar answered Dec 26 '22 11:12

Schorsch