using Plots
= range(0, 8π; length = 100)
x = @. sin(x) # the @. macro broadcasts (vectorizes) every operation
sx = @. cos(2x^(1/2))
cx
plot(x, [sx cx])
16 Plots und Datenvisualisierung in Julia: Plots.jl
Es gibt zahlreiche Grafikpakete für Julia. Zwei oft genutzte sind Makie.jl und Plots.jl. Bevor wir diese genauer vorstellen, seien noch einige andere Pakete aufgelistet.
16.1 Kurze Übersicht: einige Grafikpakete
Paket/Doku | Tutorial | Beispiele | Bemerkungen |
---|---|---|---|
Plots.jl | Tutorial | Galerie | konzipiert als einheitliches Interface zu verschiedenen backends (Grafikbibliotheken) |
Makie.jl | Basic tutorial | Beautiful Makie | “data visualization ecosystem for Julia”, Backends: Cairo (Vektorgrafik), OpenGL, WebGL |
PlotlyJS.jl | Getting started | Examples | Interface zur Plotly Javascript-Grafikbibliothek |
Gadfly.jl | Tutorial | Galerie | “a plotting and data visualization system written in Julia, influenced by R’s ggplot2” |
Bokeh.jl | Galerie | Julia-Frontend für Bokeh | |
VegaLite.jl | Tutorial | Examples | Julia-Frontend für Vega-Lite |
Luxor.jl | Tutorial | Examples | Allgemeine Vektorgrafik/Illustrationen |
Javis.jl | Tutorials | Examples | Animierte Vektorgrafik |
TidierPlots.jl | Reference | “is a 100% Julia implementation of the R package ggplot2 powered by Makie.jl” | |
PythonPlot.jl | Examples (in Python) | Interface zu Matplotlib (Python), 1:1-Übertragung der Python-API, deswegen s. Matplotlib-Dokumentation |
16.2 Plots.jl
16.2.1 Einfache Plots
Die plot()
-Funktion erwartet im einfachsten Fall:
- als erstes Argument einen Vektor von \(x\)-Werten der Länge \(n\) und
- als zweites Argument einen gleichlangen Vektor mit den dazugehörigen \(y\)-Werten.
- Das zweite Argument kann auch eine \(n\times m\)-Matrix sein. Dann wird jeder Spaltenvektor als eigener Graph (in der Docu
series
genannt) angesehen und es werden \(m\) Kurven geplottet:
- Die Funktionen des Plots.jl-Paketes wie
plot(), scatter(), contour(), heatmap(), histogram(), bar(),...
usw. starten alle einen neuen Plot. - Die Versionen
plot!(), scatter!(), contour!(), heatmap!(), histogram!(), bar!(),...
erweitern einen existierenden Plot:
plot(x, sx) # plot only sin(x)
plot!(x, cx) # add second graph
plot!(x, sqrt.(x)) # add a thirth one
Plots sind Objekte, die zugewiesen werden können. Dann kann man sie später weiterverwenden, kopieren und insbesondere mit den !
-Funktionen erweitern:
= plot(x, [sx cx])
plot1 = deepcopy(plot1) # plot objects are quite deep structures
plot1a scatter!(plot1, x, sx) # add scatter plot, i.e. unconnected data points
Die kopierte Version plot1a
ist durch die scatter!
-Anweisung nicht modifiziert worden und kann unabhängig weiterverwendet werden:
plot!(plot1a, x, 2 .* sx)
Plot-Objekte kann man als Grafikdateien (PDF, SVG, PNG,…) abspeichern:
savefig(plot1, "plot.png")
"/home/hellmund/Julia/23/Book-ansipatch/chapters/plot.png"
-l plot.png ;ls
-rw-r--r-- 1 hellmund hellmund 56158 Mar 3 17:09 plot.png
Plot-Objekte können auch als Teilplot in andere Plots eingefügt werden, siehe Abschnitt Kapitel 16.2.7.
16.2.2 Funktionsplots
Man kann plot()
auch eine Funktion und einen Vektor mit \(x\)-Werten übergeben:
# https://mzrg.com/math/graphs.shtml
f(x) = abs(sin(x^x)/2^((x^x-π/2)/π))
plot(f, 0:0.01:3)
Die parametrische Form \(x = x(t),\ y = y(t)\) kann durch die Übergabe von zwei Funktionen und einen Vektor von \(t\)-Werten an plot()
gezeichnet werden.
# 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-Themen
“PlotThemes is a package to spice up the plots made with Plots.jl.”
Hier geht es zur illustrierten Liste der Themen
oder:
using PlotThemes
# Liste der Themen
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
⋮
showtheme(:juno) Plots.
using PlotThemes
theme(:juno) # set a theme for all further plots
plot(x, [sx cx 1 ./ (1 .+ x)])
16.2.4 Plot-Attribute
Die Funktionen des Plots.jl
-Paketes haben eine große Anzahl von Optionen. Plots.jl
teilt die Attribute in 4 Gruppen ein:
plotattr(:Plot) # Attribute für den Gesamtplot
Defined 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) # Attribute für einen Teilplot
Defined 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) # Attribute für eine Achse
Defined 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, unitformat, widen
plotattr(:Series) # Attribute für eine Serie, also zB ein Linienzug im Plot
Defined 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
Man kann auch nachfragen, was die einzelnen Attribute bedeuten und welche Werte zulässig sind:
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`.
Ein Beispiel:
theme(:default) # zurück zum Standardthema
= 0:0.05:1
x = sin.(2π*x)
y
plot(x, y, seriestype = :sticks, linewidth = 4, seriescolor = "#00b300",
= :circle, markersize = 8, markercolor = :green,
marker )
Viele Angaben können auch sehr weit abgekürzt werden, siehe z.B. die Angabe Aliases:
in der obigen Ausgabe des Kommandos plotattr("linestyle")
.
Das folgende plot()
-Kommando is äquivalent zum vorherigen:
plot(x, y, t = :sticks, w = 4, c = "#00b300", m = (:circle, 8, :green ))
16.2.5 Weitere Extras
using Plots # Wiederholung schadet nicht
using Plots.PlotMeasures # für Maßangaben in mm, cm,...
using LaTeXStrings # für LaTeX-Konstrukte in Plot-Beschriftungen
using PlotThemes # vorgefertigte Themen
Das Paket LaTeXStrings.jl
stellt einen String-Konstruktor L"..."
zur Verfügung. Diese Strings können LaTeX-Konstrukte, insbesondere Formeln, enthalten. Wenn der String keine expliziten Dollarzeichen enthält, wird er automatisch im LaTeX-Math-Modus interpretiert.
= range(0, 2π, length = 100)
xs
= [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 Funktionen
data
theme(:ggplot2)
= plot(xs, data,
plot10 ="Computer Modern",
fontfamily
# LaTeX-String L"..."
= L"Winkelfunktionen $\sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)$",
title xlabel = L"Winkel $\alpha$",
= "Funktionswert",
ylabel
# 1x4-Matrizen mit Farben, Marker,... für die 4 'Series'
=[:black :green RGB(0.3, 0.8, 0.2) :blue ],
color= [:rect :circle :utriangle :diamond],
markers = [2 1 0 4],
markersize = [1 3 1 2],
linewidth = [:solid :dash :dot :solid ],
linestyle
# Achsen
= (0, 6.6),
xlim = (-2, 2.3),
ylim = -2:.4:2.3, # mit Schrittweite
yticks
# Legende
= :bottomleft,
legend = [ L"\sin(\alpha)" L"\cos(\alpha)" L"2\sin(\alpha)" L"\sin(\alpha^2)"],
label
= 5mm, # hier wird Plots.PlotMeasures gebraucht
top_margin
)
# Zusatztext: annotate!(x-pos, y-pos, text("...", font, fontsize))
annotate!(plot10, 4.1, 1.8, text("nicht schön, aber viel","Computer Modern", 10) )
16.2.6 Andere Plot-Funktionen
Bisher haben wir vor allem Linien geplottet. Es gibt noch viele andere Typen wie scatter plot, contour, heatmap, histogram, stick,…
Dies kann man mit dem seriestype
-Attribut steuern:
theme(:default)
= range(0, 2π; length = 50)
x plot(x, sin.(x), seriestype=:scatter)
oder indem man die spezielle Funktion benutzt, die so heißt wie der seriestype
:
= range(0, 2π; length = 50)
x scatter(x, sin.(x))
16.2.7 Subplots und Layout
Mehrere Plots können zu einer Abbildung zusammengefasst werden. Die Anordnung bestimmt der layout
-Parameter. Dabei bedeutet layout=(m,n)
, dass die Plots in einem \(m\times n\)-Schema angeordnet werden:
= range(0, 2π; length = 100)
x = [] # vector of plot objects
plots for f in [sin, cos, tan, sinc]
= plot(x, f.(x))
p 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"])
Man kann Layouts auch schachteln und mit dem @layout
-Macro explizite Breiten/Höhenanteile vorgeben:
= @layout [
mylayout 0.3w} [ b
a{0.2h} ]
c{0.2h}
d{
]
plot(plots..., layout=mylayout, legend=false, title=["sin" "cos" "tan" "sinc"])
16.2.8 Backends
Plots.jl
ist konzipiert als ein einheitliches Interface zu verschiedenen backends (Grafik-Engines). Man kann zu einem anderen Backend wechseln und dieselben Plot-Kommandos und -Attribute verwenden.
Allerdings unterstützen nicht alle backends alle Plot-Typen und -Attribute. Einen Überblick gibt es hier.
Bisher wurde das Standard-Backend verwendet. Es heißt GR und ist eine am Forschungszentrum Jülich entwickelte und hauptsächlich in C geschriebene Grafik-Engine.
using Plots
backend() # Anzeige des gewählten backends, GR ist der default
Plots.GRBackend()
Nochmal ein Beispiel
= 1:30
x = rand(30)
y plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
und hier derselbe Plot mit dem PlotlyJS
-Backend.
plotlyjs() # change plots backend
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
Dieses Backend ermöglich mit Hilfe von Javascript eine gewisse Interaktivität. Wenn man die Maus in das Bild bewegt, kann man mit der Maus zoomen, verschieben und 3D-Plots auch drehen.
gr() # zurück zu GR als backend
Plots.GRBackend()
16.2.9 3D Plots
Die Funktionen surface()
und contour()
ermöglichen den Plot einer Funktion \(f(x,y)\). Als Argumente werden benötigt:
- eine Menge (Vektor) \(X\) von \(x\)-Werten,
- eine Menge (Vektor) \(Y\) von \(y\)-Werten und
- eine Funktion von zwei Variablen, die dann auf \(X \times Y\) ausgewertet und geplottet wird.
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)
Kurven (oder auch einfach Punktmengen) in drei Dimensionen lassen sich plotten, indem man plot()
mit 3 Vektoren aufruft, die jeweils die \(x\), \(y\) und \(z\)-Koordinaten der Datenpunkte enthalten.
plotlyjs()
= range(0, stop=8π, length=100) # parameter t
t = @. t * cos(t) # x(t), y(t), z(t)
x = @. 0.1 * t * sin(t)
y = @. 100 * t/8π
z plot(x, y, z, zcolor=reverse(z), markersize=3, markershape= :circle,
=5, legend=false, colorbar=false) linewidth
Wir verwenden mal das
plotlyjs
-Backend, damit ist der Plot interaktiv und kann mit der Maus gedreht und gezoomt werden.
16.2.10 Plots.jl und recipes
Andere Pakete können die Möglichkeiten von Plots.jl
erweitern, indem sie sogenannte recipes für spezielle Plots und Datenstrukturen definieren, siehe https://docs.juliaplots.org/latest/ecosystem/, z.B.:
StatsPlots.jl
direktes Plotten von Dataframes, spezielle statistische Plots usw. oderGraphRecipes.jl
Plotten von Graphstrukturen
16.2.11 Ein Säulendiagramm
Für das letzte Beispiel laden wir ein Paket, das über 700 freie (“public domain”) Datensätze, darunter z.B:
- die Passagierliste der Titanic,
- Verbrauchsdaten amerikanischer Autos aus den 70ern oder
- historische Währungskurse
bereitstellt:
using RDatasets
Der Datensatz “Motor Trend Car Road Tests”
= dataset("datasets", "mtcars") cars
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 |
Wir brauchen für den Plot nur die beiden Spalten cars.Model
und cars.MPG
, den Benzinverbrauch in miles per gallon (Mehr heißt sparsamer!)
theme(:bright)
bar(cars.Model, cars.MPG,
= "Miles/Gallon",
label = "Models and Miles/Gallon",
title =:all,
xticks = 45,
xrotation = [600, 400],
size =:topleft,
legend = 10mm
bottom_margin )
16.2.12 Was noch fehlt: Animation
Hier sei auf die Dokumentation verwiesen und nur ein Beispiel (von https://www.juliafordatascience.com/animations-with-plots-jl/) angegeben:
using Plots, Random
theme(:default)
= @animate for i in 1:50
anim Random.seed!(123)
scatter(cumsum(randn(i)), ms=i, lab="", alpha = 1 - i/50,
=(0,50), ylim=(-5, 7))
xlimend
gif(anim, fps=50)