Using Matplotlib
Matplotlib is worth using, but it’s very finicky, and the defaults are aimed at a class of user that doesn’t include me.
MATLAB style with pyplot
I started with the simple declarative style via matplotlib.pyplot
, but that quickly
gets limited. It looks like this:
import matplotlib
import numpy
matplotlib.use('Agg')
matplotlib.rcParams['lines.linewidth'] = 2
matplotlib.rcParams['lines.color'] = 'r'
matplotlib.rcParams['figure.figsize'] = (6,3)
import matplotlib.pyplot as plt
plt.title('Orgs by create date')
plt.xlabel('date')
plt.ylabel('count')
d = []
for r in org_list:
d.append(year_fraction(r['created_at']))
ax = plt.gca()
ax.ticklabel_format(useOffset=False)
n = numpy.arange(len(d))
plt.plot(d, n)
plt.savefig(plot_name, bbox_inches='tight')
For example, without the useOffset=False
bit, my X axis was numbered 0-5 with
an offset written above it, rathern than 2012-2017 as I intended. I suppose this is
useful for scientific plots. I spent 30 minutes combing through documentation trying
to figure this out before resorting to StackOverflow. Similarly, I had to use other
StackOverflow entries to tell me how to write the graph as a file and not to show
it in an interactive window. Again, I’m not the target audience.
object-oriented Matplotlib
This is the right way for me, I think. Note that the code example above had to dip into the object layer anyway, in order to configure the X axis.
xkcd style
One cool thing is that someone made an xkcd style for Matplotlib. Just wrap your code in this:
with matplotlib.pyplot.xkcd():
# your code here
and your graphics will have that hand-drawn xkcd style applied to them.
Here is the example from the Matplotlib docs
import matplotlib.pyplot as plt
import numpy as np
with plt.xkcd():
# Based on "Stove Ownership" from XKCD by Randall Monroe
# http://xkcd.com/418/
fig = plt.figure()
ax = fig.add_axes((0.1, 0.2, 0.8, 0.7))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
plt.xticks([])
plt.yticks([])
ax.set_ylim([-30, 10])
data = np.ones(100)
data[70:] -= np.arange(30)
plt.annotate(
'THE DAY I REALIZED\nI COULD COOK BACON\nWHENEVER I WANTED',
xy=(70, 1), arrowprops=dict(arrowstyle='->'), xytext=(15, -10))
plt.plot(data)
plt.xlabel('time')
plt.ylabel('my overall health')
fig.text(
0.5, 0.05,
'"Stove Ownership" from xkcd by Randall Monroe',
ha='center')
# Based on "The Data So Far" from XKCD by Randall Monroe
# http://xkcd.com/373/
fig = plt.figure()
ax = fig.add_axes((0.1, 0.2, 0.8, 0.7))
ax.bar([-0.125, 1.0 - 0.125], [0, 100], 0.25)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.set_xticks([0, 1])
ax.set_xlim([-0.5, 1.5])
ax.set_ylim([0, 110])
ax.set_xticklabels(['CONFIRMED BY\nEXPERIMENT', 'REFUTED BY\nEXPERIMENT'])
plt.yticks([])
plt.title("CLAIMS OF SUPERNATURAL POWERS")
fig.text(
0.5, 0.05,
'"The Data So Far" from xkcd by Randall Monroe',
ha='center')
plt.show()
ggplot
I wish Matplotlib learned more lessons from Leland Wilkinson’s Grammar of Graphics.
Seaborn is an interesting start.
Reference
Matplotlib yaxis range display using absolute values rather than offset values?
matplotlib: format axis offset-values to whole numbers or specific number
A Dramatic Tour through Python’s Data Visualization Landscape (including ggplot and Altair)