Julia: Tutorial & Code-Collection¶

Source: https://github.com/markomlikota/CodingSoftware

MIT License, Ā© Marko Mlikota, https://markomlikota.github.io

Plotting¶

InĀ [Ā ]:
# Let's install the new packages needed in this section:
vPkgs = ["Plots",
         "StatsPlots",
         "Measures"]
Pkg.add.(vPkgs)
InĀ [2]:
sPathMain            = "/files/Julia/TutorialCodecollection/" # (insert your own path here)
sPathOutput          = sPathMain * "/Output/"

using Plots

Single Vector (Line-Plot) & Basics¶

InĀ [3]:
vx = collect(1:5:100)

fMySquare(x) = x^2
vy = fMySquare.(vx)

using Distributions
myDist = Normal(25,8)
vz = pdf.(myDist,vx)
Out[3]:
20-element Vector{Float64}:
 0.0005539810514922509
 0.002971487603739226
 0.010784664853313941
 0.026484580721962435
 0.04400816584553744
 0.04947971086809369
 0.037642179019350554
 0.019376533182286652
 0.006748870814148508
 0.001590522699603929
 0.000253631007162471
 2.7366454720576512e-5
 1.9979676383631843e-6
 9.869884675867493e-8
 3.299054004463217e-9
 7.461402864292904e-11
 1.1418400510455742e-12
 1.1823437850983154e-14
 8.28392181996094e-17
 3.927190135831084e-19
InĀ [4]:
# The very basics:

# Plot single vector:
plot(vy) # x-axis defaults to 1:1:length(vy)

# Plot one vector against another:
plot(vx, vy)

# Can also plot directly function against x-axis: 
plot(fMySquare, vx)

# Can also plot a distribution against x-axis:
using StatsPlots
plot(myDist, vx)
Out[4]:
InĀ [5]:
# Labels:

# Edit line-label:
plot(vx, vy, label="single label looks ugly")
plot(vx, vy, label="")

# Add title and axis-labels:
plot(vx, vy, label="", title="An amazing plot", xlabel="xxx", ylabel="yyy")

# Change their font size:
myFS = 12
plot(vx, vy, label="", title="An amazing plot", xlabel="xxx", ylabel="yyy", titlefont=font(myFS), xtickfont=font(myFS), ytickfont=font(myFS))

# Can add latex-labels: e.g.:
plot(vx, vy, label="", title="Plot of  \$ \\alpha(x) \$")
# declare equation-start and -end by "\$", and use double-backslash instead of single backlash in front of latex-definitions
Out[5]:
InĀ [6]:
# Appearance of line:

plot(vx, vy, label="", line = (:black, 1, 2, :solid))

# First number gives transparency, second gives thickness:
plot(vx, vy, label="", line = (:black, 0.5, 2, :solid))
plot(vx, vy, label="", line = (:black, 1, 5, :solid))

# Linetype:
plot(vx, vy, label="", line = (:black, 1, 2, :dash))
plot(vx, vy, label="", line = (:black, 1, 2, :dot))
plot(vx, vy, label="", line = (:black, 1, 2, :dashdot))
plot(vx, vy, label="", line = (:black, 1, 2, :dashdotdot))
# (Sidenote: can also type ":line" instead of ":solid".)

# Color:
plot(vx, vy, label="", line = (:blue, 1, 2, :solid))
plot(vx, vy, label="", line = (:red, 1, 2, :solid))

# Get nicer colors by using "colorschemes":
cgrad(:blues) # color-palette as gradient; indexable by x ∈ [0.0, 1.0]
palette(:Blues_9) # color-palette as vector; indexable x = 1, 2, ... (here: 9 elements) 
# see https://docs.juliaplots.org/latest/generated/colorschemes/ for schemes available
# Can also define own gradient/vector of colors: e.g. 
myBlue  = cgrad(:blues)[1.0]
myRed   = cgrad(:reds)[1.0]
cgrad([myRed,myBlue]) # gradient
vColors = range(start=myRed, stop=myBlue, length=10) # vector

myBlue = cgrad(:blues)[1.0] # very nice blue
plot(vx, vy, label="", line = (myBlue, 1, 2, :solid))
Out[6]:
InĀ [7]:
# Appearance of axes:

# Edit limits:
plot(vx, vy, label="", xlims=(-20,150), ylims=(0,5000))
# To just edit lower limit of e.g. x-axis: (analogously for upper limit and for y-axis)
plot(vx, vy, label="", xlims=(-20,Inf))

