using Plots
x = range(0, 8π; length = 100)
sx = @. sin(x) # the @. macro broadcasts (vectorizes) every operation
cx = @. cos(2x^(1/2))
plot(x, [sx cx])16 Plots and Data Visualization in Julia: Plots.jl
Julia has numerous graphics packages. Two frequently used ones are Makie.jl and Plots.jl. Before presenting Plots.jl in detail, we list some others.
16.1 Brief Overview: Some Graphics Packages
| Package/Documentation | Tutorial | Examples | Remarks |
|---|---|---|---|
| Plots.jl | Tutorial | Gallery | designed as a unified interface to various backends (graphics libraries) |
| Makie.jl | Basic tutorial | Beautiful Makie | “data visualization ecosystem for Julia”, backends: Cairo (vector graphics), OpenGL, WebGL |
| PlotlyJS.jl | Getting started | Examples | Interface to the Plotly JavaScript graphics library |
| Gadfly.jl | Tutorial | Gallery | “a plotting and data visualization system written in Julia, influenced by R’s ggplot2” |
| Bokeh.jl | Gallery | Julia frontend for Bokeh | |
| VegaLite.jl | Tutorial | Examples | Julia frontend for Vega-Lite |
| Luxor.jl | Tutorial | Examples | General vector graphics/illustrations |
| Javis.jl | Tutorials | Examples | Animated vector graphics |
| TidierPlots.jl | Reference | “is a 100% Julia implementation of the R package ggplot2 powered by Makie.jl” | |
| PythonPlot.jl | Examples (in Python) | Interface to Matplotlib (Python), 1:1 transfer of the Python API, therefore see Matplotlib documentation |
16.2 Plots.jl
16.2.1 Simple Plots
The plot() function expects, in the simplest case:
- as the first argument a vector of \(x\)-values of length \(n\) and
- as the second argument a vector of the same length with the corresponding \(y\)-values.
- The second argument can also be an \(n\times m\) matrix. Each column is treated as a separate graph (called a
seriesin the documentation), plotting \(m\) curves:
- Functions like
plot(),scatter(),contour(),heatmap(),histogram(),bar(), etc. from Plots.jl all start a new plot. - The versions
plot!(),scatter!(),contour!(),heatmap!(),histogram!(),bar!(), etc. extend an existing plot:
plot(x, sx) # plot only sin(x)
plot!(x, cx) # add second graph
plot!(x, sqrt.(x)) # add a third onePlots are objects that can be assigned. Then they can be used later, copied, and in particular extended with the ! functions:
plot1 = plot(x, [sx cx])
plot1a = deepcopy(plot1) # plot objects are quite deep structures
scatter!(plot1, x, sx) # add scatter plot, i.e. unconnected data pointsThe copied version plot1a remains unchanged by the scatter! call and can be used independently:
plot!(plot1a, x, 2 .* sx)Plot objects can be saved as graphics files (PDF, SVG, PNG, etc.):
savefig(plot1, "plot.png")"/home/hellmund/Julia/Book26/JuliaBook/chapters/plot.png"
;ls -l plot.png-rw-r--r-- 1 hellmund hellmund 55780 Mar 11 15:51 plot.png
Plot objects can also be inserted as subplots into other plots, see section Section 16.2.7.
16.2.2 Function Plots
plot() can also be passed a function and a vector of \(x\)-values:
# https://mzrg.com/math/graphs.shtml
f(x) = abs(sin(x^x)/2^((x^x-π/2)/π))
plot(f, 0:0.01:3)The parametric form \(x = x(t),\ y = y(t)\) is plotted by passing two functions and a vector of \(t\)-values to plot().
# https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental)
xt(t) = sin(t) * (exp(cos(t))-2cos(4t)-sin(t/12)^5)
yt(t) = cos(t) * (exp(cos(t))-2cos(4t)-sin(t/12)^5)
plot(xt, yt, 0:0.01:12π)16.2.3 Plot Themes
“PlotThemes is a package to spice up plots made with Plots.jl.”
See the illustrated list of themes
using PlotThemes
# list of themes
keys(PlotThemes._themes)KeySet for a Dict{Symbol, PlotTheme} with 21 entries. Keys:
:juno
:default
:dao
:ggplot2
:gruvbox_dark
:dark
:gruvbox_light
:solarized
:wong
:dracula
:solarized_light
:mute
:boxed
:rose_pine
:wong2
:sand
:lime
:rose_pine_dawn
:bright
⋮
Plots.showtheme(:juno)using PlotThemes
theme(:juno) # set a theme for all further plots
plot(x, [sx cx 1 ./ (1 .+ x)])16.2.4 Plot Attributes
The Plots.jl functions have numerous options. Attributes are divided into 4 groups:
plotattr(:Plot) # attributes for the overall plotDefined Plot attributes are: background_color, background_color_outside, display_type, dpi, extra_kwargs, extra_plot_kwargs, fontfamily, foreground_color, html_output_format, inset_subplots, layout, link, overwrite_figure, plot_title, plot_titlefontcolor, plot_titlefontfamily, plot_titlefonthalign, plot_titlefontrotation, plot_titlefontsize, plot_titlefontvalign, plot_titleindex, plot_titlelocation, plot_titlevspan, pos, show, size, tex_output_standalone, thickness_scaling, warn_on_unsupported, window_title
plotattr(:Subplot) # attributes for a subplotDefined Subplot attributes are: annotationcolor, annotationfontfamily, annotationfontsize, annotationhalign, annotationrotation, annotations, annotationvalign, aspect_ratio, background_color_inside, background_color_subplot, bottom_margin, camera, clims, color_palette, colorbar, colorbar_continuous_values, colorbar_discrete_values, colorbar_fontfamily, colorbar_formatter, colorbar_scale, colorbar_tickfontcolor, colorbar_tickfontfamily, colorbar_tickfonthalign, colorbar_tickfontrotation, colorbar_tickfontsize, colorbar_tickfontvalign, colorbar_ticks, colorbar_title, colorbar_title_location, colorbar_titlefontcolor, colorbar_titlefontfamily, colorbar_titlefonthalign, colorbar_titlefontrotation, colorbar_titlefontsize, colorbar_titlefontvalign, extra_kwargs, fontfamily_subplot, foreground_color_subplot, foreground_color_title, framestyle, left_margin, legend_background_color, legend_column, legend_font, legend_font_color, legend_font_family, legend_font_halign, legend_font_pointsize, legend_font_rotation, legend_font_valign, legend_foreground_color, legend_position, legend_title, legend_title_font, legend_title_font_color, legend_title_font_family, legend_title_font_halign, legend_title_font_pointsize, legend_title_font_rotation, legend_title_font_valign, margin, projection, projection_type, right_margin, subplot_index, title, titlefontcolor, titlefontfamily, titlefonthalign, titlefontrotation, titlefontsize, titlefontvalign, titlelocation, top_margin
plotattr(:Axis) # attributes for an axisDefined Axis attributes are: discrete_values, draw_arrow, flip, foreground_color_axis, foreground_color_border, foreground_color_grid, foreground_color_guide, foreground_color_minor_grid, foreground_color_text, formatter, grid, gridalpha, gridlinewidth, gridstyle, guide, guide_position, guidefontcolor, guidefontfamily, guidefonthalign, guidefontrotation, guidefontsize, guidefontvalign, lims, link, minorgrid, minorgridalpha, minorgridlinewidth, minorgridstyle, minorticks, mirror, rotation, scale, showaxis, tick_direction, tickfontcolor, tickfontfamily, tickfonthalign, tickfontrotation, tickfontsize, tickfontvalign, ticks, unit, unitformat, widen
plotattr(:Series) # attributes for a series, e.g., a line in the plotDefined Series attributes are: arrow, bar_edges, bar_position, bar_width, bins, colorbar_entry, connections, contour_labels, contours, extra_kwargs, fill_z, fillalpha, fillcolor, fillrange, fillstyle, group, hover, label, levels, line_z, linealpha, linecolor, linestyle, linewidth, marker_z, markeralpha, markercolor, markershape, markersize, markerstrokealpha, markerstrokecolor, markerstrokestyle, markerstrokewidth, normalize, orientation, permute, primary, quiver, ribbon, series_annotations, seriesalpha, seriescolor, seriestype, show_empty_bins, smooth, stride, subplot, weights, x, xerror, y, yerror, z, z_order, zerror
You can also query what individual attributes mean and which values are allowed:
plotattr("linestyle"):linestyle
Style of the line (for path and bar stroke). Choose from [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
Aliases: (:linestyles, :ls, :s, :style).
Type: Symbol.
`Series` attribute, defaults to `solid`.
An example:
theme(:default) # return to default theme
x = 0:0.05:1
y = sin.(2π*x)
plot(x, y, seriestype = :sticks, linewidth = 4, seriescolor = "#00b300",
marker = :circle, markersize = 8, markercolor = :green,
)Many specifications can be abbreviated significantly; see, e.g., the Aliases: in the output of plotattr("linestyle").
The following plot() command is equivalent to the previous one:
plot(x, y, t = :sticks, w = 4, c = "#00b300", m = (:circle, 8, :green ))16.2.5 Additional Extras
using Plots # no harm in repeating
using Plots.PlotMeasures # for measurements in mm, cm,...
using LaTeXStrings # for LaTeX constructs in plot labels
using PlotThemes # predefined themesThe LaTeXStrings.jl package provides the L"..." string constructor. These strings can contain LaTeX constructs, especially formulas. Without explicit dollar signs, they are automatically interpreted in LaTeX math mode.
xs = range(0, 2π, length = 100)
data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 functions
theme(:ggplot2)
plot10 = plot(xs, data,
fontfamily="Computer Modern",
# LaTeX string L"..."
title = L"Trigonometric functions $\sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)$",
xlabel = L"angle $\alpha$",
ylabel = "value",
# 1x4-matrices with colors, markers,... for the 4 'series'
color=[:black :green RGB(0.3, 0.8, 0.2) :blue ],
markers = [:rect :circle :utriangle :diamond],
markersize = [2 1 0 4],
linewidth = [1 3 1 2],
linestyle = [:solid :dash :dot :solid ],
# axes
xlim = (0, 6.6),
ylim = (-2, 2.3),
yticks = -2:.4:2.3, # with step size
# legend
legend = :bottomleft,
label = [ L"\sin(\alpha)" L"\cos(\alpha)" L"2\sin(\alpha)" L"\sin(\alpha^2)"],
top_margin = 5mm, # here Plots.PlotMeasures is needed
)
# additional text: annotate!(x-pos, y-pos, text("...", font, fontsize))
annotate!(plot10, 4.1, 1.8, text("Some remark","Computer Modern", 10) )16.2.6 Other Plot Functions
So far, we have mainly plotted lines. Many other types exist, such as scatter plots, contours, heatmaps, histograms, sticks, etc.
This can be controlled with the seriestype attribute:
theme(:default)
x = range(0, 2π; length = 50)
plot(x, sin.(x), seriestype=:scatter)or by using the specific function named after the seriestype:
x = range(0, 2π; length = 50)
scatter(x, sin.(x))16.2.7 Subplots and Layout
Multiple plots can be combined into one figure. The arrangement is determined by the layout parameter: layout=(m,n) arranges plots in an \(m\times n\) grid:
x = range(0, 2π; length = 100)
plots = [] # vector of plot objects
for f in [sin, cos, tan, sinc]
p = plot(x, f.(x))
push!(plots, p)
end
plot(plots..., layout=(2,2), legend=false, title=["sin" "cos" "tan" "sinc"])plot(plots..., layout=(4,1), legend=false, title=["sin" "cos" "tan" "sinc"])Layouts can also be nested and explicit width/height proportions can be specified using the @layout macro:
mylayout = @layout [
a{0.3w} [ b
c{0.2h} ]
d{0.2h}
]
plot(plots..., layout=mylayout, legend=false, title=["sin" "cos" "tan" "sinc"])16.2.8 Backends
Plots.jl provides a unified interface to various backends (graphics engines). You can switch backends and use the same plot commands and attributes.
However, not all backends support all plot types and attributes. An overview is available here.
So far, we have used the default backend: GR, a graphics engine developed at the Jülich Research Center, primarily in C.
using Plots
backend() # display the selected backend, GR is the defaultPlots.GRBackend()
Another example:
x = 1:30
y = rand(30)
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Water level")The same plot with the PlotlyJS backend:
plotlyjs() # change plots backend
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Water level")This backend enables interactivity via JavaScript. Hovering over the image allows zooming and panning; 3D plots can also be rotated.
gr() # return to GR as backendPlots.GRBackend()
16.2.9 3D Plots
The surface() and contour() functions plot a function \(f(x,y)\). Required arguments are:
- a set (vector) \(X\) of \(x\)-values,
- a set (vector) \(Y\) of \(y\)-values and
- a function of two variables that is then evaluated on \(X \times Y\) and plotted.
f(x,y) = (1 - x/2 + x^5 + y^3) * exp(-x^2 - y^2)
surface( -3:0.02:3, -3:0.02:3, f)contour( -3:0.02:3, -3:0.02:3, f, fill=true, colormap=:summer, levels=20, contour_labels=false)Curves (or point sets) in three dimensions are plotted by calling plot() with three vectors containing the \(x\), \(y\), and \(z\) coordinates of the data points.
plotlyjs()
t = range(0, stop=8π, length=100) # parameter t
x = @. t * cos(t) # x(t), y(t), z(t)
y = @. 0.1 * t * sin(t)
z = @. 100 * t/8π
plot(x, y, z, zcolor=reverse(z), markersize=3, markershape= :circle,
linewidth=5, legend=false, colorbar=false)The
plotlyjsbackend makes the plot interactive: it can be rotated and zoomed with the mouse.
16.2.10 Plots.jl and recipes
Other packages can extend Plots.jl by defining so-called recipes for special plots and data structures (see https://docs.juliaplots.org/latest/ecosystem/), e.g.:
StatsPlots.jl: direct plotting of DataFrames, special statistical plots, etc.GraphRecipes.jl: plotting of graph structures
16.2.11 A Bar Chart
For the last example, we load a package providing over 700 free (“public domain”) datasets, including:
- the Titanic passenger list,
- fuel consumption data for American cars from the 70s, or
- historical exchange rates:
using RDatasetsThe dataset “Motor Trend Car Road Tests”
cars = dataset("datasets", "mtcars")| Row | Model | MPG | Cyl | Disp | HP | DRat | WT | QSec | VS | AM | Gear | Carb |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| String31 | Float64 | Int64 | Float64 | Int64 | Float64 | Float64 | Float64 | Int64 | Int64 | Int64 | Int64 | |
| 1 | Mazda RX4 | 21.0 | 6 | 160.0 | 110 | 3.9 | 2.62 | 16.46 | 0 | 1 | 4 | 4 |
| 2 | Mazda RX4 Wag | 21.0 | 6 | 160.0 | 110 | 3.9 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
| 3 | Datsun 710 | 22.8 | 4 | 108.0 | 93 | 3.85 | 2.32 | 18.61 | 1 | 1 | 4 | 1 |
| 4 | Hornet 4 Drive | 21.4 | 6 | 258.0 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
| 5 | Hornet Sportabout | 18.7 | 8 | 360.0 | 175 | 3.15 | 3.44 | 17.02 | 0 | 0 | 3 | 2 |
| 6 | Valiant | 18.1 | 6 | 225.0 | 105 | 2.76 | 3.46 | 20.22 | 1 | 0 | 3 | 1 |
| 7 | Duster 360 | 14.3 | 8 | 360.0 | 245 | 3.21 | 3.57 | 15.84 | 0 | 0 | 3 | 4 |
| 8 | Merc 240D | 24.4 | 4 | 146.7 | 62 | 3.69 | 3.19 | 20.0 | 1 | 0 | 4 | 2 |
| 9 | Merc 230 | 22.8 | 4 | 140.8 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2 |
| 10 | Merc 280 | 19.2 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4 |
| 11 | Merc 280C | 17.8 | 6 | 167.6 | 123 | 3.92 | 3.44 | 18.9 | 1 | 0 | 4 | 4 |
| 12 | Merc 450SE | 16.4 | 8 | 275.8 | 180 | 3.07 | 4.07 | 17.4 | 0 | 0 | 3 | 3 |
| 13 | Merc 450SL | 17.3 | 8 | 275.8 | 180 | 3.07 | 3.73 | 17.6 | 0 | 0 | 3 | 3 |
| ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
| 21 | Toyota Corona | 21.5 | 4 | 120.1 | 97 | 3.7 | 2.465 | 20.01 | 1 | 0 | 3 | 1 |
| 22 | Dodge Challenger | 15.5 | 8 | 318.0 | 150 | 2.76 | 3.52 | 16.87 | 0 | 0 | 3 | 2 |
| 23 | AMC Javelin | 15.2 | 8 | 304.0 | 150 | 3.15 | 3.435 | 17.3 | 0 | 0 | 3 | 2 |
| 24 | Camaro Z28 | 13.3 | 8 | 350.0 | 245 | 3.73 | 3.84 | 15.41 | 0 | 0 | 3 | 4 |
| 25 | Pontiac Firebird | 19.2 | 8 | 400.0 | 175 | 3.08 | 3.845 | 17.05 | 0 | 0 | 3 | 2 |
| 26 | Fiat X1-9 | 27.3 | 4 | 79.0 | 66 | 4.08 | 1.935 | 18.9 | 1 | 1 | 4 | 1 |
| 27 | Porsche 914-2 | 26.0 | 4 | 120.3 | 91 | 4.43 | 2.14 | 16.7 | 0 | 1 | 5 | 2 |
| 28 | Lotus Europa | 30.4 | 4 | 95.1 | 113 | 3.77 | 1.513 | 16.9 | 1 | 1 | 5 | 2 |
| 29 | Ford Pantera L | 15.8 | 8 | 351.0 | 264 | 4.22 | 3.17 | 14.5 | 0 | 1 | 5 | 4 |
| 30 | Ferrari Dino | 19.7 | 6 | 145.0 | 175 | 3.62 | 2.77 | 15.5 | 0 | 1 | 5 | 6 |
| 31 | Maserati Bora | 15.0 | 8 | 301.0 | 335 | 3.54 | 3.57 | 14.6 | 0 | 1 | 5 | 8 |
| 32 | Volvo 142E | 21.4 | 4 | 121.0 | 109 | 4.11 | 2.78 | 18.6 | 1 | 1 | 4 | 2 |
We only need two columns for the plot: cars.Model and cars.MPG, the fuel consumption in miles per gallon (higher is more economical).
theme(:bright)
bar(cars.Model, cars.MPG,
label = "Miles/Gallon",
title = "Models and Miles/Gallon",
xticks =:all,
xrotation = 45,
size = [600, 400],
legend =:topleft,
bottom_margin = 10mm
)16.2.12 What is Missing: Animation
See the documentation; here is an example (from https://www.juliafordatascience.com/animations-with-plots-jl/):
using Plots, Random
theme(:default)
anim = @animate for i in 1:50
Random.seed!(123)
scatter(cumsum(randn(i)), ms=i, lab="", alpha = 1 - i/50,
xlim=(0,50), ylim=(-5, 7))
end
gif(anim, fps=50)