# Plotting in Julia¶

## Overview¶

Since it’s inception, plotting in Julia has been a mix of happiness and frustration

Some initially promising libraries have stagnated, or failed to keep up with user needs

New packages have appeared to compete with them, but not all are fully featured

The good news is that the Julia community now has several very good options for plotting

In this lecture we’ll try to save you some of our pain by focusing on what we believe are currently the best libraries

First we look at two high quality plotting packages that have proved useful to us in a range of applications

After that we turn to a relative newcomer called Plots.jl

The latter package takes a different – and intriguing – approach that combines and exploits the strengths of several existing plotting libraries

Below we assume that

### How to Read this Lecture¶

If you want to get started quickly with relatively simple plots, you can skip straight to the section on Plots.jl

If you want a deeper understanding and more flexibility, continue from the next section and read on

Credits: Thanks to @albep, @vgregory757 and @spencerlyon2 for help with the code examples below

## PyPlot¶

Let’s look at PyPlot first

PyPlot is a Julia front end to the excellent Python plotting library Matplotlib

### Installing PyPlot¶

One disadvantage of PyPlot is that it not only requires Python but also much of the scientific Python stack

Fortunately, installation of the latter has been greatly simplified by the excellent Anaconda Python distribution

Moreover, the tools that come with Anaconda (such as Jupyter) are too good to miss out on

Next, start up Julia and type Pkg.add("PyPlot")

### Usage¶

There are two different interfaces to Matplotlib and hence to PyPlot

Let’s look at them in turn

### The Procedural API¶

Matplotlib has a straightforward plotting API that essentially replicates the plotting routines in MATLAB

These plotting routines can be expressed in Julia with almost identical syntax

Here’s an example

using PyPlot
x = linspace(0, 10, 200)
y = sin(x)
plot(x, y, "b-", linewidth=2)


The resulting figure looks as follows

### The Object Oriented API¶

Matplotlib also has a more powerful and expressive object oriented API

Because Julia isn’t object oriented in the same sense as Python, the syntax required to access this interface via PyPlot is a little awkward

Here’s an example:

x = linspace(0, 10, 200)
y = sin(x)
fig, ax = subplots()
ax[:plot](x, y, "b-", linewidth=2)


The resulting figure is the same

Here we get no particular benefit from switching APIs, while introducing a less attractive syntax

However, as plots get more complex, the more explicit syntax will give us greater control

Here’s a similar plot with a bit more customization

x = linspace(0, 10, 200)
y = sin(x)
fig, ax = subplots()
ax[:plot](x, y, "r-", linewidth=2, label="sine function", alpha=0.6)
ax[:legend](loc="upper center")


The resulting figure has a legend at the top center

We can render the legend in LaTeX by changing the ax[:plot] line to

x = linspace(0, 10, 200)
y = sin(x)
fig, ax = subplots()
ax[:plot](x, y, "r-", linewidth=2, label=L"$y = \sin(x)$", alpha=0.6)
ax[:legend](loc="upper center")


Note the L in front of the string to indicate LaTeX mark up

The result looks as follows

### Multiple Plots on One Axis¶

Here’s another example, which helps illustrate how to put multiple plots on one figure

We use Distributions.jl to get the values of the densities given a randomly generated mean and standard deviation

using Distributions

u = Uniform()

fig, ax = subplots()
x = linspace(-4, 4, 150)
for i in 1:3
# == Compute normal pdf from randomly generated mean and std == #
m, s = rand(u) * 2 - 1, rand(u) + 1
d = Normal(m, s)
y = pdf(d, x)
# == Plot current pdf == #
ax[:plot](x, y, linewidth=2, alpha=0.6, label="draw $i") end ax[:legend]()  It generates the following plot #### Subplots¶ A figure containing n rows and m columns of subplots can be created by the call fig, axes = subplots(num_rows, num_cols)  Here’s an example that generates 6 normal distributions, takes 100 draws from each, and plots each of the resulting histograms u = Uniform() num_rows, num_cols = 2, 3 fig, axes = subplots(num_rows, num_cols, figsize=(16,6)) subplot_num = 0 for i in 1:num_rows for j in 1:num_cols ax = axes[i, j] subplot_num += 1 # == Generate a normal sample with random mean and std == # m, s = rand(u) * 2 - 1, rand(u) + 1 d = Normal(m, s) x = rand(d, 100) # == Histogram the sample == # ax[:hist](x, alpha=0.6, bins=20) ax[:set_title]("histogram$subplot_num")
ax[:set_xticks]([-4, 0, 4])
ax[:set_yticks]([])
end
end