# Edit ticks: (e.g. x-ticks; analogously for y-ticks)
myTicks         = [0,25,50,100,150]
myTickLabs      = string.(myTicks)
plot(vx, vy, label="", xlims=(-20,150), xticks=(myTicks,myTickLabs))
# e.g. have tick-labels in multiples of 100:
myTickLabs      = string.(myTicks./100)
plot(vx, vy, label="", xlims=(-20,150), xticks=(myTicks,myTickLabs), xlabel="xxx [in 100s]")
# Remove tick-label at 25, but leave tick-mark:
myTickLabs[2] = ""
plot(vx, vy, label="", xlims=(-20,150), xticks=(myTicks,myTickLabs))
# Faster, but less flexible way to have tick-labels in multiples of 100:
plot(vx, vy, label="", xlims=(-20,150), xformatter = x -> string(x/100), xlabel="xxx [in 100s]")

# Change font size of ticks:
plot(vx, vy, label="", title="An amazing plot", xlabel="xxx", ylabel="yyy", xguidefontsize=myFS, yguidefontsize=myFS)

# Note: to plot dates, best convert to continuous number.
# e.g. for quarterly data, use 1970.00, 1970.25, etc.
Out[7]:
InĀ [8]:
# Ex-post changes of title, axis-labels, and axis-appearance

# We can change everything that pertains to the plot as a whole
# (and not just the single line we plotted) using plot!(...):
plot(vx, vy, label="")
# e.g. title and axis-labels:
plot!(title="An amazing plot", xlabel="xxx", ylabel="yyy")
# e.g. axis-limits:
plot!(xlims=(-20,150), ylims=(0,5000))
# e.g. axis-ticks:
plot!(xticks=(myTicks,myTickLabs))

# Sidenote: some of these can also be changed directly using e.g.
# xlabel!("xxx") or ylims!((0,5000)),
# but I find it easier to remember the approach above;
# write plot!(...) and add the options you want 
# in the same way as you would when you first create a plot.
Out[8]:
InĀ [9]:
# Further options:

plot(vx, vy, label="", grid=false) # remove grid in background

vline!([0], label="") # add vertical line at x=0
hline!([100], label="") # add horizontal line at y=100

# Add text to plot:
annotate!(5, 1000, text("note that curve goes below 100", :blue, :left, 10)) 

xflip!(true) # flip x-axis

# Edit margins:
using Measures
# e.g.:
plot(vx, vy, label="", title="An amazing plot", topmargin=5mm) 

# Add shaded area around line:
# 1. same distance for all x: 
plot(vx, vy, ribbon=(200,500), fillalpha=0.2, fillcolor=:blue)
# 2. distinct distance across x, but same for top and bottom: ("symmetric bounds")
vDist           = rand(Uniform(200,500),length(vy))
plot(vx, vy, ribbon=vDist, fillalpha=0.2 , fillcolor=:blue)
# 3. distinct distance across x and between top and bottom: ("asymmetric bounds")
vDistBottom     = rand(Uniform(200,300),length(vy))
vDistTop        = rand(Uniform(200,800),length(vy))
plot(vx, vy, ribbon=(vDistBottom,vDistTop), fillalpha=0.2 , fillcolor=:blue)
Out[9]:
InĀ [10]:
# Save the plot as file:

plot(vx, vy, label="")
savefig(sPathOutput * "plot1.png") 
# "savefig" saves currently displayed plot (the one just created in line above)

# Note that we can create the plot as an object...:
plot1 = plot(vx, vy, label="")
# ... and display it even after its creation:
display(plot1)

# This allows us to save it after it's been created:
savefig(plot1, sPathOutput * "plot1.png")
Out[10]:
"/files/Julia/TutorialCodecollection/Output/plot1.png"

Try Exercises 13.a.i - 13.a.ii



Multiple Vectors (Line-Plot)¶

InĀ [11]:
vx  = collect(-2:0.1:2)
vy1 = vx.^2
vy2 = vx.^3
vy3 = vx.^4
Out[11]:
41-element Vector{Float64}:
 16.0
 13.032099999999998
 10.4976
  8.352099999999998
  6.553600000000001
  5.0625
  3.8415999999999992
  2.8561000000000005
  2.0736
  1.4641000000000004
  1.0
  0.6561
  0.4096000000000001
  ā‹®
  0.6561
  1.0
  1.4641000000000004
  2.0736
  2.8561000000000005
  3.8415999999999992
  5.0625
  6.553600000000001
  8.352099999999998
 10.4976
 13.032099999999998
 16.0
InĀ [12]:
# To plot multiple lines, 
# type plot() for first line, followed by plot!() for each subsequent one:
plot(vx, vy1, label="line 1")
plot!(vx, vy2, label="line 2")
plot!(vx, vy3, label="line 3")

# Again, we can save this plot as an object:
myplot2 = plot(vx, vy1, label="line 1")
plot!(vx, vy2, label="line 2")
plot!(vx, vy3, label="line 3")
Out[12]:
InĀ [13]:
# Edit legend:

# Position:
plot(vx, vy1, label="line 1", legend = :bottom)
plot!(vx, vy2, label="line 2")
plot!(vx, vy3, label="line 3")
# The option "legend" specifies the position of the legend.
# Can use :bottom, :top, :left, :right as well as :topright, :bottomleft, etc.,
# and can also add "outer" in front (e.g. :outertopright) to put legend outside of plot area.

# To remove the legend, add "legend = false".

# To set color of legend frame to transparent:
plot(vx, vy1, label="line 1", legend = :bottom, foreground_color_legend = nothing)
# To set color of legend background to transparent:
plot(vx, vy1, label="line 1", legend = :bottom, background_color_legend = nothing)

# For the legend, even more so than for other options,
# it is useful to adjust the plot ex-post, e.g.:
plot(vx, vy1, label="line 1")
plot!(vx, vy2, label="line 2")
plot!(vx, vy3, label="line 3")
plot!(legend = :bottom, foreground_color_legend = nothing, background_color_legend = nothing)
Out[13]:
InĀ [14]:
# Of course, all options discussed above (labels, axis-appearance, ...)
# are applicable no matter how many lines we plot.

# Thereby, we can adjust the appearance of each line separately; e.g.
plot(vx, vy1, label="line 1", line = (:blue, 1, 2, :solid))
plot!(vx, vy2, label="line 2", line = (:blue, 1, 2, :dash))
plot!(vx, vy3, label="line 3", line = (:blue, 1, 2, :dashdot))

# It's useful to create linetypes and/or colors ex-ante
# (to more easily adjust them later):
vMyColors       = [cgrad(:blues)[xx/3] for xx in 1:3]
plot(vx, vy1, label="line 1", line = (vMyColors[1], 1, 2, :solid))
plot!(vx, vy2, label="line 2", line = (vMyColors[2], 1, 2, :solid))
plot!(vx, vy3, label="line 3", line = (vMyColors[3], 1, 2, :solid))
Out[14]:
InĀ [15]:
# Along these lines, we can also create a multiple-line-plot in a loop:

# First, create all necessary ingredients:
mY              = [vy1 vy2 vy3]
vMyLineTypes    = [:solid, :solid, :solid]
vMyColors       = [cgrad(:blues)[xx/3] for xx in 1:3]
vsMyLineLabs    = string.("line ",1:3)

# Then, create empty plot:
plot2 = plot([0,0],[NaN,NaN],label="", grid=false,
                        titlefont=font(myFS), xtickfont=font(myFS), ytickfont=font(myFS), 
                        xguidefontsize=myFS, yguidefontsize=myFS,
                        legend = :bottom, 
                        background_color_legend = nothing, 
                        foreground_color_legend = nothing,
                        legendfontsize=myFS)

# Thend, add line-by-line to this empty plot in for-loop:
for ii = 1:3
    plot!(vx, mY[:,ii], label=vsMyLineLabs[ii], line = (vMyColors[ii], 1, 2, vMyLineTypes[ii]))                           
end

# Finally, show resulting plot:
display(plot2)
InĀ [16]:
# The empty plot also provides a way 
# to save options that we want to apply to several plots 
# without having to type them for every plot anew:

# Create function that returns the empty plot with specified options:
fMyEmptyPlot() = plot([0,0],[NaN,NaN],label="", grid=false,
                        titlefont=font(myFS), xtickfont=font(myFS), ytickfont=font(myFS), 
                        xguidefontsize=myFS, yguidefontsize=myFS)

# Create two plots that both use these options:
plotA = fMyEmptyPlot()
plot!(vx,vy1, label="", line=(:black,1,2,:solid))    

plotB = fMyEmptyPlot()
plot!(vx,vy2, label="", line=(:black,1,2,:solid))
Out[16]:

Multiple Vectors (Scatter-Plot)¶

