Plots und einfache Datenvisualisierung in Julia¶

  • Frage "Wie plottet man in Julia?" inzwischen genauso sinnvoll wie "Wie plottet man in C++?";
  • es gibt zahlreiche Pakete, die unterschiedlich geeignet sind je nach

    • Ausgabemedium: Grafikkarte, PDF, SVG, PNG, WebApp,....
    • Interaktivität
    • 2D- und 3D-Fähigkeiten
    • Plottypen
    • Umgang mit großen Datenmengen ...

Einbindung anderer Grafikbibliotheken¶

JavaScript: Interaktivität im Browser¶

  • PlotlyJS.jl Interface zur PlotlyJS-Grafikbibliothek
  • Bokeh.jl Interface zur Bokeh-Grafikbibliothek
  • VegaLite.jl Interface zu VegaLite, vor allem statistische Plots

Cairo: 2D Vektorgrafik, für Grafikkarte (screen), PDF, PNG, SVG,...¶

  • Luxor.jl für Vektorgrafik
  • Javis.jl für animierte Vektorgrafik

Matplotlib (Python)¶

  • PyPlot.jl

    • weitgehende 1:1-Übertragung der Python-API, deswegen wird auch auf die Matplotlib-Dokumentation verwiesen
    • Beispiele mit Gegenüberstellung Python/Julia: https://gist.github.com/gizmaa/7214002

Pure Julia: Makie.jl¶

Makie bezeichnet sich selbst als "data visualization ecosystem for Julia"

Es ist vollständig in Julia geschrieben und bietet als backends Cairo (Vektorgrafik), OpenGL und WebGL an.

  • Makie.jl
  • Beautiful Makie eine Seite mit vielen Beispielen

Plots.jl¶

  • Plots.jl ist konzipiert als ein einheitliches Interface zu verschiedenen backends (Grafikbibliotheken).

    Man kann zu einem anderen backend wechseln und dieselben Plot-Kommandos und -Attribute verwenden.

  • Einige backends:

    • GR
    • PyPlot (d.h., Matplotlib)
    • Plotly(JS)

Plots.jl schien mir am besten geeignet für den Workflow

Jupyter notebooks => Konvertierung nach HTML/LaTeX/PDF

Im Rest dieses Notebooks wird Plots.jl vorgestellt.

einige backends¶

In [1]:
using Plots
backend()      # Anzeige des gewählten backends, GR ist der default
Out[1]:
Plots.GRBackend()
In [2]:
x = 1:30
y = rand(30)
 
plot(x, y, linecolor =:green, bg_inside =:pink, line =:solid, label = "Wasserstand")
Out[2]:
In [3]:
# wir wechseln das backend zu 
# plotly/js


plotly()
┌ Info: For saving to png with the Plotly backend PlotlyBase has to be installed.
└ @ Plots /home/hellmund/.julia/packages/Plots/MzlNY/src/backends.jl:318
Out[3]:
Plots.PlotlyBackend()
In [4]:
# dasselbe Plot-Kommando

# das ist interaktiv (zoom in/out, pan), 
# 'überlebt' aber leider die PDF-Konvertierung des notebooks nicht

plot(x, y, linecolor =:green, bg_inside =:pink, line =:solid, label = "Wasserstand")
Out[4]:
In [5]:
# und noch ein backend

pyplot()
Out[5]:
Plots.PyPlotBackend()
In [6]:
plot(x, y, linecolor =:green, bg_inside =:pink, line =:solid, label = "Wasserstand")
Out[6]:
In [7]:
# zurück zu GR als backend

gr()
Out[7]:
Plots.GRBackend()

Plots.jl und recipes¶

Andere Pakete können die Möglichkeiten von Plots.jl erweitern, indem sie 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,...
  • GraphRecipes.jl Plotten von Graphstrukturen
  • ...

Einige Verschönerungen¶

In [8]:
using Plots.PlotMeasures   # für Angaben in mm, cm,...
using LaTeXStrings         # für LaTeX-Konstrukte in Plot-Beschriftungen
using PlotThemes           # vorgefertigte Themen
In [9]:
# Liste der Themen
keys(PlotThemes._themes)
Out[9]:
KeySet for a Dict{Symbol, PlotThemes.PlotTheme} with 18 entries. Keys:
  :juno
  :default
  :dao
  :ggplot2
  :gruvbox_dark
  :dark
  :gruvbox_light
  :solarized
  :wong
  :dracula
  :solarized_light
  :mute
  :wong2
  :sand
  :lime
  :bright
  :vibrant
  :orange