The resulting figure is as follows

#### 3D Plots¶

Here’s an example of how to create a 3D plot

using QuantEcon: meshgrid

n = 50
x = linspace(-3, 3, n)
y = x

z = Array{Float64}(n, n)
f(x, y) = cos(x^2 + y^2) / (1 + x^2 + y^2)
for i in 1:n
for j in 1:n
z[j, i] = f(x[i], y[j])
end
end

fig = figure(figsize=(8,6))
ax = fig[:gca](projection="3d")
ax[:set_zlim](-0.5, 1.0)
xgrid, ygrid = meshgrid(x, y)
ax[:plot_surface](xgrid, ygrid, z, rstride=2, cstride=2,
cmap=ColorMap("jet"), alpha=0.7, linewidth=0.25)


It creates this figure

## PlotlyJS¶

Now let’s turn to another plotting package — a promising new library called PlotlyJS, authored by Spencer Lyon

PlotlyJS is a Julia interface to the plotly.js visualization library

It can be installed by typing Pkg.add("PlotlyJS") from within Julia

It has several advantages, one of which is beautiful interactive plots

While we won’t treat the interface in great detail, we will frequently use PlotlyJS as a backend for Plots.jl

(More on this below)

### Examples¶

Let’s look at some simple examples

Here’s a version of the sine function plot you saw above

import PlotlyJS
x = linspace(0, 10, 200)
y = sin(x)
# specify which module scatter belongs to since both has scatter
PlotlyJS.plot(PlotlyJS.scatter(x=x, y=y, marker_color="blue", line_width=2))


Here’s the resulting figure:

Here’s a replication of the figure with multiple Gaussian densities

traces = PlotlyJS.GenericTrace[]
u = Uniform()