InĀ [17]:
# Above, we plotted one or several vectors (vy, vz, vy1, ...) against another vector (vx).
# Using the command plot() (or plot!()), we obtained a line-plot, 
#Ā i.e. a plot where the values of each plotted vector are connected by a line.
# To obtain a scatter plot, we just use the command scatter() instead of plot().
InĀ [18]:
# For example:

scatter(vx, vy1, label="set of values 1")
scatter!(vx, vy2, label="set of values 2")
scatter!(vx, vy3, label="set of values 3")
Out[18]:
InĀ [19]:
# Note that can mix scatter (points) and lines:

scatter(vx, vy1, label="set of values")
plot!(vx, vy2, label="line")
Out[19]:
InĀ [20]:
# More sensible scatter-plot-example:

vx = [2, 3, 6, 7, 9, 14]
vy = [9, 8, 8, 4, -2, 1]
scatter(vx, vy, label="")
Out[20]:
InĀ [21]:
# All of the options discussed above are applicable (labels, axis-appearance, legend, ...),
# except of course the ones regarding line-appearance.
# e.g.
scatter(vx, vy, label="", ylims=(-3,10),xlims=(0,15))
scatter(vx, vy, label="", title="my amazing scatter-plot", xlabel="one set of values", ylabel="another set of values")
Out[21]:
InĀ [22]:
# Instead of adjusting the appearance of lines, 
# we can adjust the appearance of markers: e.g.
scatter(vx, vy, label="", marker=(:circ, :red), markersize=5, markerstrokewidth=4)
# To see list of supported marker-types:
Plots.supported_markers()
Out[22]:
25-element Vector{Symbol}:
 :+
 :auto
 :circle
 :cross
 :diamond
 :dtriangle
 :heptagon
 :hexagon
 :hline
 :ltriangle
 :none
 :octagon
 :pentagon
 :pixel
 :rect
 :rtriangle
 :star4
 :star5
 :star6
 :star7
 :star8
 :utriangle
 :vline
 :x
 :xcross
InĀ [23]:
# Label points:

vsPointLabs = ["CHE", "AUT", "AUS", "SRB", "HRV", "BRA"]
scatter(vx, vy, label="", series_annotations = text.(vsPointLabs, :left, :bottom))

# For non-overlapping scatter-labels, 
# see post by user "cbsteh" on stackoverflow:
# https://stackoverflow.com/questions/74355327/how-to-add-text-labels-to-a-scatterplot
Out[23]:

Try Exercises 13.b.i - 13.b.ii



Histogram¶

InĀ [24]:
vData       = rand(Normal(0,1),1000)
vData2      = rand(Normal(2,2),1000)

vDataVals3  = [2, 3, 7]
vWeights    = [0.3, 0.6, 0.1]
Out[24]:
3-element Vector{Float64}:
 0.3
 0.6
 0.1
InĀ [25]:
# Histogram with absolute frequency on y-axis:
histogram(vData)
   
# Histogram with relative frequency on y-axis:
histogram(vData, normalize=:pdf)

# Histogram for set of values with respective relative frequency (weights):
histogram(vDataVals3, weights=vWeights)
Out[25]:
InĀ [26]:
# Specify bin-borders: (for n bins, need n+1 values!)
histogram(vDataVals3, weights=vWeights, bins=collect(1:1:8)) 
# Typically need to edit ticks and tick-labels as well, then:
minBinVal   = -4
maxBinVal   = 4
binWidth    = 0.25
tickStep    = 2
histogram(vData, bins=collect((minBinVal-binWidth):binWidth:(maxBinVal+binWidth)), 
                    xlims=((minBinVal-binWidth),(maxBinVal+binWidth)), 
                    xticks=collect(minBinVal:tickStep:maxBinVal))
Out[26]:
InĀ [27]:
# Edit bin appearance:
myBlue      = cgrad(:blues)[1.0]
myLightBlue = cgrad(:blues)[0.5]
histogram(vData, linecolor=myBlue, fillcolor=myLightBlue, fillalpha=0.8)
Out[27]:
InĀ [28]:
# Drop label:
histogram(vData, label="") # or:
histogram(vData, legend=:none)
Out[28]:
InĀ [29]:
# Can also plot several histograms in single plot:
myBlue     = cgrad(:blues)[1.0]
myRed      = cgrad(:reds)[1.0]
histogram(vData, linecolor=myBlue, fillcolor=myBlue, fillalpha=0.5)
histogram!(vData2, linecolor=myRed, fillcolor=myRed, fillalpha=0.5)
# Note that need to have both sets of bins quite transparent,
# otherwise latter histogram will completely cover parts of former.
Out[29]:

Other Plot Types¶

InĀ [30]:
# Kernel-density plot:

using StatsBase

vData       = rand(Normal(0,1),1000)

density(vData) 
density(vData, bandwidth = 0.1) # under-smoothing
density(vData, bandwidth = 10)  # over-smoothing

# Combine histogram, Kernel density-estimate and true density:
histogram(vData, normalize=:pdf, fillcolor=:black, fillalpha=0.2, label="Histogram of draws")
density!(vData, label="Kernel density estimate", line = (:black, 1, 2, :solid)) 
plot!(Normal(0,1), label="True density", line = (:red, 1, 2, :solid))

# Note that we can also estimate and then plot the kernel density
# using the package KernelDensity discussed further below.
Out[30]:
InĀ [31]:
# Bar-plot:

vy = [2, 3, 6, 7, 9, 14]
vx = collect(range(start=2, step=2, length=length(vy)))

bar(vy) # as with plot(), x-axis defaults to 1:1:length(vy)

bar(vx,vy)
# adjust ticks:
bar(vx,vy, label="", xticks=(vx,string.(vx)))
Out[31]:
InĀ [32]:
# Grouped bar-plot:

mY          = [2 6 3; 7 9 14]
vsGroupLabs = ["a" "b" "c"]
println(mY)

groupedbar(mY)

# Edit labels:    
groupedbar(mY, label=vsGroupLabs)

groupedbar(mY, label=vsGroupLabs, bar_position = :stack)
# default is :dodge, as above

# Regardless of type, first set of bars is centered at x=1, second at x=2, etc.

# Change width of each set of bars:
groupedbar(mY, label=vsGroupLabs, bar_width=0.3)
groupedbar(mY, label=vsGroupLabs, bar_width=1.0)

# Change colors:
groupedbar(mY, label=vsGroupLabs, color = [:red :green :blue])
[2 6 3; 7 9 14]
Out[32]:
InĀ [33]:
# Pie-plot:

vy      = [2, 3, 7]
vsLabs  = ["a", "b", "c"]

pie(vy) # group-labels default to 1:1:length(vy) (they are like x-axis here)

# Edit labels:
pie(vsLabs, vy)
Out[33]:
InĀ [34]:
# 3d-plots:

vx              = collect(-5:0.01:5)
vy              = collect(-3:0.01:3)

myDist          = MvNormal([2,0],[1 0.3; 0.3 0.8])
fMyPDF(x,y)     = pdf(myDist,[x,y])
mz              = [fMyPDF(x,y) for x in vx, y in vy]
Out[34]:
1001Ɨ601 Matrix{Float64}:
 2.44481e-12  2.47582e-12  2.50688e-12  …  5.1548e-20   4.79785e-20
 2.61198e-12  2.64522e-12  2.67851e-12     5.64844e-20  5.25753e-20
 2.79026e-12  2.8259e-12   2.86158e-12     6.18866e-20  5.7606e-20
 2.98038e-12  3.01857e-12  3.05682e-12     6.77977e-20  6.3111e-20
 3.18309e-12  3.22402e-12  3.26501e-12     7.42651e-20  6.91342e-20
 3.39921e-12  3.44306e-12  3.48698e-12  …  8.13402e-20  7.57237e-20
 3.6296e-12   3.67657e-12  3.72363e-12     8.90794e-20  8.2932e-20
 3.87516e-12  3.92548e-12  3.97589e-12     9.75439e-20  9.08162e-20
 4.13687e-12  4.19076e-12  4.24476e-12     1.06801e-19  9.94388e-20
 4.41575e-12  4.47347e-12  4.5313e-12      1.16923e-19  1.08868e-19
 4.71291e-12  4.77471e-12  4.83664e-12  …  1.2799e-19   1.19177e-19
 5.02949e-12  5.09566e-12  5.16197e-12     1.40089e-19  1.30449e-19
 5.36674e-12  5.43757e-12  5.50857e-12     1.53314e-19  1.4277e-19
 ā‹®                                      ⋱               ā‹®
 7.74643e-8   8.17946e-8   8.63548e-8      0.000121364  0.00011778
 7.40338e-8   7.81756e-8   8.25376e-8   …  0.000118962  0.000115455
 7.07472e-8   7.47083e-8   7.88802e-8      0.000116595  0.000113162
 6.75989e-8   7.13868e-8   7.53763e-8      0.000114262  0.000110903
 6.45834e-8   6.82052e-8   7.202e-8        0.000111964  0.000108676
 6.16955e-8   6.51581e-8   6.88054e-8      0.000109699  0.000106482
 5.89301e-8   6.22401e-8   6.57268e-8   …  0.000107468  0.000104321
 5.62823e-8   5.94461e-8   6.2779e-8       0.00010527   0.000102192
 5.37474e-8   5.67712e-8   5.99565e-8      0.000103105  0.000100095
 5.13209e-8   5.42104e-8   5.72546e-8      0.000100974  9.80299e-5
 4.89985e-8   5.17594e-8   5.46682e-8      9.88758e-5   9.59968e-5
 4.67758e-8   4.94136e-8   5.21928e-8   …  9.68102e-5   9.39953e-5