In [10]:
Plots.showtheme(:juno)
Out[10]:
In [11]:
Plots.showtheme(:dao)
Out[11]:
In [12]:
# so legt man ein Thema für die folgenden Plots fest:

theme(:dao)

# Wir wollen es wieder langweilig haben...

theme(:default)

Funktionen in Plots.jl¶

plot()
scatter()
contour()
heatmap()
histogram()
bar()
plot3d()
... und weitere

Diese Funktionen erzeugen ein neues Plot-Objekt.

Die Varianten mit Ausrufezeichen plot!(), scatter!(),... modifizieren das letzte Plot-Objekt oder das Plot-Objekt, das ihnen als 1. Argument übergeben wird:

In [13]:
x = range(0,10, length=40)   # 40 x-Werte von 0 bis 10

pl1 = plot(x, sin.(x))
Out[13]:
In [14]:
pl1a = deepcopy(pl1)  # unmodifizierte copy aufheben

pl2 = plot!(x, cos.(x))    # modifiziert pl1
Out[14]:
In [15]:
pl3 = scatter!(pl1a, x, cos.(x))   # add to (copy of) original Plot
Out[15]:

Plot-Objekte kann man als Grafikdateien (PDF, SVG, PNG,...) abspeichern:

In [16]:
savefig(pl2, "pl2.png")
In [17]:
;ls -l pl2.png
-rw-r--r-- 1 hellmund hellmund 30634 Jun 28 13:09 pl2.png

... oder zB als Sub-Plots mit einem layout-Parameter zusammenfügen:

In [18]:
plot(pl1, pl2, pl3, layout = (1,3))
Out[18]:
In [19]:
plot(pl1, pl2, pl3, layout = (3,1))
Out[19]:

Input-Daten¶

  • im einfachsten Fall ein Vektor von $m$ x-Werten und ein gleichlanger Vektor von $m$ y-Werten
  • falls $y$ eine $m\times n$-Matrix ist, wird jeder Spaltenvektor als eine Series angesehen und es werden $n$ Kurven geplottet:
In [20]:
plot(x, [sin.(x) cos.(x) sqrt.(x)])
Out[20]:
  • Durch eine layout-Angabe kann man die einzelnen series auch in einzelnen Subplots unterbringen.
  • Man kann layouts auch schachteln und explizite Breiten/Höhenangaben verwenden.
In [21]:
theme(:dark)

la1 = @layout [
        a{0.3w} [ b
                  c{0.2h}  ]
    ]

plot(x, [sin.(x) cos.(x) sqrt.(x)] , layout = la1)
Out[21]:

Plot-Attribute¶

Plots.jl teilt die Attribute in 4 Gruppen ein:

In [22]:
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
In [23]:
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, right_margin, subplot_index, title, titlefontcolor, titlefontfamily, titlefonthalign, titlefontrotation, titlefontsize, titlefontvalign, titlelocation, top_margin
In [24]:
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, widen
In [25]:
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
In [26]:
# Zur Erinnerung nochmal:

using Plots
using Plots.PlotMeasures   # für Angaben in mm, cm,...
using LaTeXStrings         # für LaTeX-Konstrukte in Plot-Beschriftungen
using PlotThemes           # vorgefertigte Themen
In [27]:
xs = range(0, 2π, length = 100)

data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)]

pl10 = plot(xs, data,
           fontfamily="Computer Modern",
    
           # LaTeX-String L""  ist im Math-mode  
           title = L"\textrm{Winkelfunktionen}\ \sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)",
           xlabel = L"\textrm{ Winkel\ } \alpha",
           ylabel = L"\textrm{Funktionswert}", 
    
           # 1x4-Matrizen mit Farben, Marker,...  für die 4 'Series' 
           color=[:black :green RGB(0.3, 0.8, 0.2) :blue ],
           markers = [:rect :circle :utriangle :diamond],
           markersize = [3 3 0 6],
           linewidth = [1 3 1 5],
           linestyle = [:solid :dash :dot :solid ],
           
           # Achsen
           xlim = (0, 6.6),
           ylim = (-2, 2.3),
           yticks = -2:.4:2.3,
           
           legend = :bottomleft,
           label = [ L"\sin(\alpha)" "cos" "2sin" L"\sin(\alpha^2)"],
    
           top_margin = 5mm,
)

