Today I wanted to draw some graphs. I started out using Wolfram Alpha’s excellent plot() functionality but wanted something that I would be able to use offline too. Mathematica & Matlab are beyond my requirements and Excel/Google Sheets/the Apple one don’t give me enough flexibility.

I chose to use Python and in particular the matplotlib library’s pyplot module. I don’t really use Python so before I talk about how I got basic graphs working, let’s look at getting Python set up on OSX:

Python Setup

As Python 3 is the latest official version, we should try to use that if possible. The quickest way to get that is by installing it with brew:

$ brew install python3

To verify this has worked, start a new terminal session and run python3. You should now see something like this:

$ python3
Python 3.4.3 (default, Aug 11 2015, 08:57:25)
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

The default brew Python 3 installation includes the pip package manager. As with the python executable, pip is suffixed with ‘3’ to distinguish it from a pip installation for python 2. You can verify its presence by querying its version:

$ pip3 --version
pip 7.1.2 from /usr/local/lib/python3.4/site-packages (python 3.4)

Basic Graphing

We need the matplotlib library which we can install with pip:

$ pip3 install matplotlib

Now we’re ready to make some graphs in Python! This is the script I used to draw my graphs:

import matplotlib.pyplot as plt
from cmath import log
from math import pow

test_data = list(filter(
                lambda x: x != 0,
                [n / 100.0 for n in range(-1000, 1001)]))

equations = [
     (lambda x: 1),
     (lambda x: x),
     (lambda x: pow(x, 2)),
     (lambda x: pow(x, 3)),
     (lambda x: pow(x, 4)),
     (lambda x: log(x).real)
]

plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.xlim((-10, 10))
plt.ylim((-10, 10))

for equation in equations:
    plt.plot(test_data, list(map(equation, test_data)))

plt.savefig("out.png")

In this example, I want to run a series of equations of the form y = f(x) so I need to create some x values for the data points and then have some way of representing the equations.

I want my x values to go from -10 to 10 so I first tried range(-10, 11), but this only gives me a granularity of 20 coordinates. Instead I used a for comprehension - creating a range from -1000 up to and including 1000, and then dividing each coordinate by 100 which results in 2000 floating point x values between -10 and 10.

I create several lambdas representing equations (y = 1, y = x, y = x^2, y = x^3, y = x^4, y = log(x)) and stash these in an array. I want to use the complex logarithm for which y values exist for negative x, but not for 0 so at this point I exclude 0 from my test_data using the filter function and a lambda predicate.

Setting up the graph layout is simple - I add lines through the origin with the axhline and axvline functions and set the limits of the graph to positive and negative 10 for both axes with xlim and ylim.

To plot the graphs, I iterate over the array of equation lambdas and plot the test data against the test data mapped to the current lambda. Finally I output the graph to a file called “out.png” with the savefig function:

Demo graph generated with matplotlib's pyplot module

Bonus 1: Atom Setup

I like the Atom editor, and it comes with support for Python out of the box. However, there are two extra packages that make Python editing nicer for a beginner like me. These are autocomplete-python which provides autocompletion functionality as you might expect, and linter-pep8 which applies the pep8 standards tool to your code and tells you when you’re not formatting it in the correct way.

First you need pep8:

$ pip3 install pep8

And then you need to install the packages which you can either do through the Atom UI, or with the Atom Package Manager as follows:

$ apm install autocomplete-python linter-pep8

Bonus 2: Pythonista

There exists a splendid iOS app called Pythonista which contains an implementation of Python and a well featured editor. Pythonista also comes packaged with matplotlib, so out of curiosity I copied my graph script in, changing the plt.savefig("out.png") line to plt.show() to display the graph rather than write it to a file, and it worked straight away:blo

Basic graphing script in Pythonista Graph displayed in Pythonista