InĀ [35]:
# Surface:
plot(vx, vy, mz', st=:surface)
Out[35]:
InĀ [36]:
# Contour:
plot(vx, vy, mz', st=:contour)
Out[36]:
InĀ [37]:
# Heatmap:
heatmap(vx, vy, mz')
Out[37]:
InĀ [38]:
# Sidenote: can also supply function:
plot(vx, vy, fMyPDF, st=:surface)
plot(vx, vy, fMyPDF, st=:contour)
heatmap(vx, vy, fMyPDF)
Out[38]:
InĀ [39]:
# Again, lots of options from above (labels, axis-appearance, etc.) are applicable,
# whereby we have three axes here.

# Can change color by supplying color-gradient:

plot(vx, vy, mz', st=:surface, color=:reds)
plot(vx, vy, mz', st=:contour, color=:reds)
heatmap(vx, vy, mz', color=:reds)

# Own color gradient:
myColGr = cgrad([:red,:blue])
plot(vx, vy, mz', st=:surface, color=myColGr)
plot(vx, vy, mz', st=:contour, color=myColGr)
heatmap(vx, vy, mz', color=myColGr)

# To remove color-bar on the right:
plot(vx, vy, mz', st=:surface, color=:reds, colorbar = false)
Out[39]:
InĀ [40]:
# In surface-plot, can also edit camera-angle:

plot(vx, vy, mz', st=:surface, camera=(60,30))
Out[40]:

Combine Multiple Plots into Single Figure¶

InĀ [41]:
vx  = collect(-2:0.1:2)
vy1 = vx.^2
vy2 = vx.^3
vy3 = vx.^4
vy4 = vx.^5

plot1 = plot(vx, vy1, line = (:black, 1, 2, :solid))
plot2 = plot(vx, vy2, line = (:black, 1, 2, :solid))
plot3 = plot(vx, vy3, line = (:black, 1, 2, :solid))
plot4 = plot(vx, vy4, line = (:black, 1, 2, :solid))
Out[41]:
InĀ [42]:
plot(plot1, plot2, layout=(1,2))
Out[42]:
InĀ [43]:
# Delete legend in each plot:
plot(plot1, plot2, layout=(1,2), legend=false)
Out[43]:
InĀ [44]:
# Can also adjust other options (for each plot): e.g.
plot(plot1, plot2, layout=(1,2), grid=false)
plot(plot1, plot2, layout=(1,2), ylims=(-5,5))
Out[44]:
InĀ [45]:
# Can also save multiple plots to single vector ...:
vPlots = Vector{Any}(undef,4)
vPlots[1] = plot1
vPlots[2] = plot2
vPlots[3] = plot3
vPlots[4] = plot4
# ... and then combine several plots from this vector:
plot(vPlots..., layout=(2,2))
plot(vPlots[1:2]..., layout=(1,2))
Out[45]:
InĀ [46]:
# Note that we fill plots row-by-row;
plot(vPlots..., layout=(2,2))

# To fill plots column-by-column:
nr = 2
nc = 2
mA = reshape(1:nr*nc,nr,nc) # this is how I want the plots to be ordered
mAt = mA' # this is how Julia does it by default
plot(vPlots[vec(mAt)]..., layout=(nr,nc))
Out[46]:
InĀ [47]:
# Add overarching title to 1x2-plot:

myLayout = @layout [a{.1h};grid(1,2)]
plot(
   plot(annotation=(0.5,0.5, "My amazing title"), framestyle = :none),
   plot1, plot2,
   layout = myLayout)
Out[47]:

Try Exercises 13.c.i - 13.c.iii