x = linspace(-4, 4, 150)
for i in 1:3
# == Compute normal pdf from randomly generated mean and std == #
m, s = rand(u) * 2 - 1, rand(u) + 1
d = Normal(m, s)
y = pdf(d, x)
trace = PlotlyJS.scatter(x=x, y=y, name="draw $i") push!(traces, trace) end PlotlyJS.plot(traces, PlotlyJS.Layout())  The output looks like this (modulo randomness): ## Plots.jl¶ Plots.jl is another relative newcomer to the Julia plotting scene, authored by Tom Breloff The approach of Plots.jl is to 1. provide a “frontend” plotting language 2. render the plots by using one of several existing plotting libraries as “backends” In other words, Plots.jl plotting commands are translated internally to commands understood by a selected plotting library Underlying libraries, or backends, can be swapped very easily This is neat because each backend has a different look, as well as different capabilities Also, Julia being Julia, it’s quite possible that a given backend won’t install or function on your machine at a given point in time With Plots.jl, you can just change to another one ### Simple Examples¶ We produced some simple plots using Plots.jl back in our introductory Julia lecture Here’s another simple one: import Plots x = linspace(0, 10, 200) y = sin.(x) Plots.plot(x, y, color=:blue, linewidth=2, label="sine")  On our machine this produces the following figure No backend was specified in the preceding code, and in this case it defaulted to PlotlyJS.jl We can make this explicit by adding one extra line Plots.plotlyjs() # specify backend x = linspace(0, 10, 200) y = sin.(x) Plots.plot(x, y, color=:blue, linewidth=2, label="sine")  To switch your backend to PyPlot, change plotlyjs() to pyplot() Your figure should now look more like the plots produced by PyPlot Here’s a slightly more complex plot using Plots.jl with PyPlot backend using LaTeXStrings # Install this package Plots.pyplot() x = linspace(0, 10, 100) Plots.plot(x, sin, color=:red, lw=2, yticks=-1:1:1, title="sine function", label=L"$y = \sin(x)$", # L for LaTeX string alpha=0.6)  Here’s the figure it produces: Use legend=:none if you want no legend on the plot Notice that in the preceding code example, the second argument to plot() is a function rather than an array of data points This is valid syntax, as is Plots.plot(sin, 0, 10) # Plot the sine function from 0 to 10  Plots.jl accommodates these useful variations in syntax by exploiting multiple dispatch ### Multiple Plots on One Axis¶ Next, let’s replicate the figure with multiple Gaussian densities Plots.plotlyjs() x = linspace(-4, 4, 150) y_vals = Array{Vector}(3) labels = Array{String}(1, 3) for i = 1:3 m, s = 2*(rand() - 0.5), rand() + 1 d = Normal(m, s) y_vals[i] = pdf(d, x) labels[i] = string("mu = ", round(m, 2)) end Plots.plot(x, y_vals, linewidth=2, alpha=0.6, label=labels)  Also, when you have multiple y-series, Plots.jl can accept one x-values vector and apply it to each y-series Here’s the resulting figure: ### Subplots¶ Let’s replicate the subplots figure shown above Plots.pyplot() draws = Array{Vector}(6) titles = Array{String}(1, 6) for i = 1:6 m, s = 2*(rand() - 0.5), rand() + 1 d = Normal(m, s) draws[i] = rand(d, 100) t = string(L"$\mu = $", round(m, 2), L",$\sigma = $", round(s, 2)) titles[i] = t end Plots.histogram(draws, layout=6, title=titles, legend=:none, titlefont=Plots.font(9), bins=20)  Notice that the font and bins settings get applied to each subplot Here’s the resulting figure: When you want to pass individual arguments to subplots, you can use a row vector of arguments • For example, in the preceding code, titles' is a 1 x 6 row vector Here’s another example of this, with a row vector of different colors for the histograms using Distributions using Plots using LaTeXStrings pyplot() draws = Array{Vector}(6) titles = Array{String}(1, 6) for i = 1:6 m, s = 2*(rand() - 0.5), rand() + 1 d = Normal(m, s) draws[i] = rand(d, 100) t = string(L"$\mu = $", round(m, 2), L",$\sigma = $", round(s, 2)) titles[i] = t end histogram(draws, layout=6, title=titles, legend=:none, titlefont=font(9), color=[:red :blue :yellow :green :black :purple], bins=20)  The result is a bit garish but hopefully the message is clear ### 3D Plots¶ Here’s a sample 3D plot Plots.plotlyjs() n = 50 x = linspace(-3, 3, n) y = x z = Array{Float64}(n, n) ff(x, y) = cos(x^2 + y^2) / (1 + x^2 + y^2) for i in 1:n for j in 1:n z[j, i] = ff(x[i], y[j]) end end Plots.surface(x, y, z)  The resulting figure looks like this: ### Further Reading¶ Hopefully this tutorial has given you some ideas on how to get started with Plots.jl We’ll see more examples of this package in action through the lectures Additional information can be found in the official documentation ## Exercises¶ ### Exercise 1¶ The identity function $$f(x) = x$$ is approximated on the nonnegative numbers $$[0, \infty)$$ with increasing degrees of precision by the sequence of functions $d_n(x) = \sum_{k=1}^{n 2^n} \frac{k-1}{2^n} \mathbb{1} \left\{ \frac{k-1}{2^n} \leq x < \frac{k}{2^n} \right\} + n \mathbb{1}\{ x \geq n \}$ for $$n = 1, 2, \ldots$$ Here $$\mathbb{1}\{ P \} = 1$$ if the statement $$P$$ is true and 0 otherwise (This result is often used in measure theory) Plot the functions $$d_n, \; n=1, \ldots, 6$$ on the interval $$[0, 10]$$ and compare them to the identity function Do they get closer to the identity as $$n$$ gets larger? ## Solutions¶ Our aim is to plot the sequence of functions described in the exercise. We will use the library Plots.jl. Plots.pyplot()  Plots.PyPlotBackend()  Here’s the function $$d_n$$ for any given $$n$$: function d(x, n) current_val = 0 for k in 1:(n * 2^n) if (k - 1) / 2^n <= x < k / 2^n current_val += (k - 1) / 2^n end end if x >= n current_val += n end return current_val end  d (generic function with 1 method)  And here’s the plot: x_grid = linspace(0, 10, 100) n_vals = [1, 2, 3, 4, 5] function_vals = [] labels = [] for n in n_vals push!(function_vals, [d(x, n) for x in x_grid]) push!(labels, "$n")
end

push!(function_vals, x_grid)
push!(labels, "identity function")

Plots.plot(x_grid,
function_vals,
label=reshape(labels, 1, length(n_vals) + 1),
ylim=(0, 10))

• Share page