# Zusatzelement

annotate!(pl10, 4.1, 1.8, text("nicht schön, aber viel",10))
Out[27]:

Säulendiagramm¶

In [28]:
using RDatasets

Inhalt: über 700 freie ("public domain") Datensätze, darunter z.B:

  • Passagierliste der Titanic
  • Verbrauchsdaten amerikanischer Autos aus den 70ern
  • historische Währungskurse
In [29]:
RDatasets.datasets()
Out[29]:

763 rows × 5 columns

PackageDatasetTitleRowsColumns
String15String31StringInt64Int64
1COUNTaffairsaffairs60118
2COUNTazdrg112azdrg11217984
3COUNTazproazpro35896
4COUNTbadhealthbadhealth11273
5COUNTfasttrakgfasttrakg159
6COUNTlbwlbw18910
7COUNTlbwgrplbwgrp67
8COUNTloomisloomis41011
9COUNTmdvismdvis222713
10COUNTmedparmedpar149510
11COUNTrwmrwm273264
12COUNTrwm5yrrwm5yr1960917
13COUNTshipsships407
14COUNTtitanictitanic13164
15COUNTtitanicgrptitanicgrp125
16EcdatAccidentShip Accidents405
17EcdatAirlineCost for U.S. Airlines906
18EcdatAirqAir Quality for Californian Metropolitan Areas306
19EcdatBenefitsUnemployement of Blue Collar Workers487718
20EcdatBidsBids Received By U.S. Firms12612
21EcdatBudgetFoodBudget Share of Food for Spanish Households239726
22EcdatBudgetItalyBudget Shares for Italian Households172911
23EcdatBudgetUKBudget Shares of British Households151910
24EcdatBwagesWages in Belgium14724
25EcdatCPSch3Earnings from the Current Population Survey111303
26EcdatCapmStock Market Data5165
27EcdatCarStated Preferences for Car Choice465470
28EcdatCaschoolThe California Test Score Data Set42017
29EcdatCatsupChoice of Brand for Catsup279814
30EcdatCigarCigarette Consumption13809
⋮⋮⋮⋮⋮⋮
In [30]:
cars = dataset("datasets", "mtcars")
Out[30]:

32 rows × 12 columns (omitted printing of 4 columns)

ModelMPGCylDispHPDRatWTQSec
String31Float64Int64Float64Int64Float64Float64Float64
1Mazda RX421.06160.01103.92.6216.46
2Mazda RX4 Wag21.06160.01103.92.87517.02
3Datsun 71022.84108.0933.852.3218.61
4Hornet 4 Drive21.46258.01103.083.21519.44
5Hornet Sportabout18.78360.01753.153.4417.02
6Valiant18.16225.01052.763.4620.22
7Duster 36014.38360.02453.213.5715.84
8Merc 240D24.44146.7623.693.1920.0
9Merc 23022.84140.8953.923.1522.9
10Merc 28019.26167.61233.923.4418.3
11Merc 280C17.86167.61233.923.4418.9
12Merc 450SE16.48275.81803.074.0717.4
13Merc 450SL17.38275.81803.073.7317.6
14Merc 450SLC15.28275.81803.073.7818.0
15Cadillac Fleetwood10.48472.02052.935.2517.98
16Lincoln Continental10.48460.02153.05.42417.82
17Chrysler Imperial14.78440.02303.235.34517.42
18Fiat 12832.4478.7664.082.219.47
19Honda Civic30.4475.7524.931.61518.52
20Toyota Corolla33.9471.1654.221.83519.9
21Toyota Corona21.54120.1973.72.46520.01
22Dodge Challenger15.58318.01502.763.5216.87
23AMC Javelin15.28304.01503.153.43517.3
24Camaro Z2813.38350.02453.733.8415.41
25Pontiac Firebird19.28400.01753.083.84517.05
26Fiat X1-927.3479.0664.081.93518.9
27Porsche 914-226.04120.3914.432.1416.7
28Lotus Europa30.4495.11133.771.51316.9
29Ford Pantera L15.88351.02644.223.1714.5
30Ferrari Dino19.76145.01753.622.7715.5
⋮⋮⋮⋮⋮⋮⋮⋮⋮
In [31]:
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
   )
Out[31]:
In [ ]: