using Plots
using LaTeXStrings
using Measures
using Random
Random.seed!(1);
Tutorial: Making Plots with Julia
Overview
This tutorial will give some examples of plotting and plotting features in Julia, as well as providing references to some relevant resources. The main plotting library is Plots.jl
, but there are some others that provide useful features.
Some Resources
Plots.jl
useful tipsPlots.jl
examples- Plot attributes
- Axis attributes
- Color names
Making a Basic Plot
Let’s walk through making a basic line or scatter plot in Julia, using Plots.jl
1.
1 There are some other plotting libraries in Julia, but Plots.jl
is a standard starting point. Feel free to experiment, though!
Since we’ll be generating random numbers, let’s import Random.jl
to let us set a seed to reproduce the same plot in addition to Plots.jl
.
First, to generate a basic line plot, use plot()
:
= rand(5)
y plot(y, label="original data", legend=:topleft)
We could also explicitly pass \(x\)-axis coordinates by passing an array with these coordinates first, as in plot(x, y, ...)
. If only one array is passed, Plots.jl
will interpret the values as \(y\) coordinates and use their indices for the \(x\) positions.
Notice the use of the label
and legend
keywords to label the plot element and position the legend. To not label a particular plotting element, use label=false
, and to turn off any legend (including a colorbar) from the plot, use legend=false
.
Now we can add some other lines and point markers. We will use plot!
and scatter!
to add another line and some points.
The exclamation mark says that plot!()
is a mutating function, which changes an existing variable instead of creating a new one. In this case, these functions change or add to an existing plot, instead of creating a new one.
Notice the arguments in plot!()
and scatter!()
, which let us set properties for the line and scatterplot markers.
= rand(5)
y2 = rand(5)
y3 plot!(y2, color=:red, linewidth=2, linestyle=:dot, label="new data")
scatter!(y3, markercolor=:black, markershape=:square, markersize=5, label="even more data")
Let’s now add axis labels. We can use LaTeX syntax to add mathematical markup elements to labels (such as superscripts, subscripts, Greek letters, and mathematical symbols) using the LaTeXStrings.jl
package. If we indicate that a string should be interpreted as a LaTeXString using the L"..."
syntax, it will render content inside $..$
using LaTeX, as seen below.
xlabel!("Regular String (days)")
ylabel!(L"LaTeX String $x_2$ (m$^3$)")
Removing Plot Elements
Sometimes we want to remove legends, axes, grid lines, and/or ticks.
plot!(legend=false, axis=false, grid=false, ticks=false)
Notice that this unintentionally modified the image dimensions to move the axis labels off the page. If we wanted to keep them, we could modify the dimensions with plot!(size=...)
.
plot!(size=(400, 400))
The lesson is that sometimes the Plots.jl
defaults don’t look ideal, and we need to adjust sizes and margins.
Aspect Ratio
If we want to have a square aspect ratio, use ratio = 1
.
= rand(5)
v plot(v, ratio=1, legend=false)
scatter!(v)
Plot Demos
This section includes some examples of how to make other types of plots.
Heatmaps
A heatmap is effectively a plotted matrix with colors chosen according to the values. Use clim
to specify a fixed range for the color limits.
= rand(10, 10)
A heatmap(A, clim=(0, 1), ratio=1, legend=false, axis=false, ticks=false)
= [ 0 1 0; 0 0 0; 1 0 0]
M = [RGBA(1,1,1,0), RGB(0,0,0)]
whiteblack heatmap(c=whiteblack, M, aspect_ratio = 1, ticks=.5:3.5, lims=(.5,3.5), gridalpha=1, legend=false, axis=false, ylabel="i", xlabel="j")
Custom Colors
using Colors
= [colorant"lightslateblue",colorant"limegreen",colorant"red"]
mycolors = [i for i=50:300, j=1:100]
A heatmap(A, c=mycolors, clim=(1,300))
Plotting Areas Under Curves
We can plot the area between a curve and the \(x\)-axis using areaplot()
.
= -3:.01:3
x areaplot(x, exp.(-x.^2/2)/√(2π),alpha=.25,legend=false)
We can also use this functionality for stacked area plots.
= [1 2 3; 7 8 9; 4 5 6; 0 .5 1.5]
M areaplot(1:3, M, seriescolor = [:red :green :blue ], fillalpha = [0.2 0.3 0.4])
The fillrange
option lets us color the area between two arbitrary lines/curves if we only want to treat one of those curves as a boundary. fillcolor
and fillalpha
let you change the color and transparency of the filled area.
= rand(10)
y plot(y, fillrange= y.*0 .+ .5, label= "above/below 1/2", fillcolor=:red, legend =:top)
= LinRange(0,2,100)
x = exp.(x)
y1 = exp.(1.3 .* x)
y2 plot(x, y1, fillrange = y2, fillalpha = 0.35, c = 1, label = "Confidence band", legend = :topleft)
We can also get more creative and color different parts of a curve differently. Here, we divide a normal distribution into 100 quantiles and alternate red and blue stripes. We’ll do this using the erfinv()
function from SpecialFunctions.jl
to calculate the quantiles using the inverse cumulative distribution function, but there are other approaches using Distributions.jl
.
using SpecialFunctions
# write a function for the normal distribution density
= x -> exp(-x^2/2)/√(2π)
f # get the edges of the quantiles
= .01
δ = √2 .* erfinv.(2 .* (δ/2 : δ : 1) .- 1)
x # make the plot and draw the density line in black
areaplot(x, f.(x), seriescolor=[ :red,:blue], legend=false)
plot!(x, f.(x),c=:black)
Plotting Shapes
We can also draw shapes more directly, such as rectangles and circles.
rectangle(w, h, x, y) = Shape(x .+ [0,w,w,0], y .+ [0,0,h,h])
circle(r,x,y) = (θ = LinRange(0,2π,500); (x.+r.*cos.(θ), y.+r.*sin.(θ)))
plot(circle(5,0,0), ratio=1, c=:red, fill=true)
plot!(rectangle(5*√2,5*√2,-2.5*√2,-2.5*√2),c=:white,fill=true,legend=false)
Plotting Distributions
The StatsPlots.jl
package is very useful for making various plots of probability distributions.
using Distributions, StatsPlots
plot(Normal(2, 5))
scatter(LogNormal(0.8, 1.5))
We can also use this functionality to plot distributions of data in tabular data structures like DataFrames
.
using DataFrames
= DataFrame(a = 1:10, b = 10 .+ rand(10), c = 10 .* rand(10))
dat @df dat density([:b :c], color=[:black :red])
Log-Scaled Axes
= .1:.1:10
xx plot(xx.^2, xaxis=:log, yaxis=:log)
plot(exp.(x), yaxis=:log)
Editing Plots Manually
= plot(1:4,[1, 4, 9, 16]) pl
pl.attr
RecipesPipeline.DefaultsDict with 30 entries:
:dpi => 96
:background_color_outside => :match
:plot_titlefontvalign => :vcenter
:warn_on_unsupported => true
:background_color => RGBA{Float64}(1.0,1.0,1.0,1.0)
:inset_subplots => nothing
:size => (672, 480)
:display_type => :auto
:overwrite_figure => true
:html_output_format => :svg
:plot_titlefontfamily => :match
:plot_titleindex => 0
:foreground_color => RGB{N0f8}(0.0,0.0,0.0)
:window_title => "Plots.jl"
:plot_titlefontrotation => 0.0
:extra_plot_kwargs => Dict{Any, Any}()
:pos => (0, 0)
:plot_titlefonthalign => :hcenter
:tex_output_standalone => false
:extra_kwargs => :series
:thickness_scaling => 1
:layout => 1
:plot_titlelocation => :center
:plot_titlefontsize => 16
:plot_title => ""
⋮ => ⋮
1] pl.series_list[
Plots.Series(RecipesPipeline.DefaultsDict(:plot_object => Plot{Plots.GRBackend() n=1}, :subplot => Subplot{1}, :label => "y1", :fillalpha => nothing, :linealpha => nothing, :linecolor => RGBA{Float64}(0.0,0.6056031611752245,0.9786801175696073,1.0), :x_extrema => (NaN, NaN), :series_index => 1, :markerstrokealpha => nothing, :markeralpha => nothing…))
:size]=(300,200) pl[
(300, 200)
pl